Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Archives
Log in
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?
Sign up for a premium subscription Already a paid subscriber? Click here to log in.
GitHub
Bluesky
LinkedIn
Mastodon
jdhitsolutions.github.io
Powered by Buttondown, the easiest way to start and grow your newsletter.