Melon Scanner
The Melon Scanner is designed to:
- Scan specified library paths recursively to discover media files.
- Extract metadata from media files using the ATL library.
- Update the MongoDB database with new or modified tracks, albums, and artists.
- Delete entries from the database that no longer exist in the file system.
- Update dynamic collections based on the latest track information.
- Provide real-time feedback on the scanning progress through the user interface.
Class Structure
The MelonScanner
class is implemented as a
static
class within the
Melon.LocalClasses
namespace. It encapsulates all
functionalities related to scanning and updating the MongoDb database.
Properties
The class maintains several static properties to keep track of the scanning process and store temporary data.
-
CurrentFolder (
string
): The path of the folder currently being scanned. -
CurrentFile (
string
): The path of the file currently being processed. -
CurrentStatus (
string
): A status message indicating the current operation. -
ScannedFiles (
double
): The number of files that have been scanned. -
FoundFiles (
double
): The total number of files found to be scanned. -
averageMilliseconds (
long
): The average time taken to process files. -
fileTimes (
List<long>
): A list of times taken to process individual files. -
Indexed (
bool
): Indicates whether the database collections have been indexed. -
endDisplay (
bool
): Controls the termination of the progress display in the UI. -
Scanning (
bool
): Indicates whether a scanning operation is currently in progress. -
LyricFiles (
List<string>
): A list of paths to lyric files found during scanning. -
newMelonDB (
IMongoDatabase
): A reference to the MongoDB database. -
artistsCollection
(
IMongoCollection<Artist>
): The collection of artist documents. -
albumsCollection
(
IMongoCollection<Album>
): The collection of album documents. -
tracksCollection
(
IMongoCollection<Track>
): The collection of track documents. -
tracks (
ConcurrentDictionary<string, ProtoTrack>
): A thread-safe dictionary of tracks, keyed by file path. -
albums (
ConcurrentDictionary<string, Album>
): A thread-safe dictionary of albums, keyed by album name and artists. -
artists (
ConcurrentDictionary<string, Artist>
): A thread-safe dictionary of artists, keyed by artist name. -
threads (
ConcurrentDictionary<string, string>
): A thread-safe dictionary to track active scanning threads.
Methods
The MelonScanner
class provides several methods to perform
scanning and database operations:
-
IndexCollections()
: Enables Indexes for database collections for efficient querying. -
ResetDb()
: Resets the database by clearing collections and deleting associated files. -
StartScan(object skipBool)
: Initiates the scanning process. -
**
ScanFolderCounter(string path)`: Recursively counts the total number of files to scan. -
ScanFolder(string path, bool skip)
: Recursively scans folders and processes files. -
**
ScanInTrack(string file)`: Processes individual media files and extracts metadata. -
FillOutDB()
: Constructs and updates database documents based on scanned data. -
Upload(List<Track> DbTracks, List<Album> DbAlbums, List<Artist> DbArtists)
: Performs bulk writes to the database. -
DeletePass()
: Deletes database entries for files that no longer exist. -
UpdateCollections()
: Updates dynamic collections based on the latest tracks. -
IsAudioFile(string path)
: Determines if a file is an audio file. -
SplitArtists(string artistsStr)
: Splits artist strings into individual names. -
SplitGenres(string genresStr)
: Splits genre strings into individual genres. -
ResetDBUI()
: Provides a user interface for resetting the database. -
MemoryScan()
: Initiates a full library scan with UI prompts. -
MemoryScanShort()
: Initiates a short scan (skips existing files) with UI prompts. - `ScanProgressView()**: Displays the scanning progress in the user interface.
Scanning Process
Initialization
-
Check Scanning Status: The scanner first checks if a scanning operation is already in progress by inspecting the
Scanning
flag. If scanning is active, it returns immediately to prevent concurrent scans. -
Set Up Database Connections: Establishes connections to the MongoDB database and retrieves the collections for artists, albums, and tracks.
-
Load Existing Data: Loads existing tracks, albums, and artists from the database into in-memory dictionaries (
tracks
,albums
,artists
) for quick access and comparison. -
Initialize Variables: Resets counters and status messages. Sets up the
LyricFiles
list and other temporary data structures. -
Check Library Paths: Validates that library paths are specified in the settings. If none are found, it displays an error message and aborts the scanning process.
Folder Scanning
-
Counting Files: The
ScanFolderCounter
method recursively traverses all library paths to count the total number of files that will be processed. This is essential for displaying accurate progress information. -
Scanning Files: The
ScanFolder
method recursively scans each folder in the library paths. For each file found:- Thread Management: Ensures that no more than 25 scanning threads are active simultaneously to prevent resource exhaustion.
-
File Processing: For each file, a new thread is
spawned to process the file using the
ScanInTrack
method.
File Processing
-
Filter Non-Audio Files: The
ScanInTrack
method first checks if the file is an audio file using theIsAudioFile
method. If not, it skips processing. -
Process Lyric Files: If the file is a lyric file (e.g., ends with
.lrc
), it adds the path to theLyricFiles
list and skips further processing. -
Extract Metadata: Uses the
ATL
library to extract metadata from the audio file, including:- Title
- Artists
- Album
- Track number
- Disc number
- Genres
- Release date
- Additional fields (e.g., MusicBrainz ID, ISRC)
-
Create ProtoTrack Object: Constructs a
ProtoTrack
object to temporarily hold the track's metadata. -
Handle Artists and Genres: Splits artist and genre strings into lists using the
SplitArtists
andSplitGenres
methods. -
Update Existing Tracks: Checks if the track already exists in the
tracks
dictionary. If it does, updates the existing entry; otherwise, adds a new one. -
Error Handling: If an exception occurs during processing, logs the error to the
FailedFiles
collection in the database.
Database Update
After all files have been processed:
-
Construct Albums and Artists: Uses the collected track data to construct albums and artists, ensuring that relationships between tracks, albums, and artists are accurately represented.
-
Deduplicate Entries: Removes duplicate albums and artists by using distinct keys based on names and associated artists.
-
Update Track References: Updates tracks to reference the correct album and artist IDs.
-
Process Lyric Files: Associates lyric files with their corresponding tracks by matching file paths.
-
Bulk Upload: Uses the
Upload
method to perform bulk write operations to the database for tracks, albums, and artists.
Cleanup Operations
-
Delete Missing Files: The
DeletePass
method removes database entries for files that no longer exist in the file system. -
Update Collections: The
UpdateCollections
method updates dynamic collections based on the latest track information. -
Index Database Collections: Calls
IndexCollections
to ensure that database collections are properly indexed for efficient querying. -
Finalize Scanning: Resets scanning flags, updates status messages, and cleans up temporary data structures.
Database Interactions
Indexing Collections
The IndexCollections
method creates indexes on the
Artists
, Albums
, and
Tracks
collections to optimize query performance. It sets
up indexes on the Name
field with collation settings to
ensure case-insensitive and culture-aware comparisons.
Resetting the Database
The ResetDb
method performs a complete reset of the
database by:
-
Deleting all documents from the collections:
Tracks
,Artists
,Albums
,Playlists
,Collections
,FailedFiles
,Metadata
,Stats
, andQueues
. - Dropping indexes from the collections to remove any existing indexing configurations.
-
Deleting associated files from directories like
AlbumArts
,ArtistBanners
,ArtistPfps
,Assets
,CollectionArts
, andPlaylistArts
. - Users Collection is NOT Reset, so any users including your own will remain intact with their username, password, and profile settings. Any stats like play/skip logs and ratings will be lost.
Warning: Resetting the database is a destructive operation that cannot be undone. All media metadata and user stats will be lost.
User Interface Integration
The Melon Scanner provides user interface methods to interact with users and display scanning progress:
-
ResetDBUI(): Displays a warning message and prompts the user for confirmation before resetting the database.
-
MemoryScan(): Initiates a full library scan with user prompts and progress indicators.
-
MemoryScanShort(): Initiates a short scan that skips existing files, useful for quick updates.
-
ScanProgressView(): Displays real-time scanning progress, including:
- Number of files scanned vs. total files found.
- Current status message (e.g., "Scanning", "Updating Tracks").
- Control instructions (e.g., "Press Esc to exit").
Progress Display Diagram:
+--------------------------------------------------------+
| Melon > Scanner Progress |
+--------------------------------------------------------+
| Scan Status: 1500 / 3000 Found |
| [####################################--------] 70% |
| System Status: Scanning files |
| |
| |
| |
+--------------------------------------------------------+