Add fine-grained options for downloading widevine content

This commit is contained in:
Michael Bucari-Tovo 2025-05-01 13:03:03 -06:00
parent 1c336e1fe9
commit 1090d29f74
8 changed files with 202 additions and 112 deletions

View File

@ -33,81 +33,78 @@ public partial class DownloadOptions
private static async Task<ContentLicense> ChooseContent(Api api, LibraryBook libraryBook, Configuration config) private static async Task<ContentLicense> ChooseContent(Api api, LibraryBook libraryBook, Configuration config)
{ {
var cdm = await Cdm.GetCdmAsync();
var dlQuality = config.FileDownloadQuality == Configuration.DownloadQuality.Normal ? DownloadQuality.Normal : DownloadQuality.High; var dlQuality = config.FileDownloadQuality == Configuration.DownloadQuality.Normal ? DownloadQuality.Normal : DownloadQuality.High;
ContentLicense? contentLic = null; if (!config.UseWidevine || await Cdm.GetCdmAsync() is not Cdm cdm)
ContentLicense? fallback = null; return await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId, dlQuality);
if (cdm is null) ContentLicense? contentLic = null, fallback = null;
try
{ {
//Doesn't matter what the user chose. We can't get a CDM so we must fall back to AAX(C) //try to request a widevine content license using the user's spatial audio settings
contentLic = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId, dlQuality); var codecChoice = config.SpatialAudioCodec switch
{
Configuration.SpatialCodec.EC_3 => Ec3Codec,
Configuration.SpatialCodec.AC_4 => Ac4Codec,
_ => throw new NotSupportedException($"Unknown value for {nameof(config.SpatialAudioCodec)}")
};
contentLic
= await api.GetDownloadLicenseAsync(
libraryBook.Book.AudibleProductId,
dlQuality,
ChapterTitlesType.Tree,
DrmType.Widevine,
config.RequestSpatial,
codecChoice);
} }
else catch (Exception ex)
{ {
var spatial = config.FileDownloadQuality is Configuration.DownloadQuality.Spatial; Serilog.Log.Logger.Error(ex, "Failed to request a Widevine license.");
try //We failed to get a widevine license, so fall back to AAX(C)
{ return await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId, dlQuality);
var codecChoice = config.SpatialAudioCodec switch
{
Configuration.SpatialCodec.EC_3 => Ec3Codec,
Configuration.SpatialCodec.AC_4 => Ac4Codec,
_ => throw new NotSupportedException($"Unknown value for {nameof(config.SpatialAudioCodec)}")
};
contentLic = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId, dlQuality, ChapterTitlesType.Tree, DrmType.Widevine, spatial, codecChoice);
}
catch (Exception ex)
{
Serilog.Log.Logger.Error(ex, "Failed to request a Widevine license.");
}
if (contentLic is null)
{
//We failed to get a widevine license, so fall back to AAX(C)
contentLic = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId, dlQuality);
}
else if (!contentLic.ContentMetadata.ContentReference.IsSpatial && contentLic.DrmType != DrmType.Adrm)
{
/*
We got a widevine license and we have a Cdm, but we still need to decide if we WANT the file
being delivered with widevine. This file is not "spatial", so it may be no better than the
audio in the Adrm files. All else being equal, we prefer Adrm files because they have more
build-in metadata and always AAC-LC, which is a codec playable by pretty much every device
in existence.
Unfortunately, there appears to be no way to determine which codec/quality combination we'll
get until we make the request and see what content gets delivered. For some books,
Widevine/High delivers 44.1 kHz / 128 kbps audio and Adrm/High delivers 22.05 kHz / 64 kbps.
In those cases, the Widevine content size is much larger. Other books will deliver the same
sample rate / bitrate for both Widevine and Adrm, the only difference being codec. Widevine
is usually xHE-AAC, but is sometimes AAC-LC. Adrm is always AAC-LC.
To decide which file we want, use this simple rule: if files are different codecs and
Widevine is significantly larger, use Widevine. Otherwise use ADRM.
*/
fallback = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId, dlQuality);
var wvCr = contentLic.ContentMetadata.ContentReference;
var adrmCr = fallback.ContentMetadata.ContentReference;
if (wvCr.Codec == adrmCr.Codec ||
adrmCr.ContentSizeInBytes > wvCr.ContentSizeInBytes ||
RelativePercentDifference(adrmCr.ContentSizeInBytes, wvCr.ContentSizeInBytes) < 0.05)
{
contentLic = fallback;
}
}
} }
if (contentLic.DrmType == DrmType.Widevine && cdm is not null) if (!contentLic.ContentMetadata.ContentReference.IsSpatial && contentLic.DrmType != DrmType.Adrm)
{
/*
We got a widevine license and we have a Cdm, but we still need to decide if we WANT the file
being delivered with widevine. This file is not "spatial", so it may be no better than the
audio in the Adrm files. All else being equal, we prefer Adrm files because they have more
build-in metadata and always AAC-LC, which is a codec playable by pretty much every device
in existence.
Unfortunately, there appears to be no way to determine which codec/quality combination we'll
get until we make the request and see what content gets delivered. For some books,
Widevine/High delivers 44.1 kHz / 128 kbps audio and Adrm/High delivers 22.05 kHz / 64 kbps.
In those cases, the Widevine content size is much larger. Other books will deliver the same
sample rate / bitrate for both Widevine and Adrm, the only difference being codec. Widevine
is usually xHE-AAC, but is sometimes AAC-LC. Adrm is always AAC-LC.
To decide which file we want, use this simple rule: if files are different codecs and
Widevine is significantly larger, use Widevine. Otherwise use ADRM.
*/
fallback = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId, dlQuality);
var wvCr = contentLic.ContentMetadata.ContentReference;
var adrmCr = fallback.ContentMetadata.ContentReference;
if (wvCr.Codec == adrmCr.Codec ||
adrmCr.ContentSizeInBytes > wvCr.ContentSizeInBytes ||
RelativePercentDifference(adrmCr.ContentSizeInBytes, wvCr.ContentSizeInBytes) < 0.05)
{
contentLic = fallback;
}
}
if (contentLic.DrmType == DrmType.Widevine)
{ {
try try
{ {
using var client = new HttpClient(); using var client = new HttpClient();
var mpdResponse = await client.GetAsync(contentLic.LicenseResponse); using var mpdResponse = await client.GetAsync(contentLic.LicenseResponse);
var dash = new MpegDash(mpdResponse.Content.ReadAsStream()); var dash = new MpegDash(mpdResponse.Content.ReadAsStream());
if (!dash.TryGetUri(new Uri(contentLic.LicenseResponse), out var contentUri)) if (!dash.TryGetUri(new Uri(contentLic.LicenseResponse), out var contentUri))
@ -124,7 +121,6 @@ public partial class DownloadOptions
Key = Convert.ToHexStringLower(keys[0].Kid.ToByteArray()), Key = Convert.ToHexStringLower(keys[0].Kid.ToByteArray()),
Iv = Convert.ToHexStringLower(keys[0].Key) Iv = Convert.ToHexStringLower(keys[0].Key)
}; };
} }
catch catch
{ {

View File

@ -43,14 +43,40 @@
<controls:WheelComboBox <controls:WheelComboBox
Margin="5,0,0,0" Margin="5,0,0,0"
Grid.Column="1" Grid.Column="1"
SelectionChanged="Quality_SelectionChanged"
ItemsSource="{CompiledBinding DownloadQualities}" ItemsSource="{CompiledBinding DownloadQualities}"
SelectedItem="{CompiledBinding FileDownloadQuality}"/> SelectedItem="{CompiledBinding FileDownloadQuality}"/>
</Grid> </Grid>
<Grid ColumnDefinitions="*,Auto" Margin="0,5,0,0"
IsEnabled="{CompiledBinding SpatialSelected}" <Grid ColumnDefinitions="*,*">
<CheckBox
IsChecked="{CompiledBinding UseWidevine, Mode=TwoWay}"
IsCheckedChanged="UseWidevine_IsCheckedChanged"
ToolTip.Tip="{CompiledBinding UseWidevineTip}">
<TextBlock Text="{CompiledBinding UseWidevineText}" />
</CheckBox>
<CheckBox
Grid.Column="1"
HorizontalAlignment="Right"
ToolTip.Tip="{CompiledBinding RequestSpatialTip}"
IsEnabled="{CompiledBinding UseWidevine}"
IsChecked="{CompiledBinding RequestSpatial, Mode=TwoWay}">
<TextBlock Text="{CompiledBinding RequestSpatialText}" />
</CheckBox>
</Grid>
<Grid ColumnDefinitions="*,Auto"
ToolTip.Tip="{CompiledBinding SpatialAudioCodecTip}"> ToolTip.Tip="{CompiledBinding SpatialAudioCodecTip}">
<Grid.IsEnabled>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<MultiBinding.Bindings>
<CompiledBinding Path="UseWidevine"/>
<CompiledBinding Path="RequestSpatial"/>
</MultiBinding.Bindings>
</MultiBinding>
</Grid.IsEnabled>
<TextBlock <TextBlock
VerticalAlignment="Center" VerticalAlignment="Center"
@ -62,6 +88,11 @@
ItemsSource="{CompiledBinding SpatialAudioCodecs}" ItemsSource="{CompiledBinding SpatialAudioCodecs}"
SelectedItem="{CompiledBinding SpatialAudioCodec}"/> SelectedItem="{CompiledBinding SpatialAudioCodec}"/>
</Grid> </Grid>
<CheckBox IsChecked="{CompiledBinding CreateCueSheet, Mode=TwoWay}"> <CheckBox IsChecked="{CompiledBinding CreateCueSheet, Mode=TwoWay}">
<TextBlock Text="{CompiledBinding CreateCueSheetText}" /> <TextBlock Text="{CompiledBinding CreateCueSheetText}" />

View File

@ -22,21 +22,21 @@ namespace LibationAvalonia.Controls.Settings
} }
} }
private async void UseWidevine_IsCheckedChanged(object sender, Avalonia.Interactivity.RoutedEventArgs e)
public async void Quality_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
if (_viewModel.SpatialSelected) if (sender is CheckBox cbox && cbox.IsChecked is true)
{ {
using var accounts = AudibleApiStorage.GetAccountsSettingsPersister(); using var accounts = AudibleApiStorage.GetAccountsSettingsPersister();
if (!accounts.AccountsSettings.Accounts.Any(a => a.IdentityTokens.DeviceType == AudibleApi.Resources.DeviceType)) if (!accounts.AccountsSettings.Accounts.Any(a => a.IdentityTokens.DeviceType == AudibleApi.Resources.DeviceType))
{ {
await MessageBox.Show(VisualRoot as Window, if (VisualRoot is Window parent)
"Your must remove account(s) from Libation and then re-add them to enable spatial audiobook downloads.", await MessageBox.Show(parent,
"Spatial Audio Unavailable", "Your must remove account(s) from Libation and then re-add them to enable widwvine content.",
"Widevine Content Unavailable",
MessageBoxButtons.OK); MessageBoxButtons.OK);
_viewModel.FileDownloadQuality = _viewModel.DownloadQualities[1]; _viewModel.UseWidevine = false;
} }
} }
} }

View File

@ -67,6 +67,8 @@ namespace LibationAvalonia.ViewModels.Settings
FileDownloadQuality = DownloadQualities.SingleOrDefault(s => s.Value == config.FileDownloadQuality) ?? DownloadQualities[0]; FileDownloadQuality = DownloadQualities.SingleOrDefault(s => s.Value == config.FileDownloadQuality) ?? DownloadQualities[0];
SelectedSampleRate = SampleRates.SingleOrDefault(s => s.Value == config.MaxSampleRate) ?? SampleRates[0]; SelectedSampleRate = SampleRates.SingleOrDefault(s => s.Value == config.MaxSampleRate) ?? SampleRates[0];
SelectedEncoderQuality = config.LameEncoderQuality; SelectedEncoderQuality = config.LameEncoderQuality;
UseWidevine = config.UseWidevine;
RequestSpatial = config.RequestSpatial;
} }
public void SaveSettings(Configuration config) public void SaveSettings(Configuration config)
@ -96,12 +98,13 @@ namespace LibationAvalonia.ViewModels.Settings
config.MaxSampleRate = SelectedSampleRate?.Value ?? config.MaxSampleRate; config.MaxSampleRate = SelectedSampleRate?.Value ?? config.MaxSampleRate;
config.FileDownloadQuality = FileDownloadQuality?.Value ?? config.FileDownloadQuality; config.FileDownloadQuality = FileDownloadQuality?.Value ?? config.FileDownloadQuality;
config.SpatialAudioCodec = SpatialAudioCodec?.Value ?? config.SpatialAudioCodec; config.SpatialAudioCodec = SpatialAudioCodec?.Value ?? config.SpatialAudioCodec;
config.UseWidevine = UseWidevine;
config.RequestSpatial = RequestSpatial;
} }
public AvaloniaList<EnumDisplay<Configuration.DownloadQuality>> DownloadQualities { get; } = new([ public AvaloniaList<EnumDisplay<Configuration.DownloadQuality>> DownloadQualities { get; } = new([
new EnumDisplay<Configuration.DownloadQuality>(Configuration.DownloadQuality.Normal), new EnumDisplay<Configuration.DownloadQuality>(Configuration.DownloadQuality.Normal),
new EnumDisplay<Configuration.DownloadQuality>(Configuration.DownloadQuality.High), new EnumDisplay<Configuration.DownloadQuality>(Configuration.DownloadQuality.High),
new EnumDisplay<Configuration.DownloadQuality>(Configuration.DownloadQuality.Spatial, "Spatial (if available)"),
]); ]);
public AvaloniaList<EnumDisplay<Configuration.SpatialCodec>> SpatialAudioCodecs { get; } = new([ public AvaloniaList<EnumDisplay<Configuration.SpatialCodec>> SpatialAudioCodecs { get; } = new([
new EnumDisplay<Configuration.SpatialCodec>(Configuration.SpatialCodec.EC_3, "Dolby Digital Plus (E-AC-3)"), new EnumDisplay<Configuration.SpatialCodec>(Configuration.SpatialCodec.EC_3, "Dolby Digital Plus (E-AC-3)"),
@ -109,6 +112,10 @@ namespace LibationAvalonia.ViewModels.Settings
]); ]);
public AvaloniaList<Configuration.ClipBookmarkFormat> ClipBookmarkFormats { get; } = new(Enum<Configuration.ClipBookmarkFormat>.GetValues()); public AvaloniaList<Configuration.ClipBookmarkFormat> ClipBookmarkFormats { get; } = new(Enum<Configuration.ClipBookmarkFormat>.GetValues());
public string FileDownloadQualityText { get; } = Configuration.GetDescription(nameof(Configuration.FileDownloadQuality)); public string FileDownloadQualityText { get; } = Configuration.GetDescription(nameof(Configuration.FileDownloadQuality));
public string UseWidevineText { get; } = Configuration.GetDescription(nameof(Configuration.UseWidevine));
public string UseWidevineTip { get; } = Configuration.GetHelpText(nameof(Configuration.UseWidevine));
public string RequestSpatialText { get; } = Configuration.GetDescription(nameof(Configuration.RequestSpatial));
public string RequestSpatialTip { get; } = Configuration.GetHelpText(nameof(Configuration.RequestSpatial));
public string SpatialAudioCodecText { get; } = Configuration.GetDescription(nameof(Configuration.SpatialAudioCodec)); public string SpatialAudioCodecText { get; } = Configuration.GetDescription(nameof(Configuration.SpatialAudioCodec));
public string SpatialAudioCodecTip { get; } = Configuration.GetHelpText(nameof(Configuration.SpatialAudioCodec)); public string SpatialAudioCodecTip { get; } = Configuration.GetHelpText(nameof(Configuration.SpatialAudioCodec));
public string CreateCueSheetText { get; } = Configuration.GetDescription(nameof(Configuration.CreateCueSheet)); public string CreateCueSheetText { get; } = Configuration.GetDescription(nameof(Configuration.CreateCueSheet));
@ -133,19 +140,13 @@ namespace LibationAvalonia.ViewModels.Settings
public string RetainAaxFileTip => Configuration.GetHelpText(nameof(RetainAaxFile)); public string RetainAaxFileTip => Configuration.GetHelpText(nameof(RetainAaxFile));
public bool DownloadClipsBookmarks { get => _downloadClipsBookmarks; set => this.RaiseAndSetIfChanged(ref _downloadClipsBookmarks, value); } public bool DownloadClipsBookmarks { get => _downloadClipsBookmarks; set => this.RaiseAndSetIfChanged(ref _downloadClipsBookmarks, value); }
public bool SpatialSelected { get; private set; }
private EnumDisplay<Configuration.DownloadQuality>? _fileDownloadQuality; private bool _useWidevine;
public EnumDisplay<Configuration.DownloadQuality> FileDownloadQuality private bool _requestSpatial;
{ public bool UseWidevine { get => _useWidevine; set => this.RaiseAndSetIfChanged(ref _useWidevine, value); }
get => _fileDownloadQuality ?? DownloadQualities[0]; public bool RequestSpatial { get => _requestSpatial; set => this.RaiseAndSetIfChanged(ref _requestSpatial, value); }
set
{ public EnumDisplay<Configuration.DownloadQuality> FileDownloadQuality { get; set; }
SpatialSelected = value?.Value == Configuration.DownloadQuality.Spatial;
this.RaiseAndSetIfChanged(ref _fileDownloadQuality, value);
this.RaisePropertyChanged(nameof(SpatialSelected));
}
}
public EnumDisplay<Configuration.SpatialCodec> SpatialAudioCodec { get; set; } public EnumDisplay<Configuration.SpatialCodec> SpatialAudioCodec { get; set; }
public Configuration.ClipBookmarkFormat ClipBookmarkFormat { get; set; } public Configuration.ClipBookmarkFormat ClipBookmarkFormat { get; set; }
public bool MergeOpeningAndEndCredits { get; set; } public bool MergeOpeningAndEndCredits { get; set; }

View File

@ -89,6 +89,24 @@ namespace LibationFileManager
AC-4 cannot be converted to MP3. AC-4 cannot be converted to MP3.
""" }, """ },
{nameof(UseWidevine), """
Some audiobooks are only delivered in the highest
available quality with special, third-party content
protection. Enabling this option will make Libation
request audiobooks with Widevine DRM, which may
yield higher quality audiobook files. If they are
higher quality, however, they will also be encoded
with a somewhat uncommon codec (xHE-AAC USAC)
which you may have difficulty playing.
This must be enable to download spatial audiobooks.
""" },
{nameof(RequestSpatial), """
If selected, Libation will request audiobooks in the
Dolby Atmos 'Spatial Audio' format. Audiobooks which
don't have a spatial audio version will be download
as usual based on your other file quality settings.
""" },
} }
.AsReadOnly(); .AsReadOnly();

View File

@ -246,8 +246,7 @@ namespace LibationFileManager
public enum DownloadQuality public enum DownloadQuality
{ {
High, High,
Normal, Normal
Spatial
} }
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(StringEnumConverter))]
@ -257,6 +256,12 @@ namespace LibationFileManager
AC_4 AC_4
} }
[Description("Use widevine DRM")]
public bool UseWidevine { get => GetNonString(defaultValue: true); set => SetNonString(value); }
[Description("Request Spatial Audio")]
public bool RequestSpatial { get => GetNonString(defaultValue: true); set => SetNonString(value); }
[Description("Spatial audio codec:")] [Description("Spatial audio codec:")]
public SpatialCodec SpatialAudioCodec { get => GetNonString(defaultValue: SpatialCodec.EC_3); set => SetNonString(value); } public SpatialCodec SpatialAudioCodec { get => GetNonString(defaultValue: SpatialCodec.EC_3); set => SetNonString(value); }

View File

@ -23,6 +23,8 @@ namespace LibationWinForms.Dialogs
this.stripAudibleBrandingCbox.Text = desc(nameof(config.StripAudibleBrandAudio)); this.stripAudibleBrandingCbox.Text = desc(nameof(config.StripAudibleBrandAudio));
this.stripUnabridgedCbox.Text = desc(nameof(config.StripUnabridged)); this.stripUnabridgedCbox.Text = desc(nameof(config.StripUnabridged));
this.moveMoovAtomCbox.Text = desc(nameof(config.MoveMoovToBeginning)); this.moveMoovAtomCbox.Text = desc(nameof(config.MoveMoovToBeginning));
this.useWidevineCbox.Text = desc(nameof(config.UseWidevine));
this.requestSpatialCbox.Text = desc(nameof(config.RequestSpatial));
this.spatialCodecLbl.Text = desc(nameof(config.SpatialAudioCodec)); this.spatialCodecLbl.Text = desc(nameof(config.SpatialAudioCodec));
toolTip.SetToolTip(combineNestedChapterTitlesCbox, Configuration.GetHelpText(nameof(config.CombineNestedChapterTitles))); toolTip.SetToolTip(combineNestedChapterTitlesCbox, Configuration.GetHelpText(nameof(config.CombineNestedChapterTitles)));
@ -34,6 +36,8 @@ namespace LibationWinForms.Dialogs
toolTip.SetToolTip(mergeOpeningEndCreditsCbox, Configuration.GetHelpText(nameof(config.MergeOpeningAndEndCredits))); toolTip.SetToolTip(mergeOpeningEndCreditsCbox, Configuration.GetHelpText(nameof(config.MergeOpeningAndEndCredits)));
toolTip.SetToolTip(retainAaxFileCbox, Configuration.GetHelpText(nameof(config.RetainAaxFile))); toolTip.SetToolTip(retainAaxFileCbox, Configuration.GetHelpText(nameof(config.RetainAaxFile)));
toolTip.SetToolTip(stripAudibleBrandingCbox, Configuration.GetHelpText(nameof(config.StripAudibleBrandAudio))); toolTip.SetToolTip(stripAudibleBrandingCbox, Configuration.GetHelpText(nameof(config.StripAudibleBrandAudio)));
toolTip.SetToolTip(useWidevineCbox, Configuration.GetHelpText(nameof(config.UseWidevine)));
toolTip.SetToolTip(requestSpatialCbox, Configuration.GetHelpText(nameof(config.RequestSpatial)));
toolTip.SetToolTip(spatialCodecLbl, Configuration.GetHelpText(nameof(config.SpatialAudioCodec))); toolTip.SetToolTip(spatialCodecLbl, Configuration.GetHelpText(nameof(config.SpatialAudioCodec)));
toolTip.SetToolTip(spatialAudioCodecCb, Configuration.GetHelpText(nameof(config.SpatialAudioCodec))); toolTip.SetToolTip(spatialAudioCodecCb, Configuration.GetHelpText(nameof(config.SpatialAudioCodec)));
@ -41,7 +45,6 @@ namespace LibationWinForms.Dialogs
[ [
new EnumDisplay<Configuration.DownloadQuality>(Configuration.DownloadQuality.Normal), new EnumDisplay<Configuration.DownloadQuality>(Configuration.DownloadQuality.Normal),
new EnumDisplay<Configuration.DownloadQuality>(Configuration.DownloadQuality.High), new EnumDisplay<Configuration.DownloadQuality>(Configuration.DownloadQuality.High),
new EnumDisplay<Configuration.DownloadQuality>(Configuration.DownloadQuality.Spatial, "Spatial (if available)"),
]); ]);
spatialAudioCodecCb.Items.AddRange( spatialAudioCodecCb.Items.AddRange(
@ -76,6 +79,8 @@ namespace LibationWinForms.Dialogs
downloadClipsBookmarksCbox.Checked = config.DownloadClipsBookmarks; downloadClipsBookmarksCbox.Checked = config.DownloadClipsBookmarks;
fileDownloadQualityCb.SelectedItem = config.FileDownloadQuality; fileDownloadQualityCb.SelectedItem = config.FileDownloadQuality;
spatialAudioCodecCb.SelectedItem = config.SpatialAudioCodec; spatialAudioCodecCb.SelectedItem = config.SpatialAudioCodec;
useWidevineCbox.Checked = config.UseWidevine;
requestSpatialCbox.Checked = config.RequestSpatial;
clipsBookmarksFormatCb.SelectedItem = config.ClipsBookmarksFileFormat; clipsBookmarksFormatCb.SelectedItem = config.ClipsBookmarksFileFormat;
retainAaxFileCbox.Checked = config.RetainAaxFile; retainAaxFileCbox.Checked = config.RetainAaxFile;
@ -118,6 +123,8 @@ namespace LibationWinForms.Dialogs
config.DownloadCoverArt = downloadCoverArtCbox.Checked; config.DownloadCoverArt = downloadCoverArtCbox.Checked;
config.DownloadClipsBookmarks = downloadClipsBookmarksCbox.Checked; config.DownloadClipsBookmarks = downloadClipsBookmarksCbox.Checked;
config.FileDownloadQuality = ((EnumDisplay<Configuration.DownloadQuality>)fileDownloadQualityCb.SelectedItem).Value; config.FileDownloadQuality = ((EnumDisplay<Configuration.DownloadQuality>)fileDownloadQualityCb.SelectedItem).Value;
config.UseWidevine = useWidevineCbox.Checked;
config.RequestSpatial = requestSpatialCbox.Checked;
config.SpatialAudioCodec = ((EnumDisplay<Configuration.SpatialCodec>)spatialAudioCodecCb.SelectedItem).Value; config.SpatialAudioCodec = ((EnumDisplay<Configuration.SpatialCodec>)spatialAudioCodecCb.SelectedItem).Value;
config.ClipsBookmarksFileFormat = (Configuration.ClipBookmarkFormat)clipsBookmarksFormatCb.SelectedItem; config.ClipsBookmarksFileFormat = (Configuration.ClipBookmarkFormat)clipsBookmarksFormatCb.SelectedItem;
config.RetainAaxFile = retainAaxFileCbox.Checked; config.RetainAaxFile = retainAaxFileCbox.Checked;
@ -140,7 +147,6 @@ namespace LibationWinForms.Dialogs
config.ChapterTitleTemplate = chapterTitleTemplateTb.Text; config.ChapterTitleTemplate = chapterTitleTemplateTb.Text;
} }
private void downloadClipsBookmarksCbox_CheckedChanged(object sender, EventArgs e) private void downloadClipsBookmarksCbox_CheckedChanged(object sender, EventArgs e)
{ {
clipsBookmarksFormatCb.Enabled = downloadClipsBookmarksCbox.Checked; clipsBookmarksFormatCb.Enabled = downloadClipsBookmarksCbox.Checked;
@ -190,27 +196,28 @@ namespace LibationWinForms.Dialogs
} }
} }
private void fileDownloadQualityCb_SelectedIndexChanged(object sender, EventArgs e)
{
var selectedSpatial = fileDownloadQualityCb.SelectedItem.Equals(Configuration.DownloadQuality.Spatial);
if (selectedSpatial)
private void useWidevineCbox_CheckedChanged(object sender, EventArgs e)
{
if (useWidevineCbox.Checked)
{ {
using var accounts = AudibleApiStorage.GetAccountsSettingsPersister(); using var accounts = AudibleApiStorage.GetAccountsSettingsPersister();
if (!accounts.AccountsSettings.Accounts.Any(a => a.IdentityTokens.DeviceType == AudibleApi.Resources.DeviceType)) if (!accounts.AccountsSettings.Accounts.Any(a => a.IdentityTokens.DeviceType == AudibleApi.Resources.DeviceType))
{ {
MessageBox.Show(this, MessageBox.Show(this,
"Your must remove account(s) from Libation and then re-add them to enable spatial audiobook downloads.", "Your must remove account(s) from Libation and then re-add them to enable widwvine content.",
"Spatial Audio Unavailable", "Widevine Content Unavailable",
MessageBoxButtons.OK); MessageBoxButtons.OK);
fileDownloadQualityCb.SelectedItem = Configuration.DownloadQuality.High; useWidevineCbox.Checked = false;
return; return;
} }
} }
requestSpatialCbox.Enabled = useWidevineCbox.Checked;
spatialCodecLbl.Enabled = spatialAudioCodecCb.Enabled = selectedSpatial; spatialCodecLbl.Enabled = spatialAudioCodecCb.Enabled = useWidevineCbox.Checked && requestSpatialCbox.Checked;
} }
} }
} }

View File

@ -84,6 +84,8 @@
folderTemplateTb = new System.Windows.Forms.TextBox(); folderTemplateTb = new System.Windows.Forms.TextBox();
folderTemplateLbl = new System.Windows.Forms.Label(); folderTemplateLbl = new System.Windows.Forms.Label();
tab4AudioFileOptions = new System.Windows.Forms.TabPage(); tab4AudioFileOptions = new System.Windows.Forms.TabPage();
requestSpatialCbox = new System.Windows.Forms.CheckBox();
useWidevineCbox = new System.Windows.Forms.CheckBox();
spatialAudioCodecCb = new System.Windows.Forms.ComboBox(); spatialAudioCodecCb = new System.Windows.Forms.ComboBox();
spatialCodecLbl = new System.Windows.Forms.Label(); spatialCodecLbl = new System.Windows.Forms.Label();
moveMoovAtomCbox = new System.Windows.Forms.CheckBox(); moveMoovAtomCbox = new System.Windows.Forms.CheckBox();
@ -306,7 +308,7 @@
allowLibationFixupCbox.AutoSize = true; allowLibationFixupCbox.AutoSize = true;
allowLibationFixupCbox.Checked = true; allowLibationFixupCbox.Checked = true;
allowLibationFixupCbox.CheckState = System.Windows.Forms.CheckState.Checked; allowLibationFixupCbox.CheckState = System.Windows.Forms.CheckState.Checked;
allowLibationFixupCbox.Location = new System.Drawing.Point(19, 205); allowLibationFixupCbox.Location = new System.Drawing.Point(19, 230);
allowLibationFixupCbox.Name = "allowLibationFixupCbox"; allowLibationFixupCbox.Name = "allowLibationFixupCbox";
allowLibationFixupCbox.Size = new System.Drawing.Size(162, 19); allowLibationFixupCbox.Size = new System.Drawing.Size(162, 19);
allowLibationFixupCbox.TabIndex = 11; allowLibationFixupCbox.TabIndex = 11;
@ -772,6 +774,8 @@
// tab4AudioFileOptions // tab4AudioFileOptions
// //
tab4AudioFileOptions.AutoScroll = true; tab4AudioFileOptions.AutoScroll = true;
tab4AudioFileOptions.Controls.Add(requestSpatialCbox);
tab4AudioFileOptions.Controls.Add(useWidevineCbox);
tab4AudioFileOptions.Controls.Add(spatialAudioCodecCb); tab4AudioFileOptions.Controls.Add(spatialAudioCodecCb);
tab4AudioFileOptions.Controls.Add(spatialCodecLbl); tab4AudioFileOptions.Controls.Add(spatialCodecLbl);
tab4AudioFileOptions.Controls.Add(moveMoovAtomCbox); tab4AudioFileOptions.Controls.Add(moveMoovAtomCbox);
@ -798,11 +802,38 @@
tab4AudioFileOptions.Text = "Audio File Options"; tab4AudioFileOptions.Text = "Audio File Options";
tab4AudioFileOptions.UseVisualStyleBackColor = true; tab4AudioFileOptions.UseVisualStyleBackColor = true;
// //
// requestSpatialCbox
//
requestSpatialCbox.AutoSize = true;
requestSpatialCbox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
requestSpatialCbox.Checked = true;
requestSpatialCbox.CheckState = System.Windows.Forms.CheckState.Checked;
requestSpatialCbox.Location = new System.Drawing.Point(284, 35);
requestSpatialCbox.Name = "requestSpatialCbox";
requestSpatialCbox.Size = new System.Drawing.Size(138, 19);
requestSpatialCbox.TabIndex = 29;
requestSpatialCbox.Text = "[RequestSpatial desc]";
requestSpatialCbox.UseVisualStyleBackColor = true;
requestSpatialCbox.CheckedChanged += useWidevineCbox_CheckedChanged;
//
// useWidevineCbox
//
useWidevineCbox.AutoSize = true;
useWidevineCbox.Checked = true;
useWidevineCbox.CheckState = System.Windows.Forms.CheckState.Checked;
useWidevineCbox.Location = new System.Drawing.Point(19, 35);
useWidevineCbox.Name = "useWidevineCbox";
useWidevineCbox.Size = new System.Drawing.Size(129, 19);
useWidevineCbox.TabIndex = 28;
useWidevineCbox.Text = "[UseWidevine desc]";
useWidevineCbox.UseVisualStyleBackColor = true;
useWidevineCbox.CheckedChanged += useWidevineCbox_CheckedChanged;
//
// spatialAudioCodecCb // spatialAudioCodecCb
// //
spatialAudioCodecCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; spatialAudioCodecCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
spatialAudioCodecCb.FormattingEnabled = true; spatialAudioCodecCb.FormattingEnabled = true;
spatialAudioCodecCb.Location = new System.Drawing.Point(249, 35); spatialAudioCodecCb.Location = new System.Drawing.Point(249, 60);
spatialAudioCodecCb.Margin = new System.Windows.Forms.Padding(3, 3, 5, 3); spatialAudioCodecCb.Margin = new System.Windows.Forms.Padding(3, 3, 5, 3);
spatialAudioCodecCb.Name = "spatialAudioCodecCb"; spatialAudioCodecCb.Name = "spatialAudioCodecCb";
spatialAudioCodecCb.Size = new System.Drawing.Size(173, 23); spatialAudioCodecCb.Size = new System.Drawing.Size(173, 23);
@ -811,7 +842,7 @@
// spatialCodecLbl // spatialCodecLbl
// //
spatialCodecLbl.AutoSize = true; spatialCodecLbl.AutoSize = true;
spatialCodecLbl.Location = new System.Drawing.Point(19, 37); spatialCodecLbl.Location = new System.Drawing.Point(19, 62);
spatialCodecLbl.Name = "spatialCodecLbl"; spatialCodecLbl.Name = "spatialCodecLbl";
spatialCodecLbl.Size = new System.Drawing.Size(143, 15); spatialCodecLbl.Size = new System.Drawing.Size(143, 15);
spatialCodecLbl.TabIndex = 24; spatialCodecLbl.TabIndex = 24;
@ -836,7 +867,6 @@
fileDownloadQualityCb.Name = "fileDownloadQualityCb"; fileDownloadQualityCb.Name = "fileDownloadQualityCb";
fileDownloadQualityCb.Size = new System.Drawing.Size(130, 23); fileDownloadQualityCb.Size = new System.Drawing.Size(130, 23);
fileDownloadQualityCb.TabIndex = 1; fileDownloadQualityCb.TabIndex = 1;
fileDownloadQualityCb.SelectedIndexChanged += fileDownloadQualityCb_SelectedIndexChanged;
// //
// fileDownloadQualityLbl // fileDownloadQualityLbl
// //
@ -851,7 +881,7 @@
// combineNestedChapterTitlesCbox // combineNestedChapterTitlesCbox
// //
combineNestedChapterTitlesCbox.AutoSize = true; combineNestedChapterTitlesCbox.AutoSize = true;
combineNestedChapterTitlesCbox.Location = new System.Drawing.Point(19, 181); combineNestedChapterTitlesCbox.Location = new System.Drawing.Point(19, 206);
combineNestedChapterTitlesCbox.Name = "combineNestedChapterTitlesCbox"; combineNestedChapterTitlesCbox.Name = "combineNestedChapterTitlesCbox";
combineNestedChapterTitlesCbox.Size = new System.Drawing.Size(217, 19); combineNestedChapterTitlesCbox.Size = new System.Drawing.Size(217, 19);
combineNestedChapterTitlesCbox.TabIndex = 10; combineNestedChapterTitlesCbox.TabIndex = 10;
@ -862,7 +892,7 @@
// //
clipsBookmarksFormatCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; clipsBookmarksFormatCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
clipsBookmarksFormatCb.FormattingEnabled = true; clipsBookmarksFormatCb.FormattingEnabled = true;
clipsBookmarksFormatCb.Location = new System.Drawing.Point(285, 107); clipsBookmarksFormatCb.Location = new System.Drawing.Point(285, 132);
clipsBookmarksFormatCb.Name = "clipsBookmarksFormatCb"; clipsBookmarksFormatCb.Name = "clipsBookmarksFormatCb";
clipsBookmarksFormatCb.Size = new System.Drawing.Size(67, 23); clipsBookmarksFormatCb.Size = new System.Drawing.Size(67, 23);
clipsBookmarksFormatCb.TabIndex = 6; clipsBookmarksFormatCb.TabIndex = 6;
@ -870,7 +900,7 @@
// downloadClipsBookmarksCbox // downloadClipsBookmarksCbox
// //
downloadClipsBookmarksCbox.AutoSize = true; downloadClipsBookmarksCbox.AutoSize = true;
downloadClipsBookmarksCbox.Location = new System.Drawing.Point(19, 109); downloadClipsBookmarksCbox.Location = new System.Drawing.Point(19, 134);
downloadClipsBookmarksCbox.Name = "downloadClipsBookmarksCbox"; downloadClipsBookmarksCbox.Name = "downloadClipsBookmarksCbox";
downloadClipsBookmarksCbox.Size = new System.Drawing.Size(248, 19); downloadClipsBookmarksCbox.Size = new System.Drawing.Size(248, 19);
downloadClipsBookmarksCbox.TabIndex = 5; downloadClipsBookmarksCbox.TabIndex = 5;
@ -883,7 +913,7 @@
audiobookFixupsGb.Controls.Add(splitFilesByChapterCbox); audiobookFixupsGb.Controls.Add(splitFilesByChapterCbox);
audiobookFixupsGb.Controls.Add(stripUnabridgedCbox); audiobookFixupsGb.Controls.Add(stripUnabridgedCbox);
audiobookFixupsGb.Controls.Add(stripAudibleBrandingCbox); audiobookFixupsGb.Controls.Add(stripAudibleBrandingCbox);
audiobookFixupsGb.Location = new System.Drawing.Point(6, 229); audiobookFixupsGb.Location = new System.Drawing.Point(6, 254);
audiobookFixupsGb.Name = "audiobookFixupsGb"; audiobookFixupsGb.Name = "audiobookFixupsGb";
audiobookFixupsGb.Size = new System.Drawing.Size(416, 114); audiobookFixupsGb.Size = new System.Drawing.Size(416, 114);
audiobookFixupsGb.TabIndex = 19; audiobookFixupsGb.TabIndex = 19;
@ -1324,7 +1354,7 @@
// mergeOpeningEndCreditsCbox // mergeOpeningEndCreditsCbox
// //
mergeOpeningEndCreditsCbox.AutoSize = true; mergeOpeningEndCreditsCbox.AutoSize = true;
mergeOpeningEndCreditsCbox.Location = new System.Drawing.Point(19, 157); mergeOpeningEndCreditsCbox.Location = new System.Drawing.Point(19, 182);
mergeOpeningEndCreditsCbox.Name = "mergeOpeningEndCreditsCbox"; mergeOpeningEndCreditsCbox.Name = "mergeOpeningEndCreditsCbox";
mergeOpeningEndCreditsCbox.Size = new System.Drawing.Size(198, 19); mergeOpeningEndCreditsCbox.Size = new System.Drawing.Size(198, 19);
mergeOpeningEndCreditsCbox.TabIndex = 9; mergeOpeningEndCreditsCbox.TabIndex = 9;
@ -1334,7 +1364,7 @@
// retainAaxFileCbox // retainAaxFileCbox
// //
retainAaxFileCbox.AutoSize = true; retainAaxFileCbox.AutoSize = true;
retainAaxFileCbox.Location = new System.Drawing.Point(19, 133); retainAaxFileCbox.Location = new System.Drawing.Point(19, 158);
retainAaxFileCbox.Name = "retainAaxFileCbox"; retainAaxFileCbox.Name = "retainAaxFileCbox";
retainAaxFileCbox.Size = new System.Drawing.Size(131, 19); retainAaxFileCbox.Size = new System.Drawing.Size(131, 19);
retainAaxFileCbox.TabIndex = 8; retainAaxFileCbox.TabIndex = 8;
@ -1347,7 +1377,7 @@
downloadCoverArtCbox.AutoSize = true; downloadCoverArtCbox.AutoSize = true;
downloadCoverArtCbox.Checked = true; downloadCoverArtCbox.Checked = true;
downloadCoverArtCbox.CheckState = System.Windows.Forms.CheckState.Checked; downloadCoverArtCbox.CheckState = System.Windows.Forms.CheckState.Checked;
downloadCoverArtCbox.Location = new System.Drawing.Point(19, 85); downloadCoverArtCbox.Location = new System.Drawing.Point(19, 110);
downloadCoverArtCbox.Name = "downloadCoverArtCbox"; downloadCoverArtCbox.Name = "downloadCoverArtCbox";
downloadCoverArtCbox.Size = new System.Drawing.Size(162, 19); downloadCoverArtCbox.Size = new System.Drawing.Size(162, 19);
downloadCoverArtCbox.TabIndex = 4; downloadCoverArtCbox.TabIndex = 4;
@ -1360,7 +1390,7 @@
createCueSheetCbox.AutoSize = true; createCueSheetCbox.AutoSize = true;
createCueSheetCbox.Checked = true; createCueSheetCbox.Checked = true;
createCueSheetCbox.CheckState = System.Windows.Forms.CheckState.Checked; createCueSheetCbox.CheckState = System.Windows.Forms.CheckState.Checked;
createCueSheetCbox.Location = new System.Drawing.Point(19, 61); createCueSheetCbox.Location = new System.Drawing.Point(19, 86);
createCueSheetCbox.Name = "createCueSheetCbox"; createCueSheetCbox.Name = "createCueSheetCbox";
createCueSheetCbox.Size = new System.Drawing.Size(145, 19); createCueSheetCbox.Size = new System.Drawing.Size(145, 19);
createCueSheetCbox.TabIndex = 3; createCueSheetCbox.TabIndex = 3;
@ -1531,5 +1561,7 @@
private System.Windows.Forms.Button applyDisplaySettingsBtn; private System.Windows.Forms.Button applyDisplaySettingsBtn;
private System.Windows.Forms.ComboBox spatialAudioCodecCb; private System.Windows.Forms.ComboBox spatialAudioCodecCb;
private System.Windows.Forms.Label spatialCodecLbl; private System.Windows.Forms.Label spatialCodecLbl;
private System.Windows.Forms.CheckBox useWidevineCbox;
private System.Windows.Forms.CheckBox requestSpatialCbox;
} }
} }