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

Add PublishingDate Field #364

Merged
merged 15 commits into from
Oct 18, 2023
Merged
9 changes: 8 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
# Auto detect text files and perform LF normalization
* text=auto
* text eol=lf
*.csproj eol=crlf
*.sln eol=crlf
*.png binary
*.jpg binary
*.ico binary
*.pdf binary
*.exe binary
# Exclude Docs From Stats
NickvisionTagger.Shared/Docs/** linguist-documentation
18 changes: 18 additions & 0 deletions NickvisionTagger.GNOME/Blueprints/window.blp
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,24 @@ Adw.ApplicationWindow _root {
Adw.EntryRow _publisherRow {
title: _("Publisher");
}

Adw.ActionRow {
title: _("Publishing Date");
activatable-widget: _publishingDateButton;

[suffix]
Gtk.MenuButton _publishingDateButton {
valign: center;
direction: none;
popover: Gtk.Popover {
Gtk.Calendar _publishingDateCalendar {
name: "calendarPublishingDate";
}
};

styles ["calendar-button"]
}
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion NickvisionTagger.GNOME/NickvisionTagger.GNOME.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<ItemGroup>
<PackageReference Include="GirCore.Adw-1" Version="0.4.0" />
<PackageReference Include="Nickvision.Aura" Version="2023.10.1.1" />
<PackageReference Include="Nickvision.Aura" Version="2023.10.1.3" />
<PackageReference Include="Nickvision.GirExt" Version="2023.7.3" />
</ItemGroup>

Expand Down
1 change: 1 addition & 0 deletions NickvisionTagger.GNOME/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public Program(string[] args)
_mainWindowController = new MainWindowController(args);
_mainWindowController.AppInfo.Changelog =
@"* Added the option to use relative paths when creating a playlist. This means that Tagger also now supports opening playlists with relative paths
* Added the PublishingDate field to additional properties
* Tagger will now watch a music folder library for changes on disk and prompt the user to reload if necessary
* Tagger will now display front album art within a music file row itself if available
* Fixed an issue where downloaded lyrics would sometimes contain html encoded characters
Expand Down
35 changes: 34 additions & 1 deletion NickvisionTagger.GNOME/Resources/org.nickvision.tagger.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,37 @@

.list-icon {
border-radius: 6px;
}
}

@define-color tagger_calendar_today_bg_color @headerbar_bg_color;
@define-color tagger_calendar_today_fg_color @view_fg_color;

#calendarPublishingDate button {
border-radius: 12px;
}

#calendarPublishingDate .day-number {
border-radius: 12px;
}

#calendarPublishingDate .today {
background-color: @tagger_calendar_today_bg_color;
color: @tagger_calendar_today_fg_color;
box-shadow: none;
}

.calendar-button label {
margin-left: -8px;
margin-right: -8px;
}

.calendar-button popover label {
margin-left: 0px;
margin-right: 0px;
}

.calendar-button calendar {
font-weight: normal;
background-color: @popover_bg_color;
border: none;
}
64 changes: 63 additions & 1 deletion NickvisionTagger.GNOME/Views/MainWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,34 @@ namespace NickvisionTagger.GNOME.Views;
/// </summary>
public partial class MainWindow : Adw.ApplicationWindow
{
[StructLayout(LayoutKind.Sequential)]
public struct TaggerDateTime
{
ulong Usec;
nint Tz;
int Interval;
int Days;
int RefCount;
}

private delegate void GtkListBoxUpdateHeaderFunc(nint row, nint before, nint data);

[LibraryImport("libadwaita-1.so.0")]
private static partial void gtk_list_box_set_header_func(nint box, GtkListBoxUpdateHeaderFunc updateHeader, nint data, nint destroy);
[LibraryImport("libadwaita-1.so.0")]
private static partial void gtk_list_box_row_set_header(nint row, nint header);
[LibraryImport("libadwaita-1.so.0", StringMarshalling = StringMarshalling.Utf8)]
private static partial int g_date_time_get_year(ref TaggerDateTime datetime);
[LibraryImport("libadwaita-1.so.0", StringMarshalling = StringMarshalling.Utf8)]
private static partial int g_date_time_get_month(ref TaggerDateTime datetime);
[LibraryImport("libadwaita-1.so.0", StringMarshalling = StringMarshalling.Utf8)]
private static partial int g_date_time_get_day_of_month(ref TaggerDateTime datetime);
[DllImport("libadwaita-1.so.0")]
private static extern ref TaggerDateTime g_date_time_new_local(int year, int month, int day, int hour, int minute, double seconds);
[DllImport("libadwaita-1.so.0")]
private static extern ref TaggerDateTime gtk_calendar_get_date(nint calendar);
[LibraryImport("libadwaita-1.so.0", StringMarshalling = StringMarshalling.Utf8)]
private static partial void gtk_calendar_select_day(nint calendar, ref TaggerDateTime datetime);

private readonly MainWindowController _controller;
private readonly Adw.Application _application;
Expand All @@ -51,6 +73,7 @@ public partial class MainWindow : Adw.ApplicationWindow
private List<Adw.EntryRow> _customPropertyRows;
private AutocompleteBox _autocompleteBox;
private bool _isSelectionOccuring;
private bool _updatePublishingDate;

[Gtk.Connect] private readonly Adw.HeaderBar _headerBar;
[Gtk.Connect] private readonly Adw.WindowTitle _title;
Expand Down Expand Up @@ -98,6 +121,8 @@ public partial class MainWindow : Adw.ApplicationWindow
[Gtk.Connect] private readonly Adw.EntryRow _composerRow;
[Gtk.Connect] private readonly Adw.EntryRow _descriptionRow;
[Gtk.Connect] private readonly Adw.EntryRow _publisherRow;
[Gtk.Connect] private readonly Gtk.MenuButton _publishingDateButton;
[Gtk.Connect] private readonly Gtk.Calendar _publishingDateCalendar;
[Gtk.Connect] private readonly Adw.PreferencesGroup _customPropertiesGroup;
[Gtk.Connect] private readonly Gtk.Label _fingerprintLabel;
[Gtk.Connect] private readonly Gtk.Button _copyFingerprintButton;
Expand All @@ -112,6 +137,7 @@ private MainWindow(Gtk.Builder builder, MainWindowController controller, Adw.App
_listMusicFilesRows = new List<MusicFileRow>();
_customPropertyRows = new List<Adw.EntryRow>();
_isSelectionOccuring = false;
_updatePublishingDate = true;
SetDefaultSize(_controller.WindowWidth, _controller.WindowHeight);
if (_controller.WindowMaximized)
{
Expand Down Expand Up @@ -275,6 +301,25 @@ private MainWindow(Gtk.Builder builder, MainWindowController controller, Adw.App
TagPropertyChanged();
}
};
_publishingDateCalendar.OnDaySelected += (sender, e) =>
{
if(_updatePublishingDate)
{
var glibDate = gtk_calendar_get_date(_publishingDateCalendar.Handle);
var date = new DateTime(g_date_time_get_year(ref glibDate), g_date_time_get_month(ref glibDate), g_date_time_get_day_of_month(ref glibDate));
if (date != DateTime.MinValue)
{
_publishingDateButton.SetLabel(date.ToShortDateString());
TagPropertyChanged();
}
else
{
_updatePublishingDate = false;
gtk_calendar_select_day(_publishingDateCalendar.Handle, ref g_date_time_new_local(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 0, 0, 0));
}
}
_updatePublishingDate = true;
};
_fingerprintLabel.SetEllipsize(Pango.EllipsizeMode.End);
_copyFingerprintButton.OnClicked += CopyFingerprintToClipboard;
OnNotify += (sender, e) =>
Expand Down Expand Up @@ -1458,6 +1503,22 @@ private bool SelectedMusicFilesPropertiesChanged()
_composerRow.SetText(_controller.SelectedPropertyMap.Composer);
_descriptionRow.SetText(_controller.SelectedPropertyMap.Description);
_publisherRow.SetText(_controller.SelectedPropertyMap.Publisher);
if (string.IsNullOrEmpty(_controller.SelectedPropertyMap.PublishingDate))
{
gtk_calendar_select_day(_publishingDateCalendar.Handle, ref g_date_time_new_local(DateTime.MinValue.Year, DateTime.MinValue.Month, DateTime.MinValue.Day, 0, 0, 0));
_publishingDateButton.SetLabel(_("Pick a date"));
}
else if (_controller.SelectedPropertyMap.PublishingDate == _("<keep>"))
{
gtk_calendar_select_day(_publishingDateCalendar.Handle, ref g_date_time_new_local(DateTime.MinValue.Year, DateTime.MinValue.Month, DateTime.MinValue.Day, 0, 0, 0));
_publishingDateButton.SetLabel(_("<keep>"));
}
else
{
var dateTime = DateTime.Parse(_controller.SelectedPropertyMap.PublishingDate);
gtk_calendar_select_day(_publishingDateCalendar.Handle, ref g_date_time_new_local(dateTime.Year, dateTime.Month, dateTime.Day, 0, 0, 0));
_publishingDateButton.SetLabel(_controller.SelectedPropertyMap.PublishingDate);
}
_durationFileSizeLabel.SetLabel($"{_controller.SelectedPropertyMap.Duration} • {_controller.SelectedPropertyMap.FileSize}");
_fingerprintLabel.SetLabel(_controller.SelectedPropertyMap.Fingerprint);
var albumArt = _currentAlbumArtType == AlbumArtType.Front ? _controller.SelectedPropertyMap.FrontAlbumArt : _controller.SelectedPropertyMap.BackAlbumArt;
Expand Down Expand Up @@ -1645,7 +1706,8 @@ private void TagPropertyChanged()
BeatsPerMinute = _bpmRow.GetText(),
Composer = _composerRow.GetText(),
Description = _descriptionRow.GetText(),
Publisher = _publisherRow.GetText()
Publisher = _publisherRow.GetText(),
PublishingDate = _publishingDateButton.GetLabel() == _("Pick a date") ? "" : _publishingDateButton.GetLabel()
};
if (_controller.SelectedMusicFiles.Count == 1)
{
Expand Down
6 changes: 3 additions & 3 deletions NickvisionTagger.GNOME/nuget-sources.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,10 @@
},
{
"type": "file",
"url": "https://api.nuget.org/v3-flatcontainer/nickvision.aura/2023.10.1.1/nickvision.aura.2023.10.1.1.nupkg",
"sha512": "d608faca70ba0f4b115292682dbc0391ce9e91bedd6d195e1ef4e7c8371c86f6dfa3d5c1826126719c9a1fe9e3d2e0b123c052a0014b7e36e22396cd3edf8d3e",
"url": "https://api.nuget.org/v3-flatcontainer/nickvision.aura/2023.10.1.3/nickvision.aura.2023.10.1.3.nupkg",
"sha512": "cf54acb139bf2985a9a335bfb2d2bd7afa196ebbdc78ebdc1d1922b838340d4a3326a89ee370c635f30996a29a982af200d201b68e8df615dabb274269bbe8da",
"dest": "nuget-sources",
"dest-filename": "nickvision.aura.2023.10.1.1.nupkg"
"dest-filename": "nickvision.aura.2023.10.1.3.nupkg"
},
{
"type": "file",
Expand Down
78 changes: 73 additions & 5 deletions NickvisionTagger.Shared/Controllers/MainWindowController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ public void UpdateTags(PropertyMap map, bool triggerSelectedMusicFilesProperties
{
pair.Value.Year = 0;
}
updated = map.Year != _filesBeingEditedOriginals[pair.Key].Year.ToString();
updated = map.Year != _filesBeingEditedOriginals[pair.Key].Year;
}
if (map.Track != (pair.Value.Track == 0 ? "" : pair.Value.Track.ToString()) && map.Track != _("<keep>"))
{
Expand All @@ -658,7 +658,7 @@ public void UpdateTags(PropertyMap map, bool triggerSelectedMusicFilesProperties
{
pair.Value.Track = 0;
}
updated = map.Track != _filesBeingEditedOriginals[pair.Key].Track.ToString();
updated = map.Track != _filesBeingEditedOriginals[pair.Key].Track;
}
if (map.TrackTotal != (pair.Value.TrackTotal == 0 ? "" : pair.Value.TrackTotal.ToString()) && map.TrackTotal != _("<keep>"))
{
Expand All @@ -670,7 +670,7 @@ public void UpdateTags(PropertyMap map, bool triggerSelectedMusicFilesProperties
{
pair.Value.TrackTotal = 0;
}
updated = map.TrackTotal != _filesBeingEditedOriginals[pair.Key].TrackTotal.ToString();
updated = map.TrackTotal != _filesBeingEditedOriginals[pair.Key].TrackTotal;
}
if (map.AlbumArtist != pair.Value.AlbumArtist && map.AlbumArtist != _("<keep>"))
{
Expand Down Expand Up @@ -702,7 +702,7 @@ public void UpdateTags(PropertyMap map, bool triggerSelectedMusicFilesProperties
{
pair.Value.BeatsPerMinute = 0;
}
updated = map.BeatsPerMinute != _filesBeingEditedOriginals[pair.Key].BeatsPerMinute.ToString();
updated = map.BeatsPerMinute != _filesBeingEditedOriginals[pair.Key].BeatsPerMinute;
}
if (map.Description != pair.Value.Description && map.Description != _("<keep>"))
{
Expand All @@ -714,6 +714,18 @@ public void UpdateTags(PropertyMap map, bool triggerSelectedMusicFilesProperties
pair.Value.Publisher = map.Publisher;
updated = map.Publisher != _filesBeingEditedOriginals[pair.Key].Publisher;
}
if(map.PublishingDate != (pair.Value.PublishingDate == DateTime.MinValue ? "" : pair.Value.PublishingDate.ToShortDateString()) && map.PublishingDate != _("<keep>"))
{
try
{
pair.Value.PublishingDate = DateTime.Parse(map.PublishingDate);
}
catch
{
pair.Value.PublishingDate = DateTime.MinValue;
}
updated = map.PublishingDate != _filesBeingEditedOriginals[pair.Key].PublishingDate;
}
if (SelectedMusicFiles.Count == 1)
{
foreach (var p in map.CustomProperties)
Expand Down Expand Up @@ -1289,7 +1301,7 @@ public async Task SubmitToAcoustIdAsync(string? recordingID)
return (false, null);
}
var propValPairs = search.Split(';');
var validProperties = new string[] { "filename", _("filename"), "title", _("title"), "artist", _("artist"), "album", _("album"), "year", _("year"), "track", _("track"), "tracktotal", _("tracktotal"), "albumartist", _("albumartist"), "genre", _("genre"), "comment", _("comment"), "beatsperminute", _("beatsperminute"), "bpm", _("bpm"), "composer", _("composer"), "description", _("description"), "publisher", _("publisher"), "custom", _("custom") };
var validProperties = new string[] { "filename", _("filename"), "title", _("title"), "artist", _("artist"), "album", _("album"), "year", _("year"), "track", _("track"), "tracktotal", _("tracktotal"), "albumartist", _("albumartist"), "genre", _("genre"), "comment", _("comment"), "beatsperminute", _("beatsperminute"), "bpm", _("bpm"), "composer", _("composer"), "description", _("description"), "publisher", _("publisher"), "publishingdate", _("publishingdate"), "custom", _("custom") };
var propertyMap = new PropertyMap();
var customPropName = "";
foreach (var propVal in propValPairs)
Expand Down Expand Up @@ -1415,6 +1427,21 @@ public async Task SubmitToAcoustIdAsync(string? recordingID)
{
propertyMap.Publisher = val;
}
else if (prop == "publishingdate" || prop == _("publishingdate"))
{
if (val != "NULL")
{
try
{
DateTime.Parse(val);
}
catch
{
return (false, null);
}
}
propertyMap.PublishingDate = val;
}
else if (prop == "custom" || prop == _("custom"))
{
customPropName = val;
Expand Down Expand Up @@ -1482,6 +1509,10 @@ public async Task SubmitToAcoustIdAsync(string? recordingID)
{
continue;
}
if (TestAdvancedSearchShouldSkip(musicFile.PublishingDate, propertyMap.PublishingDate, ref ratio))
{
continue;
}
//Check for custom property
if (!string.IsNullOrEmpty(customPropName))
{
Expand Down Expand Up @@ -1626,6 +1657,7 @@ private void UpdateSelectedMusicFilesProperties()
SelectedPropertyMap.Composer = first.Composer;
SelectedPropertyMap.Description = first.Description;
SelectedPropertyMap.Publisher = first.Publisher;
SelectedPropertyMap.PublishingDate = first.PublishingDate == DateTime.MinValue ? "" : first.PublishingDate.ToShortDateString();
SelectedPropertyMap.Duration = first.Duration.ToDurationString();
SelectedPropertyMap.Fingerprint = _("Calculating...");
Task.Run(() =>
Expand Down Expand Up @@ -1661,6 +1693,7 @@ private void UpdateSelectedMusicFilesProperties()
var haveSameComposer = true;
var haveSameDescription = true;
var haveSamePublisher = true;
var haveSamePublishingDate = true;
var haveSameFrontAlbumArt = true;
var haveSameBackAlbumArt = true;
var totalDuration = 0;
Expand Down Expand Up @@ -1719,6 +1752,10 @@ private void UpdateSelectedMusicFilesProperties()
{
haveSamePublisher = false;
}
if (first.PublishingDate != pair.Value.PublishingDate)
{
haveSamePublishingDate = false;
}
if (!first.FrontAlbumArt.SequenceEqual(pair.Value.FrontAlbumArt))
{
haveSameFrontAlbumArt = false;
Expand All @@ -1744,6 +1781,7 @@ private void UpdateSelectedMusicFilesProperties()
SelectedPropertyMap.Composer = haveSameComposer ? first.Composer : _("<keep>");
SelectedPropertyMap.Description = haveSameDescription ? first.Description : _("<keep>");
SelectedPropertyMap.Publisher = haveSamePublisher ? first.Publisher : _("<keep>");
SelectedPropertyMap.PublishingDate = haveSamePublishingDate ? (first.PublishingDate == DateTime.MinValue ? "" : first.PublishingDate.ToShortDateString()) : _("<keep>");
SelectedPropertyMap.FrontAlbumArt = haveSameFrontAlbumArt ? (first.FrontAlbumArt.Length == 0 ? "noArt" : "hasArt") : "keepArt";
SelectedPropertyMap.BackAlbumArt = haveSameBackAlbumArt ? (first.BackAlbumArt.Length == 0 ? "noArt" : "hasArt") : "keepArt";
SelectedPropertyMap.Duration = totalDuration.ToDurationString();
Expand Down Expand Up @@ -1813,4 +1851,34 @@ private bool TestAdvancedSearchShouldSkip(int fileValue, string propValue, ref i
}
return false;
}

/// <summary>
/// Tests the value of a music file with the value from a PropertyMap for advanced search
/// </summary>
/// <param name="fileValue">The DateTime value from the file</param>
/// <param name="propValue">The value from the PropertyMap</param>
/// <param name="ratio">A variable to store the similarity ratio</param>
/// <returns>True to skip the file as a match, else false</returns>
private bool TestAdvancedSearchShouldSkip(DateTime fileValue, string propValue, ref int ratio)
{
if (!string.IsNullOrEmpty(propValue))
{
if (propValue == "NULL")
{
if (fileValue == DateTime.MinValue)
{
return true;
}
}
else
{
ratio = 100;
if (fileValue != DateTime.Parse(propValue).Date)
{
return true;
}
}
}
return false;
}
}
Loading