diff --git a/octo-fiesta/Models/MusicModels.cs b/octo-fiesta/Models/MusicModels.cs
index 9055b2d..0a0c48f 100644
--- a/octo-fiesta/Models/MusicModels.cs
+++ b/octo-fiesta/Models/MusicModels.cs
@@ -1,13 +1,13 @@
namespace octo_fiesta.Models;
///
-/// Représente une chanson (locale ou externe)
+/// Represents a song (local or external)
///
public class Song
{
///
- /// ID unique. Pour les chansons externes, préfixé avec "ext-" + provider + "-" + id externe
- /// Exemple: "ext-deezer-123456" ou "local-789"
+ /// Unique ID. For external songs, prefixed with "ext-" + provider + "-" + external id
+ /// Example: "ext-deezer-123456" or "local-789"
///
public string Id { get; set; } = string.Empty;
@@ -16,7 +16,7 @@ public class Song
public string? ArtistId { get; set; }
public string Album { get; set; } = string.Empty;
public string? AlbumId { get; set; }
- public int? Duration { get; set; } // En secondes
+ public int? Duration { get; set; } // In seconds
public int? Track { get; set; }
public int? DiscNumber { get; set; }
public int? TotalTracks { get; set; }
@@ -25,12 +25,12 @@ public class Song
public string? CoverArtUrl { get; set; }
///
- /// URL de la cover en haute résolution (pour embedding)
+ /// High-resolution cover art URL (for embedding)
///
public string? CoverArtUrlLarge { get; set; }
///
- /// BPM (beats per minute) si disponible
+ /// BPM (beats per minute) if available
///
public int? Bpm { get; set; }
@@ -40,22 +40,22 @@ public class Song
public string? Isrc { get; set; }
///
- /// Date de sortie complète (format: YYYY-MM-DD)
+ /// Full release date (format: YYYY-MM-DD)
///
public string? ReleaseDate { get; set; }
///
- /// Nom de l'album artiste (peut différer de l'artiste du track)
+ /// Album artist name (may differ from track artist)
///
public string? AlbumArtist { get; set; }
///
- /// Compositeur(s)
+ /// Composer(s)
///
public string? Composer { get; set; }
///
- /// Label de l'album
+ /// Album label
///
public string? Label { get; set; }
@@ -65,33 +65,33 @@ public class Song
public string? Copyright { get; set; }
///
- /// Artistes contributeurs (featurings, etc.)
+ /// Contributing artists (features, etc.)
///
public List Contributors { get; set; } = new();
///
- /// Indique si la chanson est disponible localement ou doit être téléchargée
+ /// Indicates whether the song is available locally or needs to be downloaded
///
public bool IsLocal { get; set; }
///
- /// Provider externe (deezer, spotify, etc.) - null si local
+ /// External provider (deezer, spotify, etc.) - null if local
///
public string? ExternalProvider { get; set; }
///
- /// ID sur le provider externe (pour le téléchargement)
+ /// ID on the external provider (for downloading)
///
public string? ExternalId { get; set; }
///
- /// Chemin du fichier local (si disponible)
+ /// Local file path (if available)
///
public string? LocalPath { get; set; }
}
///
-/// Représente un artiste
+/// Represents an artist
///
public class Artist
{
@@ -105,7 +105,7 @@ public class Artist
}
///
-/// Représente un album
+/// Represents an album
///
public class Album
{
@@ -124,7 +124,7 @@ public class Album
}
///
-/// Résultat de recherche combinant résultats locaux et externes
+/// Search result combining local and external results
///
public class SearchResult
{
@@ -134,7 +134,7 @@ public class SearchResult
}
///
-/// État du téléchargement d'une chanson
+/// Download status of a song
///
public enum DownloadStatus
{
@@ -145,7 +145,7 @@ public enum DownloadStatus
}
///
-/// Information sur un téléchargement en cours ou terminé
+/// Information about an ongoing or completed download
///
public class DownloadInfo
{
@@ -153,7 +153,7 @@ public class DownloadInfo
public string ExternalId { get; set; } = string.Empty;
public string ExternalProvider { get; set; } = string.Empty;
public DownloadStatus Status { get; set; }
- public double Progress { get; set; } // 0.0 à 1.0
+ public double Progress { get; set; } // 0.0 to 1.0
public string? LocalPath { get; set; }
public string? ErrorMessage { get; set; }
public DateTime StartedAt { get; set; }
@@ -161,7 +161,7 @@ public class DownloadInfo
}
///
-/// Statut du scan de bibliothèque Subsonic
+/// Subsonic library scan status
///
public class ScanStatus
{
diff --git a/octo-fiesta/Program.cs b/octo-fiesta/Program.cs
index ea50164..dbbe5cc 100644
--- a/octo-fiesta/Program.cs
+++ b/octo-fiesta/Program.cs
@@ -14,7 +14,7 @@ builder.Services.AddSwaggerGen();
builder.Services.Configure(
builder.Configuration.GetSection("Subsonic"));
-// Services métier
+// Business services
builder.Services.AddSingleton();
builder.Services.AddScoped();
builder.Services.AddScoped();
diff --git a/octo-fiesta/Services/DeezerDownloadService.cs b/octo-fiesta/Services/DeezerDownloadService.cs
index e0d7f16..85247a8 100644
--- a/octo-fiesta/Services/DeezerDownloadService.cs
+++ b/octo-fiesta/Services/DeezerDownloadService.cs
@@ -11,7 +11,7 @@ using IOFile = System.IO.File;
namespace octo_fiesta.Services;
///
-/// Configuration pour le téléchargeur Deezer
+/// Configuration for the Deezer downloader
///
public class DeezerDownloaderSettings
{
@@ -21,8 +21,8 @@ public class DeezerDownloaderSettings
}
///
-/// Port C# du DeezerDownloader JavaScript
-/// Gère l'authentification Deezer, le téléchargement et le déchiffrement des pistes
+/// C# port of the DeezerDownloader JavaScript
+/// Handles Deezer authentication, track downloading and decryption
///
public class DeezerDownloadService : IDownloadService
{
@@ -84,7 +84,7 @@ public class DeezerDownloadService : IDownloadService
var songId = $"ext-{externalProvider}-{externalId}";
- // Vérifier si déjà téléchargé
+ // Check if already downloaded
var existingPath = await _localLibraryService.GetLocalPathForExternalSongAsync(externalProvider, externalId);
if (existingPath != null && IOFile.Exists(existingPath))
{
@@ -92,7 +92,7 @@ public class DeezerDownloadService : IDownloadService
return existingPath;
}
- // Vérifier si téléchargement en cours
+ // Check if download in progress
if (_activeDownloads.TryGetValue(songId, out var activeDownload) && activeDownload.Status == DownloadStatus.InProgress)
{
_logger.LogInformation("Download already in progress for {SongId}", songId);
@@ -112,7 +112,7 @@ public class DeezerDownloadService : IDownloadService
await _downloadLock.WaitAsync(cancellationToken);
try
{
- // Récupérer les métadonnées
+ // Get metadata
var song = await _metadataService.GetSongAsync(externalProvider, externalId);
if (song == null)
{
@@ -140,7 +140,7 @@ public class DeezerDownloadService : IDownloadService
song.LocalPath = localPath;
await _localLibraryService.RegisterDownloadedSongAsync(song, localPath);
- // Déclencher un rescan de la bibliothèque Subsonic (avec debounce)
+ // Trigger a Subsonic library rescan (with debounce)
_ = _localLibraryService.TriggerLibraryScanAsync();
_logger.LogInformation("Download completed: {Path}", localPath);
@@ -362,7 +362,7 @@ public class DeezerDownloadService : IDownloadService
_logger.LogInformation("Track token obtained for: {Title} - {Artist}", downloadInfo.Title, downloadInfo.Artist);
_logger.LogInformation("Using format: {Format}", downloadInfo.Format);
- // Déterminer l'extension basée sur le format
+ // Determine extension based on format
var extension = downloadInfo.Format?.ToUpper() switch
{
"FLAC" => ".flac",
@@ -379,7 +379,7 @@ public class DeezerDownloadService : IDownloadService
// Resolve unique path if file already exists
outputPath = PathHelper.ResolveUniquePath(outputPath);
- // Télécharger le fichier chiffré
+ // Download the encrypted file
var response = await RetryWithBackoffAsync(async () =>
{
var request = new HttpRequestMessage(HttpMethod.Get, downloadInfo.DownloadUrl);
@@ -391,23 +391,23 @@ public class DeezerDownloadService : IDownloadService
response.EnsureSuccessStatusCode();
- // Télécharger et déchiffrer
+ // Download and decrypt
await using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken);
await using var outputFile = IOFile.Create(outputPath);
await DecryptAndWriteStreamAsync(responseStream, outputFile, trackId, cancellationToken);
- // Fermer le fichier avant d'écrire les métadonnées
+ // Close file before writing metadata
await outputFile.DisposeAsync();
- // Écrire les métadonnées et la cover art
+ // Write metadata and cover art
await WriteMetadataAsync(outputPath, song, cancellationToken);
return outputPath;
}
///
- /// Écrit les métadonnées ID3/Vorbis et la cover art dans le fichier audio
+ /// Writes ID3/Vorbis metadata and cover art to the audio file
///
private async Task WriteMetadataAsync(string filePath, Song song, CancellationToken cancellationToken)
{
@@ -417,12 +417,12 @@ public class DeezerDownloadService : IDownloadService
using var tagFile = TagLib.File.Create(filePath);
- // Métadonnées de base
+ // Basic metadata
tagFile.Tag.Title = song.Title;
tagFile.Tag.Performers = new[] { song.Artist };
tagFile.Tag.Album = song.Album;
- // Album artist (peut différer de l'artiste du track pour les compilations)
+ // Album artist (may differ from track artist for compilations)
if (!string.IsNullOrEmpty(song.AlbumArtist))
{
tagFile.Tag.AlbumArtists = new[] { song.AlbumArtist };
@@ -432,25 +432,25 @@ public class DeezerDownloadService : IDownloadService
tagFile.Tag.AlbumArtists = new[] { song.Artist };
}
- // Numéro de piste
+ // Track number
if (song.Track.HasValue)
{
tagFile.Tag.Track = (uint)song.Track.Value;
}
- // Nombre total de pistes
+ // Total track count
if (song.TotalTracks.HasValue)
{
tagFile.Tag.TrackCount = (uint)song.TotalTracks.Value;
}
- // Numéro de disque
+ // Disc number
if (song.DiscNumber.HasValue)
{
tagFile.Tag.Disc = (uint)song.DiscNumber.Value;
}
- // Année
+ // Year
if (song.Year.HasValue)
{
tagFile.Tag.Year = (uint)song.Year.Value;
@@ -468,15 +468,15 @@ public class DeezerDownloadService : IDownloadService
tagFile.Tag.BeatsPerMinute = (uint)song.Bpm.Value;
}
- // ISRC (stocké dans le commentaire si pas de champ dédié, ou via MusicBrainz ID)
- // TagLib ne supporte pas directement l'ISRC, mais on peut l'ajouter au commentaire
+ // ISRC (stored in comment if no dedicated field, or via MusicBrainz ID)
+ // TagLib doesn't directly support ISRC, but we can add it to comments
var comments = new List();
if (!string.IsNullOrEmpty(song.Isrc))
{
comments.Add($"ISRC: {song.Isrc}");
}
- // Contributeurs dans le commentaire
+ // Contributors in comments
if (song.Contributors.Count > 0)
{
tagFile.Tag.Composers = song.Contributors.ToArray();
@@ -488,13 +488,13 @@ public class DeezerDownloadService : IDownloadService
tagFile.Tag.Copyright = song.Copyright;
}
- // Commentaire avec infos supplémentaires
+ // Comment with additional info
if (comments.Count > 0)
{
tagFile.Tag.Comment = string.Join(" | ", comments);
}
- // Télécharger et intégrer la cover art
+ // Download and embed cover art
var coverUrl = song.CoverArtUrlLarge ?? song.CoverArtUrl;
if (!string.IsNullOrEmpty(coverUrl))
{
@@ -521,19 +521,19 @@ public class DeezerDownloadService : IDownloadService
}
}
- // Sauvegarder les modifications
+ // Save changes
tagFile.Save();
_logger.LogInformation("Metadata written successfully to: {Path}", filePath);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to write metadata to: {Path}", filePath);
- // Ne pas propager l'erreur - le fichier est téléchargé, juste sans métadonnées
+ // Don't propagate the error - the file is downloaded, just without metadata
}
}
///
- /// Télécharge la cover art depuis une URL
+ /// Downloads cover art from a URL
///
private async Task DownloadCoverArtAsync(string url, CancellationToken cancellationToken)
{
@@ -587,7 +587,7 @@ public class DeezerDownloadService : IDownloadService
var chunk = buffer.AsSpan(0, bytesRead).ToArray();
- // Chaque 3ème chunk (index % 3 == 0) est chiffré
+ // Every 3rd chunk (index % 3 == 0) is encrypted
if (chunkIndex % 3 == 0 && bytesRead == 2048)
{
chunk = DecryptBlowfishCbc(chunk, bfKey, iv);
diff --git a/octo-fiesta/Services/DeezerMetadataService.cs b/octo-fiesta/Services/DeezerMetadataService.cs
index 57060e1..9cca74e 100644
--- a/octo-fiesta/Services/DeezerMetadataService.cs
+++ b/octo-fiesta/Services/DeezerMetadataService.cs
@@ -4,7 +4,7 @@ using System.Text.Json;
namespace octo_fiesta.Services;
///
-/// Implémentation du service de métadonnées utilisant l'API Deezer (gratuite, pas besoin de clé)
+/// Metadata service implementation using the Deezer API (free, no key required)
///
public class DeezerMetadataService : IMusicMetadataService
{
@@ -105,7 +105,7 @@ public class DeezerMetadataService : IMusicMetadataService
public async Task SearchAllAsync(string query, int songLimit = 20, int albumLimit = 20, int artistLimit = 20)
{
- // Exécuter les recherches en parallèle
+ // Execute searches in parallel
var songsTask = SearchSongsAsync(query, songLimit);
var albumsTask = SearchAlbumsAsync(query, albumLimit);
var artistsTask = SearchArtistsAsync(query, artistLimit);
@@ -134,11 +134,11 @@ public class DeezerMetadataService : IMusicMetadataService
if (track.TryGetProperty("error", out _)) return null;
- // Pour un track individuel, on récupère les métadonnées complètes
+ // For an individual track, get full metadata
var song = ParseDeezerTrackFull(track);
- // Récupérer les infos supplémentaires depuis l'album (genre, nombre total de tracks, label, copyright)
- if (track.TryGetProperty("album", out var albumRef) &&
+ // Get additional info from album (genre, total track count, label, copyright)
+ if (track.TryGetProperty("album", out var albumRef) &&
albumRef.TryGetProperty("id", out var albumIdEl))
{
var albumId = albumIdEl.GetInt64().ToString();
@@ -160,7 +160,7 @@ public class DeezerMetadataService : IMusicMetadataService
song.Genre = genreName.GetString();
}
- // Nombre total de tracks
+ // Total track count
if (albumData.TryGetProperty("nb_tracks", out var nbTracks))
{
song.TotalTracks = nbTracks.GetInt32();
@@ -172,7 +172,7 @@ public class DeezerMetadataService : IMusicMetadataService
song.Label = label.GetString();
}
- // Cover art XL si pas déjà définie
+ // Cover art XL if not already set
if (string.IsNullOrEmpty(song.CoverArtUrlLarge))
{
if (albumData.TryGetProperty("cover_xl", out var coverXl))
@@ -188,7 +188,7 @@ public class DeezerMetadataService : IMusicMetadataService
}
catch
{
- // Si on ne peut pas récupérer l'album, on continue avec les infos du track
+ // If we can't get the album, continue with track info only
}
}
@@ -211,8 +211,8 @@ public class DeezerMetadataService : IMusicMetadataService
var album = ParseDeezerAlbum(albumElement);
- // Récupérer les chansons de l'album
- if (albumElement.TryGetProperty("tracks", out var tracks) &&
+ // Get album songs
+ if (albumElement.TryGetProperty("tracks", out var tracks) &&
tracks.TryGetProperty("data", out var tracksData))
{
int trackIndex = 1;
@@ -308,8 +308,8 @@ public class DeezerMetadataService : IMusicMetadataService
}
///
- /// Parse un track Deezer avec toutes les métadonnées disponibles
- /// Utilisé pour GetSongAsync qui retourne des données complètes
+ /// Parses a Deezer track with all available metadata
+ /// Used for GetSongAsync which returns complete data
///
private Song ParseDeezerTrackFull(JsonElement track)
{
@@ -371,7 +371,7 @@ public class DeezerMetadataService : IMusicMetadataService
}
}
- // Album artist (premier artiste de l'album, ou artiste principal du track)
+ // Album artist (first artist from album, or main track artist)
string? albumArtist = null;
if (track.TryGetProperty("album", out var albumForArtist) &&
albumForArtist.TryGetProperty("artist", out var albumArtistEl))
@@ -381,7 +381,7 @@ public class DeezerMetadataService : IMusicMetadataService
: null;
}
- // Cover art URLs (différentes tailles)
+ // Cover art URLs (different sizes)
string? coverMedium = null;
string? coverLarge = null;
if (track.TryGetProperty("album", out var albumForCover))
diff --git a/octo-fiesta/Services/IDownloadService.cs b/octo-fiesta/Services/IDownloadService.cs
index f6d2afd..e1095ff 100644
--- a/octo-fiesta/Services/IDownloadService.cs
+++ b/octo-fiesta/Services/IDownloadService.cs
@@ -3,35 +3,35 @@ using octo_fiesta.Models;
namespace octo_fiesta.Services;
///
-/// Interface pour le service de téléchargement de musique (Deezspot ou autre)
+/// Interface for the music download service (Deezspot or other)
///
public interface IDownloadService
{
///
- /// Télécharge une chanson depuis un provider externe
+ /// Downloads a song from an external provider
///
- /// Le provider (deezer, spotify)
- /// L'ID sur le provider externe
- /// Token d'annulation
- /// Le chemin du fichier téléchargé
+ /// The provider (deezer, spotify)
+ /// The ID on the external provider
+ /// Cancellation token
+ /// The path to the downloaded file
Task DownloadSongAsync(string externalProvider, string externalId, CancellationToken cancellationToken = default);
///
- /// Télécharge une chanson et stream le résultat au fur et à mesure
+ /// Downloads a song and streams the result progressively
///
- /// Le provider (deezer, spotify)
- /// L'ID sur le provider externe
- /// Token d'annulation
- /// Un stream du fichier audio
+ /// The provider (deezer, spotify)
+ /// The ID on the external provider
+ /// Cancellation token
+ /// A stream of the audio file
Task DownloadAndStreamAsync(string externalProvider, string externalId, CancellationToken cancellationToken = default);
///
- /// Vérifie si une chanson est en cours de téléchargement
+ /// Checks if a song is currently being downloaded
///
DownloadInfo? GetDownloadStatus(string songId);
///
- /// Vérifie si le service est correctement configuré et fonctionnel
+ /// Checks if the service is properly configured and functional
///
Task IsAvailableAsync();
}
diff --git a/octo-fiesta/Services/IMusicMetadataService.cs b/octo-fiesta/Services/IMusicMetadataService.cs
index eca9f7c..8a9be13 100644
--- a/octo-fiesta/Services/IMusicMetadataService.cs
+++ b/octo-fiesta/Services/IMusicMetadataService.cs
@@ -3,51 +3,51 @@ using octo_fiesta.Models;
namespace octo_fiesta.Services;
///
-/// Interface pour le service de recherche de métadonnées musicales externes
+/// Interface for external music metadata search service
/// (Deezer API, Spotify API, MusicBrainz, etc.)
///
public interface IMusicMetadataService
{
///
- /// Recherche des chansons sur les providers externes
+ /// Searches for songs on external providers
///
- /// Terme de recherche
- /// Nombre maximum de résultats
- /// Liste des chansons trouvées
+ /// Search term
+ /// Maximum number of results
+ /// List of found songs
Task> SearchSongsAsync(string query, int limit = 20);
///
- /// Recherche des albums sur les providers externes
+ /// Searches for albums on external providers
///
Task> SearchAlbumsAsync(string query, int limit = 20);
///
- /// Recherche des artistes sur les providers externes
+ /// Searches for artists on external providers
///
Task> SearchArtistsAsync(string query, int limit = 20);
///
- /// Recherche combinée (chansons, albums, artistes)
+ /// Combined search (songs, albums, artists)
///
Task SearchAllAsync(string query, int songLimit = 20, int albumLimit = 20, int artistLimit = 20);
///
- /// Récupère les détails d'une chanson externe
+ /// Gets details of an external song
///
Task GetSongAsync(string externalProvider, string externalId);
///
- /// Récupère les détails d'un album externe avec ses chansons
+ /// Gets details of an external album with its songs
///
Task GetAlbumAsync(string externalProvider, string externalId);
///
- /// Récupère les détails d'un artiste externe
+ /// Gets details of an external artist
///
Task GetArtistAsync(string externalProvider, string externalId);
///
- /// Récupère les albums d'un artiste
+ /// Gets an artist's albums
///
Task> GetArtistAlbumsAsync(string externalProvider, string externalId);
}
diff --git a/octo-fiesta/Services/LocalLibraryService.cs b/octo-fiesta/Services/LocalLibraryService.cs
index 9cc3495..fb93134 100644
--- a/octo-fiesta/Services/LocalLibraryService.cs
+++ b/octo-fiesta/Services/LocalLibraryService.cs
@@ -6,51 +6,51 @@ using octo_fiesta.Models;
namespace octo_fiesta.Services;
///
-/// Interface pour la gestion de la bibliothèque locale de musiques
+/// Interface for local music library management
///
public interface ILocalLibraryService
{
///
- /// Vérifie si une chanson externe existe déjà localement
+ /// Checks if an external song already exists locally
///
Task GetLocalPathForExternalSongAsync(string externalProvider, string externalId);
///
- /// Enregistre une chanson téléchargée dans la bibliothèque locale
+ /// Registers a downloaded song in the local library
///
Task RegisterDownloadedSongAsync(Song song, string localPath);
///
- /// Récupère le mapping entre ID externe et ID local
+ /// Gets the mapping between external ID and local ID
///
Task GetLocalIdForExternalSongAsync(string externalProvider, string externalId);
///
- /// Parse un ID de chanson pour déterminer s'il est externe ou local
+ /// Parses a song ID to determine if it is external or local
///
(bool isExternal, string? provider, string? externalId) ParseSongId(string songId);
///
- /// Parse un ID externe pour extraire le provider, le type et l'ID
- /// Format: ext-{provider}-{type}-{id} (ex: ext-deezer-artist-259, ext-deezer-album-96126, ext-deezer-song-12345)
+ /// Parses an external ID to extract the provider, type and ID
+ /// Format: ext-{provider}-{type}-{id} (e.g., ext-deezer-artist-259, ext-deezer-album-96126, ext-deezer-song-12345)
/// Also supports legacy format: ext-{provider}-{id} (assumes song type)
///
(bool isExternal, string? provider, string? type, string? externalId) ParseExternalId(string id);
///
- /// Déclenche un scan de la bibliothèque Subsonic
+ /// Triggers a Subsonic library scan
///
Task TriggerLibraryScanAsync();
///
- /// Récupère le statut actuel du scan
+ /// Gets the current scan status
///
Task GetScanStatusAsync();
}
///
-/// Implémentation du service de bibliothèque locale
-/// Utilise un fichier JSON simple pour stocker les mappings (peut être remplacé par une BDD)
+/// Local library service implementation
+/// Uses a simple JSON file to store mappings (can be replaced with a database)
///
public class LocalLibraryService : ILocalLibraryService
{
@@ -62,7 +62,7 @@ public class LocalLibraryService : ILocalLibraryService
private Dictionary? _mappings;
private readonly SemaphoreSlim _lock = new(1, 1);
- // Debounce pour éviter de déclencher trop de scans
+ // Debounce to avoid triggering too many scans
private DateTime _lastScanTrigger = DateTime.MinValue;
private readonly TimeSpan _scanDebounceInterval = TimeSpan.FromSeconds(30);
@@ -128,8 +128,8 @@ public class LocalLibraryService : ILocalLibraryService
public async Task GetLocalIdForExternalSongAsync(string externalProvider, string externalId)
{
- // Pour l'instant, on retourne null car on n'a pas encore d'intégration
- // avec le serveur Subsonic pour récupérer l'ID local après scan
+ // For now, return null as we don't yet have integration
+ // with the Subsonic server to retrieve local ID after scan
await Task.CompletedTask;
return null;
}
@@ -206,7 +206,7 @@ public class LocalLibraryService : ILocalLibraryService
public async Task TriggerLibraryScanAsync()
{
- // Debounce: éviter de déclencher trop de scans successifs
+ // Debounce: avoid triggering too many successive scans
var now = DateTime.UtcNow;
if (now - _lastScanTrigger < _scanDebounceInterval)
{
@@ -219,8 +219,8 @@ public class LocalLibraryService : ILocalLibraryService
try
{
- // Appel à l'API Subsonic pour déclencher un scan
- // Note: Les credentials doivent être passés en paramètres (u, p ou t+s)
+ // Call Subsonic API to trigger a scan
+ // Note: Credentials must be passed as parameters (u, p or t+s)
var url = $"{_subsonicSettings.Url}/rest/startScan?f=json";
_logger.LogInformation("Triggering Subsonic library scan...");
@@ -280,7 +280,7 @@ public class LocalLibraryService : ILocalLibraryService
}
///
-/// Représente le mapping entre une chanson externe et son fichier local
+/// Represents the mapping between an external song and its local file
///
public class LocalSongMapping
{