Powershell Music Player
Tags: powershell, music, player, coding
Published: 2019-10-31 17:37:40

# Powershell music player

In this post will be create a Powershell script that play a list of songs in a folder you specified.

> I take the example code form the [Music Player v1.0.1](https://www.powershellgallery.com/packages/MusicPlayer/1.0.1/Content/MusicPlayer.psm1) by -Powershell Gallery

> This Music player only takes **7.65KB** in space.

> In RAM like you supposed is between **20MB** and **30MB**.

First we need to create a Powershell file call what ever you want, i call them "PlayMusic.ps1".

Next start to coding the script, we need to receive 5 parameters:

* Music path
* If is on Shuffle playing mode
* If is on Loop playing mode
* If you want to Stop
* File type of songs

with this parameters now will have all the configuration to start plating music, so you ask how to use this parameters in Powershell, yes!! like this:

``` powershell
Param (
    [Alias('P')]  [String] $PathMusic,
    [Alias('Sh')] [switch] $Shuffle, 
    [Alias('St')] [Switch] $Stop, 
    [Alias('L')]  [Switch] $Loop,
    [Alias('Ft')] [String] $fileType
)
```

Next to this at the end of the file we need to put all the logic(right now is a mess) for the terminal input; maybe now works if you put all in one line but i'm no time to try, let's try by yourself's.

``` powershell
#Start-MediaPlayer

If ($Stop. IsPresent) {

    Start-MediaPlayer -St $Stop

}
ElseIf ($PathMusic) {

    If ($Shuffle.IsPresent) {
        If ($fileType) {
            Start-MediaPlayer $ -P $PathMusic -Sh $Shuffle -Ft $fileType
        }
        Else {
            Start-MediaPlayer $ -P $PathMusic -Sh $Shuffle -Ft ".flac"
        }
    }
    ElseIf ($Loop.IsPresent) {
        If ($fileType) {
            Start-MediaPlayer -P $PathMusic -L $Loop -Ft $fileType
        }
        Else {
            Start-MediaPlayer -P $PathMusic -L $Loop -Ft ".flac"
        }
    }    
    Else {
        Start-MediaPlayer -P $PathMusic -Ft ".flac"
    }

}
Else {

    Start-MediaPlayer -Ft ".flac"

}
```

Like you see in the code i use the ".flac" format as default, because this is my prefered music file type.

## Summary

Here you have all the complete code for this script it takes 161 code lines.

``` powershell
# Create a playlist of files from folder

Param(

    [Alias('P')]  [String] $PathMusic,
    [Alias('Sh')] [switch] $Shuffle, 
    [Alias('St')] [Switch] $Stop, 
    [Alias('L')]  [Switch] $Loop,
    [Alias('Ft')] [String] $fileType

)

function Start-MediaPlayer { 

    Param( 
        [Alias('P')]  [String] $Path, 
        [Alias('Sh')] [switch] $Shuffle, 
        [Alias('St')] [Switch] $Stop, 
        [Alias('L')]  [Switch] $Loop,
        [Alias('Ft')] [String] $fileType
    ) 

 

    If ($Stop.IsPresent) { 
        Write-Host "Stoping any Already running instance of Media in background." 
        Get-Job MusicPlayer -ErrorAction SilentlyContinue | Remove-Job -Force 
    } 
    Else {        
        #Caches Path for next time in case you don't enter Path to the music directory 
        If ($Path) { 
            $Path | out-file C:\Temp\Musicplayer.txt 
        } 
        else { 
            If ((Get-Content C:\Temp\Musicplayer.txt -ErrorAction SilentlyContinue).Length -ne 0) { 
                Write-Host "You've not provided a music directory, looking for cached information from Previous use." 
                $Path = Get-Content C:\Temp\Musicplayer.txt 

 

                If (-not (Test-Path $Path)) { 
                    Write-Host "Please provide a Path to a music directory.\nFound a cached directory $Path from previous use, but that too isn't accessible!" 
                    # Mark Path as Empty string, If Cached Path doesn't exist 
                    $Path = ''      
                } 
            } 
            else { 
                Write-Host "Please provide a Path to a music directory." 
            } 
        } 

  

        #initialization Script for back ground job 
        $init = { 
            # Function to calculate duration of song in Seconds 
            Function Get-SongDuration($FullName) { 
                $Shell = New-Object -COMObject Shell.Application 
                $Folder = $shell.Namespace($(Split-Path $FullName)) 
                $File = $Folder.ParseName($(Split-Path $FullName -Leaf)) 
                         
                [int]$h, [int]$m, [int]$s = ($Folder.GetDetailsOf($File, 27)).split(":") 
                         
                $h * 60 * 60 + $m * 60 + $s 
            } 
                     
            # Function to Notify Information balloon message in system Tray 
            Function Show-NotifyBalloon($Message) { 
                [system.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | Out-Null             
                $Global:Balloon = New-Object System.Windows.Forms.NotifyIcon             
                $Balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon((Get-Process -id $pid | Select-Object -ExpandProperty Path))                     
                $Balloon.BalloonTipIcon = 'Info'            
                $Balloon.BalloonTipText = $Message             
                $Balloon.BalloonTipTitle = 'Now Playing'             
                $Balloon.Visible = $true             
                $Balloon.ShowBalloonTip(1000) 
            } 
                     
            Function PlayMusic($Path, $Shuffle, $Loop) { 
                # Calling required assembly 
                Add-Type -AssemblyName PresentationCore 
     
                # Instantiate Media Player Class 
                $MediaPlayer = New-Object System.Windows.Media.Mediaplayer 
                         
                # Crunching the numbers and Information 
                $FileList = Get-ChildItem $Path -Recurse -Include *$fileType* | Select-Object fullname, @{n = 'Duration'; e = { get-songduration $_.fullname } } 
                $FileCount = $FileList.count 
                $TotalPlayDuration = [Math]::Round(($FileList.duration | Measure-Object -Sum).sum / 60) 
                         
                # Condition to identifed the Mode chosed by the user 
                if ($Shuffle.IsPresent) { 
                    $Mode = "Shuffle" 
                    $FileList = $FileList | Sort-Object { Get-Random }  # Find the target Music Files and sort them Randomly 
                } 
                Else { 
                    $Mode = "Sequential" 
                } 
                         
                # Check If user chose to play songs in Loop 
                If ($Loop.IsPresent) { 
                    $Mode = $Mode + " in Loop" 
                    $TotalPlayDuration = "Infinite" 
                } 
                         
                If ($FileList) {     
                    '' | Select-Object @{n = 'TotalSongs'; e = { $FileCount }; }, @{n = 'PlayDuration'; e = { [String]$TotalPlayDuration + " Mins" } }, @{n = 'Mode'; e = { $Mode } }  
                } 
                else { 
                    Write-Host "No music files found in directory $Path."  
                } 
                         
                Do { 
                    $FileList | ForEach-Object { 
                        $CurrentSongDuration = New-TimeSpan -Seconds (Get-SongDuration $_.fullname) 
                        $Message = "Song : " + $(Split-Path $_.fullname -Leaf) + " `nPlay Duration : $($CurrentSongDuration.Minutes) Mins $($CurrentSongDuration.Seconds) Sec` nMode : $Mode"
                        $MediaPlayer.Open($_.FullName)                    # 1. Open Music file with media player 
                        $MediaPlayer.Play()                                # 2. Play the Music File 
                        Show-NotifyBalloon ($Message)                   # 3. Show a notification balloon in system tray 
                        Start-Sleep -Seconds $_.duration                # 4. Pause the script execution until song completes 
                        $MediaPlayer.Stop()                             # 5. Stop the Song 
                        $Balloon.Dispose(); $Balloon.visible = $false                            
                    } 
                }While ($Loop) # Play Infinitely If 'Loop' is chosen by user 
            } 
        } 

 

        # Removes any already running Job, and start a new job, that looks like changing the track 
        If ($(Get-Job Musicplayer -ErrorAction SilentlyContinue)) { 
            Get-Job MusicPlayer -ErrorAction SilentlyContinue | Remove-Job -Force 
        } 

 

        # Run only if Path was Defined or retrieved from cached information 
        If ($Path) { 
            Write-Host "Starting a background Job to play Music files" 
            Start-Job -Name MusicPlayer -InitializationScript $init -ScriptBlock { playmusic $args[0] $args[1] $args[2] } -ArgumentList $Path, $Shuffle, $Loop | Out-Null 
            Start-Sleep -Seconds 3       # Sleep to allow media player some breathing time to load files 
            Receive-Job -Name MusicPlayer | Format-Table @{n = 'TotalSongs'; e = { $_.TotalSongs }; alignment = 'left' }, @{n = 'TotalPlayDuration'; e = { $_.PlayDuration }; alignment = 'left' }, @{n = 'Mode'; e = { $_.Mode }; alignment = 'left' } -AutoSize 
        } 
    }      

}

#Start-MediaPlayer
If ($Stop. IsPresent) {

    Start-MediaPlayer -St $Stop

}
ElseIf ($PathMusic) {

    If ($Shuffle.IsPresent) {
        If ($fileType) {
            Start-MediaPlayer $ -P $PathMusic -Sh $Shuffle -Ft $fileType
        }
        Else {
            Start-MediaPlayer $ -P $PathMusic -Sh $Shuffle -Ft ".flac"
        }
    }
    ElseIf ($Loop.IsPresent) {
        If ($fileType) {
            Start-MediaPlayer -P $PathMusic -L $Loop -Ft $fileType
        }
        Else {
            Start-MediaPlayer -P $PathMusic -L $Loop -Ft ".flac"
        }
    }    
    Else {
        Start-MediaPlayer -P $PathMusic -Ft ".flac"
    }

}
Else {

    Start-MediaPlayer -Ft ".flac"

}
```