Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Subscribe
Archives
March 14, 2025

PowerShell Tag

Let's continue my process of using PowerShell to manage my MuseScore related files. Obviously, I don't expect you to need to do this, but I am trusting you will learn something from the process. The last part of my process is to update the associated MP3 file. However, after I finished the last article, I discovered I needed to revise the function that gets score information.

I was testing with files created from MuseScore v3 and realized that I shouldn't rely solely on processing the XML file for details. I should modify the function to accepts a few properties as parameters.

Param(
    [Parameter(
        Position = 0,
        ValueFromPipeline,
        HelpMessage = 'Enter the PATH to the MuseScore files.'
    )]
    [ValidateScript({ Test-Path $_ }, ErrorMessage = 'Path {0} was not found')]
    [string]$Path = '.',
    [Parameter(
        HelpMessage = 'Enter the path to the preferred cover art file.'
    )]
    [ValidateNotNullOrEmpty()]
    [ValidateScript({ Test-Path $_ }, ErrorMessage = 'Cover art path {0} was not found')]
    [string]$CoverArt,
    [string]$Title,
    [string]$SubTitle
)

In the function I added logic to parse the XML file if a value wasn't passed from the parameter.

Try {
    [xml]$score = Get-Content $ZipDestination\*.xml -ErrorAction Stop
    Write-Information $score -Tags Data
    $software = $score.'score-partwise'.identification.encoding.software.Trim()
    #10 March 2025 - if the user specifies a title, use that otherwise look for one in the XML file
    if (-Not $PSBoundParameters.ContainsKey("Title")) {
        $TitleNode = $score.'score-partwise'.credit.where({ $_.'credit-type' -eq 'title' })
        $title = $titleNode.'credit-words'.'#text'.Trim()
    }

    If (-Not $PSBoundParameters.ContainsKey("SubTitle")) {
        $subTitleNode = $score.'score-partwise'.credit.where({ $_.'credit-type' -eq 'subtitle' })
        #10 March 2025 - some scores may not have a subtitle
        if ($subTitleNode) {
            $subTitle = $subTitleNode.'credit-words'.'#text'.Trim()
        }
        else {
            $subTitle = $null
        }
    }
    ...
} #Try
Catch {
    #10 March 2025 - revise the warning message with more detail.
    Write-Warning "Can't find the XML file in $ZipDestination or there was an error in processing. $($_.Exception.Message)"
}

Here's an example of the problem.

Missing properties
Missing Properties

But with the revised function, I can manually fill in the gaps.

PS C:\Users\Jeff\Documents\MuseScore3\Scores\Nocturne for Flute> $info = Get-MuseScoreProperty -Title "Nocturne for Flute" -SubTitle "in Bb Min"
PS C:\Users\Jeff\Documents\MuseScore3\Scores\Nocturne for Flute> $info

   Path: C:\Users\Jeff\Documents\MuseScore3\Scores\Nocturne for Flute

Date      Title              SubTitle  Duration
----      -----              --------  --------
8/25/2022 Nocturne for Flute in Bb Min    05:33

Now that I have this corrected let's turn to managing the MP3 file.

TagLib Re-Visited

Once again, I will use the TagLib library to manage the audio file. I have already saved a the DLL file in my scripts folder.

Add-Type -Path C:\scripts\TagLibSharp.dll

I will need to create an instance of the TagLib.File class.

PS C:\Users\Jeff\Documents\MuseScore3\Scores\Nocturne for Flute> $file = [TagLib.file]::Create($(Convert-Path '.\Nocturne for Flute.mp3'))
Want to read the full issue?
GitHub Bluesky LinkedIn About Jeff
Powered by Buttondown, the easiest way to start and grow your newsletter.