TerminalTunes.types.ps1xml
<?xml version="1.0" encoding="utf-16"?> <!-- Generated with EZOut 1.9.3: Install-Module EZOut or https://github.com/StartAutomating/EZOut --> <Types> <Type> <Name>TerminalTunes.Generator</Name> <Members> <ScriptMethod> <Name>GetANSINoteRegex</Name> <Script> [Regex]::new(@' (?<ANSI_Note> \e # An Escape \[ # Followed by a bracket (?> (?<Volume>(?<VolumeOff>0) # 0 is no volume | (?<VolumeLow>[1-3]) # 1-3 is low volume | (?<VolumeHigh>[4-7]) # 4-7 is high volume ))\; # A semicolon separated the volume from the duration # Duration is measured in 1/32 of a second (?<Duration>\d+)\; # A semicolon separates the duration from the note # One or more notes will follow (?<Notes>(?:(?> (?<C5>25) # 25 is C in the 6th octave (MIDI 96) | (?<B5>24) # 24 is B in the 5th octave (MIDI 95) | (?<ASharp5>23) # 23 is A Sharp in the 5th octave (MIDI 94) | (?<A5>22) # 22 is A in the 5th octave (MIDI 93) | (?<GSharp5>21) # 21 is G Sharp in the 5th octave (MIDI 92) | (?<G5>20) # 20 is G in the 5th octave (MIDI 91) | (?<FSharp5>19) # 19 is F Sharp in the 5th octave (MIDI 90) | (?<F5>18) # 18 is F in the 5th octave (MIDI 89) | (?<E5>17) # 17 is F in the 5th octave (MIDI 88) | (?<DSharp5>16) # 16 is D Sharp in the 5th octave (MIDI 87) | (?<D5>15) # 15 is D in the 5th octave (MIDI 86) | (?<CSharp5>14) # 14 is C Sharp in the 5th octave (MIDI 85) | (?<C5>13) # 13 is C in the 5th octave (MIDI 84) | (?<B4>12) # 12 is B in the 4th octave (MIDI 83) | (?<ASharp4>11) # 11 is A Sharp in the 4th octave (MIDI 82) | (?<A4>10) # 10 is A in the 4th octave (MIDI 81) | (?<GSharp4>9) # 9 is G Sharp in the 4th octave (MIDI 80) | (?<G4>8) # 8 is G in the 4th octave (MIDI 79) | (?<FSharp4>7) # 7 is F Sharp in the 4th octave (MIDI 78) | (?<F4>6) # 6 is F in the 4th octave (MIDI 77) | (?<E4>5) # 5 is E in the 4th octave (MIDI 76) | (?<DSharp4>4) # 4 is D Sharp in the 4th octave (MIDI 75) | (?<D4>3) # 3 is D in the 4th octave (MIDI 74) | (?<CSharp4>2) # 2 is C Sharp in the 4th octave (MIDI 73) | (?<C4>1) # 1 is C in the 4th octave (MIDI 72) )\;?){0,}),~ # A command and a tilda end the sequence ) '@, 'IgnoreCase,IgnorePatternWhitespace') </Script> </ScriptMethod> <ScriptMethod> <Name>IsSafe</Name> <Script> [ValidateScript({ if ($_ -isnot [ScriptBlock]) { return $true } $astConditions = { param($ast) if ($ast -is [Management.Automation.Language.CommandAst]) { throw "AST cannot contain commands" } return $true} , {param($ast) $included = [Int32],[Math],[TimeSpan],[DateTime],[String],[String[]],[Int32[]],[Double[]],[Management.Automation.SwitchParameter] $excluded = '*' if ($ast -is [Management.Automation.Language.TypeExpressionAst] -or $ast -is [Management.Automation.Language.TypeConstraintAst]) { $astType = $ast.TypeName $reflectionType = if ($astType) { $astType.GetReflectionType() } foreach ($inc in $included) { if ($inc -is [string] -and $astType -like $inc) { return $true } elseif ($inc -is [Regex] -and $astType -match $inc) { return $true } elseif ($inc -is [type]){ if ($inc -eq $reflectionType) { return $true} if ($inc.IsSubclassOf($reflectionType) -or $reflectionType.IsSubclassOf($inc)) { return $true } if ($inc.IsInterface -and $reflectionType.getInterFace($inc)) { return $true } if ($reflectionType.IsInterface -and $inc.getInterFace($reflectionType)) { return $true } } } $throwMessage = "[$($ast.Typename)] is not allowed" foreach ($exc in $excluded) { if ($exc -is [string] -and $astType -like $exc) { throw $throwMessage } elseif ($exc -is [regex] -and $astType -match $exc) { throw $throwMessage } elseif ($exc -is [type]) { if ($ecx -eq $reflectionType) { throw $throwMessage } elseif ($exc.IsSubclassOf($reflectionType) -or $reflectionType.IsSubclassOf($exc)) { throw $throwMessage } elseif ($exc.IsInterface -and $reflectionType.getInterFace($exc)) { throw $throwMessage } elseif ($reflectionType.IsInterface -and $exc.getInterFace($reflectionType)) { throw $throwMessage } } } } return $true} , { param($ast) if ($ast -is [Management.Automation.Language.LoopStatementAst] -and $ast.GetType().Name -match '(?>do|while)') { throw "ScriptBlock cannot contain $($ast.GetType().Name)" } return $true } $scriptBlockAst = $_.Ast foreach ($astCondition in $astConditions) { $foundResults = $scriptBlockAst.FindAll($astCondition, $true) if (-not $foundResults) { return $false} } return $true })]$ScriptBlockIsSafe = $this.ScriptBlock <# $this.ScriptBlock.Ast.FindAll({ param($ast) if ($ast -is [Management.Automation.Language.CommandAst]) { throw "AST cannot contain commands" } if ($ast -is [Management.Automation.Language.LoopStatementAst]) { if ($ast.GetType().Name -in 'DoWhileStatementAst','WhileStatementAst', 'DoUntilStatement') { throw "Cannot use $($ast.GetType().Name)" } } if ($ast -is [Management.Automation.Language.TypeExpressionAst]) { $reflectedType = $ast.TypeName.GetReflectionType() if (-not $reflectedType) { throw "Could not resolve $($ast.Typename.FullName)" } if ($reflectedType -notin [Math], [Timespan]) { throw "Unacceptable type" } } }, $true) #> return $true </Script> </ScriptMethod> <ScriptMethod> <Name>IsSafe.ps</Name> <Script> [ValidateScriptBlock( ExcludeCommand='*', NoWhileLoop, IncludeType={ [int],[math],[timespan], [datetime], [string], [string[]],[int[]], [double[]], [switch] } )] $ScriptBlockIsSafe = $this.ScriptBlock <# $this.ScriptBlock.Ast.FindAll({ param($ast) if ($ast -is [Management.Automation.Language.CommandAst]) { throw "AST cannot contain commands" } if ($ast -is [Management.Automation.Language.LoopStatementAst]) { if ($ast.GetType().Name -in 'DoWhileStatementAst','WhileStatementAst', 'DoUntilStatement') { throw "Cannot use $($ast.GetType().Name)" } } if ($ast -is [Management.Automation.Language.TypeExpressionAst]) { $reflectedType = $ast.TypeName.GetReflectionType() if (-not $reflectedType) { throw "Could not resolve $($ast.Typename.FullName)" } if ($reflectedType -notin [Math], [Timespan]) { throw "Unacceptable type" } } }, $true) #> return $true </Script> </ScriptMethod> <ScriptProperty> <Name>Title</Name> <GetScriptBlock> $this.Name -replace '\.tune\.ps1$' -replace '[-_]', ' ' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Tune</Name> <GetScriptBlock> if (-not $this.IsSafe()) { return } if ($this.LastParameters) { $lp = $this.LastParameters & $this @lp } else { & $this } </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>TerminalTunes.Tune</Name> <Members> <ScriptMethod> <Name>GetANSINoteRegex</Name> <Script> [Regex]::new(@' (?<ANSI_Note> \e # An Escape \[ # Followed by a bracket (?> (?<Volume>(?<VolumeOff>0) # 0 is no volume | (?<VolumeLow>[1-3]) # 1-3 is low volume | (?<VolumeHigh>[4-7]) # 4-7 is high volume ))\; # A semicolon separated the volume from the duration # Duration is measured in 1/32 of a second (?<Duration>\d+)\; # A semicolon separates the duration from the note # One or more notes will follow (?<Notes>(?:(?> (?<C5>25) # 25 is C in the 6th octave (MIDI 96) | (?<B5>24) # 24 is B in the 5th octave (MIDI 95) | (?<ASharp5>23) # 23 is A Sharp in the 5th octave (MIDI 94) | (?<A5>22) # 22 is A in the 5th octave (MIDI 93) | (?<GSharp5>21) # 21 is G Sharp in the 5th octave (MIDI 92) | (?<G5>20) # 20 is G in the 5th octave (MIDI 91) | (?<FSharp5>19) # 19 is F Sharp in the 5th octave (MIDI 90) | (?<F5>18) # 18 is F in the 5th octave (MIDI 89) | (?<E5>17) # 17 is F in the 5th octave (MIDI 88) | (?<DSharp5>16) # 16 is D Sharp in the 5th octave (MIDI 87) | (?<D5>15) # 15 is D in the 5th octave (MIDI 86) | (?<CSharp5>14) # 14 is C Sharp in the 5th octave (MIDI 85) | (?<C5>13) # 13 is C in the 5th octave (MIDI 84) | (?<B4>12) # 12 is B in the 4th octave (MIDI 83) | (?<ASharp4>11) # 11 is A Sharp in the 4th octave (MIDI 82) | (?<A4>10) # 10 is A in the 4th octave (MIDI 81) | (?<GSharp4>9) # 9 is G Sharp in the 4th octave (MIDI 80) | (?<G4>8) # 8 is G in the 4th octave (MIDI 79) | (?<FSharp4>7) # 7 is F Sharp in the 4th octave (MIDI 78) | (?<F4>6) # 6 is F in the 4th octave (MIDI 77) | (?<E4>5) # 5 is E in the 4th octave (MIDI 76) | (?<DSharp4>4) # 4 is D Sharp in the 4th octave (MIDI 75) | (?<D4>3) # 3 is D in the 4th octave (MIDI 74) | (?<CSharp4>2) # 2 is C Sharp in the 4th octave (MIDI 73) | (?<C4>1) # 1 is C in the 4th octave (MIDI 72) )\;?){0,}),~ # A command and a tilda end the sequence ) '@, 'IgnoreCase,IgnorePatternWhitespace') </Script> </ScriptMethod> <ScriptMethod> <Name>GetNotes</Name> <Script> $ansiNote = $this.GetANSINoteRegex() if ($this.Tune) { foreach ($match in $ansiNote.Matches($this.Tune)) { $matchOut = [Ordered]@{} $noteStart = 0 foreach ($group in $match.Groups) { if ($group.Name -eq 'Volume') { $matchOut[$group.Name] = $group.Value -as [int] } elseif ($group.Name -eq 'Duration') { $matchOut[$group.Name] = [TimeSpan]::FromMilliseconds(($group.Value -as [int]) * (1/32) * 1000) } elseif ($group.Name -eq 'Notes') { $matchOut[$group.Name] = @() $noteStart = $group.Index } elseif ($noteStart -and $group.Success) { $matchOut.Notes += $group.Name -replace 'Sharp','#' } } $matchOut.Tune = $match.Value [PSCustomObject]$matchOut } } </Script> </ScriptMethod> <ScriptMethod> <Name>Play</Name> <Script> param( [Collections.IDictionary] $Parameter ) if ($this.IsGenerator) { $this | Add-Member LastParameters $Parameter -Force } if (-not $this.Tune) { return } [Console]::Write([Regex]::Replace($this.Tune, '[`\\]e', {"`e"})) </Script> </ScriptMethod> <ScriptProperty> <Name>Duration</Name> <GetScriptBlock> if (-not $this.CachedNoteCount) { $notes = @($this.GetNotes()) [Timespan]$duration = 0 $noteCount = 0 foreach ($note in $notes) { $duration += ($note.Duration * ($note.Notes.Length)) $noteCount += $note.Notes.Length } $this | Add-Member NoteProperty CachedDuration $duration -Force $this | Add-Member NoteProperty CachedNoteCount $noteCount -Force } if ($this.CachedDuration) { $this.CachedDuration } else { $duration } </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>IsGenerator</Name> <GetScriptBlock> $this -is [Management.Automation.ExternalScriptInfo] </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>NoteCount</Name> <GetScriptBlock> if (-not $this.CachedNoteCount) { $notes = @($this.GetNotes()) [Timespan]$duration = 0 $noteCount = 0 foreach ($note in $notes) { $duration += ($note.Duration * ($note.Notes.Length)) $noteCount += $note.Notes.Length } $this | Add-Member NoteProperty CachedDuration $duration -Force $this | Add-Member NoteProperty CachedNoteCount $noteCount -Force } if ($this.CachedNoteCount) { $this.CachedNoteCount } else { $noteCount } </GetScriptBlock> </ScriptProperty> </Members> </Type> </Types> |