iTunes Integration with .NET

The following two tabs change content below.
Bryan Headrick is an accomplished Wordpress and WooCommerce plugin developer and is skilled in responsive design, jQuery, SEO, and Conversion Optimization.

Inspiration

A few months back, I took a few lessons at a Ballroom dance studio in Knoxville. During their parties, the owner played the music to dance to on his laptop (which was connected to the sound system). He had just come up with an interesting system to let the students/guests what dance style was playing at the time. He had printed and laminated cards with each dance style, and taped them on one of columns. They were sorted top to bottom in the same order that his playlist was in. Each time a song came to an end, he would go out and pull down the card associated with the song had just played. As the night progressed, he had trouble getting back to take down the cards in time. I wondered if I could design a digital signage solution for this.

Concept

This gave me an idea – I suspected that iTunes or some other music playing software would have an API to allow you to detect when songs changed. It turns out I was right. The play and track-changed events are a little finicky at first, but I managed to get it working consistently. This isn’t incredibly fancy – more like just a proof of concept. When you play a song, it displays the artist and song title at the top, as well as the dance style (which I have stored in the comments field) in the middle. In addition, if iTunes isn’t running when you launch the program, it launches iTunes for you. When you close iTunes, the application closes as well.

Implementation

I think the ideal implementation would involve an LCD screen being mounted in the appropriate position, connected to the laptop using a 50ft VGA cable. The application would have additional code to make it launch in the secondary window and resize to full-screen. Some graphics associated with either the current song or the dance style would also be a nice addition.

httpv://www.youtube.com/watch?v=MP2MJaOK7w8

Here’s some code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using iTunesLib;

namespace WindowsFormsApplication1
{

    public partial class Form1 : Form
    {

        delegate void StringParameterDelegate(string value);
        Label statusIndicator;
        Label CategoryIndicator;
        String comment;
        iTunesApp itunes;
        String curArtist;
        String curAlbum;
        String curTitle;
        Timer Clock;
        public Form1()
        {
            InitializeComponent();
            itunes = new iTunesApp();
            itunes.OnPlayerPlayEvent += new _IiTunesEvents_OnPlayerPlayEventEventHandler(track_changed);
            itunes.OnQuittingEvent += new _IiTunesEvents_OnQuittingEventEventHandler(onItunesExit);
            itunes.OnPlayerPlayingTrackChangedEvent += new _IiTunesEvents_OnPlayerPlayingTrackChangedEventEventHandler(track_changed);
            itunes.OnQuittingEvent += new _IiTunesEvents_OnQuittingEventEventHandler(itunes_quit);
        }

        private void itunes_quit()
        {
            Application.Exit();
        }
        private void Form1_Load(object sender, EventArgs e)
        {

            statusIndicator = new Label();
            //statusIndicator.AutoSize = true;
            statusIndicator.TextAlign = ContentAlignment.MiddleCenter;
            statusIndicator.Size = new Size(this.Width, 50);
            Font font = new Font(FontFamily.GenericSansSerif, 20);
            statusIndicator.Font = font;
            statusIndicator.Location = new Point(0, 0);

            Controls.Add(statusIndicator);
           // statusIndicator.Text = "test";
            statusIndicator.BorderStyle = BorderStyle.None;

            CategoryIndicator = new Label();
            CategoryIndicator.TextAlign = ContentAlignment.MiddleCenter;
            CategoryIndicator.Font = font;
            CategoryIndicator.Location = new Point(0, this.Height / 2);
            CategoryIndicator.Size = new Size(this.Width, 50);
            CategoryIndicator.BorderStyle = BorderStyle.None;
            Controls.Add(CategoryIndicator);

            // iTunes classes

            IITPlaylist mainLibrary = itunes.CurrentPlaylist;
            IITTrackCollection tracks = mainLibrary.Tracks;

            Clock=new Timer();
            Clock.Interval=1000;
            Clock.Start();
            Clock.Tick+=new EventHandler(Timer_Tick);

        }

        private Point CenterControl(int Width, int Height, int vPos)
        {
            Point centered = new Point();
            int wWidth = this.Width;
            int wHeight = this.Height;
            centered.X = wWidth / 2 - Width / 2;
            centered.Y = vPos;
            return centered;
        }
        private Point CenterControl(int Width, int Height)
        {
            Point centered = new Point();
            int wWidth = this.Width;
            int wHeight = this.Height;
            centered.X = wWidth / 2 - Width / 2;
            centered.Y = wHeight / 2 - Height / 2; 

            return centered; 

        }

        public void Timer_Tick(object sender, EventArgs e)
        {
            try
            {
                if (itunes.CurrentTrack.Artist != curArtist | itunes.CurrentTrack.Album != curAlbum | itunes.CurrentTrack.Name != curTitle)
                {
                    track_changed(itunes.CurrentTrack);
                }
            }
            catch
            {
                //Nothing Here! this is just so your the app doesn't blow up if iTunes is busy. instead it will just try again in 1 second
            }
        }
        public void track_changed(object iTrack)
        {
            IITTrack currentTrack = (IITTrack)iTrack;
            string trackName = currentTrack.Name.ToString();
            string artist = currentTrack.Artist;
            string album = currentTrack.Album;
            curTitle = trackName;
            curArtist = artist;
            curAlbum = album;
            comment = currentTrack.Comment.ToString();

          //  if (!itunes.PlayerState.ToString().Contains("Playing")) MessageBox.Show("not playing");
            UpdateStatus(trackName + " - " + artist);

            Application.DoEvents();
        }

        void onItunesExit()
        {
            Application.Exit();
        }
        void UpdateStatus(string value)
        {
            if (InvokeRequired)
            {
                // We're not in the UI thread, so we need to call BeginInvoke

                BeginInvoke(new StringParameterDelegate(UpdateStatus), new object[] { value});
                return;
            }

           // IITTrack currentTrack = itunes.CurrentTrack;

            //statusIndicator.Width = value.Length;
            // Must be on the UI thread if we've got this far
            statusIndicator.Text = value;
           CategoryIndicator.Text = comment;
            //  statusIndicator.Invalidate();
        }

        private void button1_Click(object sender, EventArgs e)
        {

            itunes.Quit();

        }

        private void button2_Click(object sender, EventArgs e)
        {

            if (itunes.PlayerState.ToString().Contains("Playing")) itunes.Pause();
            else
            itunes.Play();
           // MessageBox.Show(itunes.PlayerState.ToString());
        }

        private void button3_Click(object sender, EventArgs e)
        {

            itunes.NextTrack();
        }

        private void button4_Click(object sender, EventArgs e)
        {

            itunes.PreviousTrack();
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            try
            {
                // Remove any handlers from the iTunes COM object.
                itunes.OnPlayerPlayEvent -= track_changed;
                itunes.OnPlayerPlayingTrackChangedEvent -= track_changed;
                // Release the COM object.
                //Marshal.ReleaseComObject(itunes);
            }
            catch (Exception ex)
            {

            }

        }
    }
}