EasyPlayer Roundup

Last time I talked about EasyPlayer, I'd just finished off the main media player view. I've now reached the point where I'm using it daily to listen to my various set of podcasts.

The main addition has been the 'podcast play' widget and it's been interesting how this fit in with the whole MVVM structure I have in place.

Thankfully it went pretty well. First, let me briefly describe what I want: as MP3's are downloaded, they should be added to a playlist. When a podcast has finished playing, it should get removed from the playlist and the next item at the top of the playlist should start playing.

Playing

MP3's are currently started from the 'Library' widget:

public void PlayMediaItem(MediaItem item)
{
  eventAgg.Publish(new PlayRequestMessage(item));
}

Listening to PlayRequestMessage events is the NowPlayingViewModel:

public void Handle(PlayRequestMessage message)
{
  // ... start playing message.Media ...

This creates a nice decoupling of the views - which of course is the aim - so in the podcast player widget, I simply need to publish PlayRequestMessages and the media control will do the rest. The only thing that is missing is an event to capture when something has stopped playing, so the podcast player can send a request to start playing the next item.

A method was already present to capture MediaEnded, so it couldn't have been easier to simply add a publish event call:

public void MediaEnded()
{
  Stop();
  eventAgg.Publish(new NowPlayingMediaEndedMessage(currentlyPlaying));
}

EasyPlayer Playlist Widget

Caliburn.Micro

The code for the podcast play widget is slightly more involved than implied above, as I implemented playlist ordering, persistence and an excluded items list. I also only wanted to auto-play items if you actually start playing from the podcast play widget. But nonetheless, I'm still pretty happy with the implementation. I feel I'm probably missing some cool features of Silverlight and/or Caliburn.Micro, but I do like the way Caliburn.Micro guided me down the MVVM path and kept out a lot of ugly UI-related gunk from the ViewModel classes.

Even upgrading to Caliburn.Micro 1.2 caused only one problem in my tests. Previously, the IEventAggregator.Publish method took an optional Action marshal argument. Using Moq to Verify the call, I had to specify null, as expression trees can't handle optional parameters:

eventAgg.Verify(e => e.Publish(It.Is<PlayRequestMessage>(p => p.Media.Id == "test-2"), null));

In 1.2, it is an overload instead of an optional argument, therefore my tests failed. Simply removing the null fixed it.

And my UI is pretty ugly! But I can't have it all.

The list goes on

There are a couple more additions I'd like to make before I'd consider it fairly "feature complete": firstly auto-downloading from RSS feeds and secondly once the podcast player has played an item, auto-delete it after a given amount of time, say a week.


Comment Guidelines
See the FAQ for details on the full rules and guidelines. No Spam. Write clearly and thoughtfully - no bad language.