James O'Neill's Blog

October 21, 2008

PowerShell and Windows Media Player, part 1

Filed under: Music and Media,Powershell,Windows Vista — jamesone111 @ 3:13 pm

Stange bedfellows you might think but why shouldn’t media be scripted ?

I was thinking this a couple of weeks ago. I wanted to run a video before I started a presentation. If the Presentation is due to start at 10:00, and the video is 3 minutes I want to the video to start automatically at 9:57, and step onto the stage at 10:00 exactly as it finishes. I cobbled something together to do that but I didn’t like it. Actually I want to play music before the video. I want a play list of tracks to start at the right time, I want the last one to fade out and go into the video. If people are in their seats before the video starts I want something counting down on screen. Etc.

Now Windows Media Player has an object model and I’ve used it before so how hard could it be ? It turned out to be a little harder than I thought because the object I used in a bit of VB.net aeons ago doesn’t seem to like running in PowerShell. I found Saveen was using a different object so I typed in

$wmp = New-object  –COM WMPlayer.OCX

and I was away… but compared with other things I have worked with recently the Object model is – backward is the nicest word I can use. I can get a play list and I’d expect to be able to do “For each item in list.tracks”. But no: you have to go call list.item(track Number) for each track. To get a playlist you have to request it by name from the “playlist collection” object.  You have to specify the exact name – no wild cards. Yet it comes back as a collection, which again doesn’t work with forEach. Grrr. So I wrote a function to get a playlist.

Function get-Playlist   
{param ($Name)
if ($Name -eq $null) {$wmp.currentPlayList}
else {$list=$wmp.playlistCollection.getByName($Name) 0..($list.count - 1)|foreach {$list.item($_) } }

If the name isn’t specified the function returns the currently playing list, otherwise it gets the named list, and it outputs each list found. All 1 of them.

Next came Set-Playlist – I wanted to be able to do Set-PlayList $listObject or set-playlist “random” or get-Playlist “random” | set-playlist so this became a filter

filter Set-Playlist

{param ($Playlist)
if ($playlist -eq $null) {$playList=$_}
if ($playlist -is [string]) {$playlist=get-playlist $playList}
if ($Playlist -is [system.__ComObject]) {$WMP.currentPlaylist = $playlist}

Of Course I wanted to see the tracks in a play list so that became the next function – again set up to take Piped input, or a name or an object

filter get-MediaInPlaylist  
{param ($Playlist)
if ($playlist -eq $null) {$playList=$_}
if ($playlist -is [string]) {$playlist=Get-Playlist $playList}
if ($playlist -eq $null) {$playList=$wmp.currentPlayList}
0..($Playlist.count - 1) | foreach {$playlist.item($_) }

Getting media which is not in an existing play list involves a query to the mediaCollection object there is get media by name, get media by artist and get media by album. It turns out that any attempt to get media returns a playlist, I could have left it that way and te results could be piped into set-playlist but I wanted to see the tracks, so that was how I built the next function.

function get-media 

{param ($Name, [Switch]$album, [Switch]$artist)
if ($artist)    {$wmp.mediaCollection.getByAuthor($Name)| get-MediaInPlaylist }
elseif ($album) {$wmp.mediaCollection.getByAlbum($Name) | get-MediaInPlaylist }
else {$wmp.mediaCollection.GetByName($name) | get-MediaInPlaylist } 

There’s also a get media by attribute so you can say “Find me all files where the format is MP3.”

function get-mediaByAttribute 
{param ($attribute, $value)
$wmp.mediaCollection.getByAttribute($Attribute,$value)  | get-MediaInPlaylist }

Next I wanted to be able to add the items I’d just found to the current playlist – so in came Append media, and to make sure I could start with an empty list so did Reset-Media.

filter Append-Media

{param ($item , $Playlist)
if ($Item -eq $null) {$Item=$_}
if ($playlist -is [string]) {$playlist=get-playlist $playList}
if ($playlist -eq $null) {$playList=$wmp.currentPlayList}
$item=$null }
Function reset-media {$wmp.currentPlaylist=$wmp.newPlaylist("Playlist","") }

Finally (for now ) came starting and stopping the playlist.

Function Start-media   {$wmp.controls.play() }
Function Stop-media  {$wmp.controls.stop() } 

Function Pause-media {$wmp.controls.pause() }


In the next post I’ll look at waiting for the media to do things, fading music up and down, why this is no good for video and what to do about it.

This post originally appeared on my technet blog.

Blog at WordPress.com.

%d bloggers like this: