This is the fourth in a series.
With our "design" out of the way, we can start digging in to the actual implementation. Our first draft will be somewhat exploratory in nature. Given my limited knowledge of the Windows Media Player plug-in architecture, I have decided to start by hosting the WMP ActiveX control in a standalone WinForms application, and have this WinForms application host a WCF service. So, here goes:
We'll start off by designing the communication contract through which our client controls and queries our media player. For now, we'll concentrate on controlling the media player. For this, we'll use a WCF contract called INowPlayingService:
[ServiceContract] public interface INowPlayingService { [OperationContract] PlayState GetPlayState(); [OperationContract] Song GetCurrentSong(); [OperationContract] List<Song> GetCurrentPlaylist(); [OperationContract] void VolumeUp(int amount); [OperationContract] void VolumeDown(int amount); [OperationContract] void SetVolume(int volume); [OperationContract] void MoveNext(); [OperationContract] void MovePrevious(); [OperationContract] void Play(); [OperationContract] void Pause(); [OperationContract] void Stop(); [OperationContract] void SetRandom(bool random); [OperationContract] void SetRepeat(bool repeat); [OperationContract] void SetMute(bool mute); [OperationContract] List<Song> AddToCurrentPlaylist(List<Song> playlist); [OperationContract] void PlayInPlaylist(Song song); [OperationContract] void ReplaceCurrentPlaylist(List<Song> playlist); }
That looks like a pretty comprehensive list of operations we would want to perform on a media player. So, let's get down to the business of actually implementing this in Visual Studio 2008. I start a new solution and add three projects, a WinForms host application, a WinForms Client application, and WCF Service Library. I add a project reference from the host application to the service library. Then, I notice I can add a service reference from the client application to the service library. Right click on the project, click add service reference, click discover->services in this solution, and choose the service of interest. Nice! Or, so I thought.
Here's where the first problem arises. Remember, I'm using this as an exercise to get my head around the new technologies. The WCF service library project type does a nice job of housing the service components as well as publishing the appropriate meta data for things like adding service references. However, when I go to debug this application, VS automatically spins up the WcfSvcHost process to host our service library. But, remember, I want to host the WCF endpoint within my host WinForms application. No matter what projects you tell VS to start up (or not start up) on debug, it ALWAYS runs the WcfSvcHost application and starts hosting my service library.
It turns out, I'm not the first person to have this problem: Visual Studio 2008, WCF Service Libraries, and CTRL-F5. It appears that the solution is to "remove the project type GUID" that tells VS that it's a WCF Service Library. What? So, in order to host a WCF service library in my own application, I have to disable all of the helpful aspects of VS regarding WCF endpoints (like, say, updating my service reference as the contract changes over time). Ridiculous.
Here's how I finally resolved it. Leave it as a WCF service library, but change the port values in the app.conf sections so my host uses a different port than the WCF service library. That way, in the course of normal debugging, the client points to the ports opened by my host. When I need to update the reference, I change the port to the VS host port, update the reference, and then change it back. It's a nasty bit of kludgery, but it works for my needs. It seems like I must be making a habit of doing things Microsoft doesn't expect. First, I expected a standard windows application to be simple in WPF, now this.
Anyway, source code (so far) is available here. You'll want to change the URL property of the media player control in the host application. You'll also want to set the startup projects so that the host and the client are both started. It's a pretty basic remote control with standard navigation utilities. Next, we'll flesh out some of the media library functionality so we can change what gets played.
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.