Public/Get-LocalMusicForProgramming.ps1

function Get-LocalMusicForProgramming {
    <#
    .SYNOPSIS
        Scans a local directory for Music For Programming audio files.

    .DESCRIPTION
        Searches the specified directory for files matching the standard
        Music For Programming naming convention (music_for_programming_NN-artist.mp3)
        and returns an object for each match with episode number, title, and path.

    .PARAMETER Path
        The directory to scan for Music For Programming audio files.

    .EXAMPLE
        Get-LocalMusicForProgramming -Path ~/Music

        Lists all MFP episodes found under ~/Music.

    .EXAMPLE
        Get-LocalMusicForProgramming -Path ~/Music | Where-Object EpisodeNumber -gt 50

        Returns only episodes numbered above 50 found locally.
    #>

    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateScript({
            if (-not (Test-Path $_ -PathType Container)) {
                throw "Path '$_' does not exist or is not a directory."
            }
            $true
        })]
        [string]$Path
    )

    Write-Verbose "Scanning '$Path' for Music For Programming files"

    $files = Get-ChildItem -Path $Path -Filter 'music_for_programming_*.mp3' -File -Recurse

    if (-not $files) {
        Write-Verbose "No Music For Programming files found in '$Path'"
        return
    }

    $files | ForEach-Object {
        $episodeNum = 0
        $artist = $_.BaseName

        # Standard filename: music_for_programming_78-datassette.mp3
        if ($_.BaseName -match 'music_for_programming_(\d+)-(.+)') {
            $episodeNum = [int]$Matches[1]
            $artist = (Get-Culture).TextInfo.ToTitleCase(($Matches[2] -replace '_', ' '))
        }

        [PSCustomObject]@{
            PSTypeName    = 'MusicForProgramming.LocalEpisode'
            EpisodeNumber = $episodeNum
            Title         = $artist
            FileName      = $_.Name
            FilePath      = $_.FullName
            FileSizeMB    = [math]::Round($_.Length / 1MB, 1)
        }
    } | Sort-Object -Property EpisodeNumber
}