Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Start/Stop Your Music Player with your Headphones

0.00/5 (No votes)
8 Apr 2010 1  
An application that starts your music app when you plug in the headphones and stops it when you unplug it!

Introduction

I tend to listen to music quite a lot while I work. And, of course, I have to use headphones to keep my colleagues from beating me up. Recently I started using my mobile phone as my music player. Since I have to move around the office now and then, I constantly found myself unplugging and plugging in my headphones. And every time I had to unplug the headphones, I would first have to stop the music player to stop it from blaring out Maiden tracks. And of course, since I had stopped it earlier, I would need to start it again when I returned to my seat! I needed a way of starting the music player when I plugged in the headphones and stopping it when I unplugged it.

And thus was born this application.

Using the Code

Note: This project uses OpenNETCF or Smart Device Framework as it is called now. It’s great! You can get a copy from http://www.opennetcf.com/.

Another note: I'm not an applications developer and am quite new to C#. So my code probably does not look very professional. But the intention here is only to present the idea and not the application itself.

The code itself is pretty simple. It does the following;

  1. On startup, checks if another instance is running. If yes, the app checks with the user to determine if he/she wants to stop the application.
  2. Registers a ChangeEventHandler for the property SystemProperty.HeadsetPresent.
  3. Starts or Stops the music player application based on the change event notification
  4. Goes to sleep a lot
using System;
using System.Windows.Forms;
using Microsoft.WindowsMobile.Status;
using System.Diagnostics;
using OpenNETCF.ToolHelp;
using System.Threading;
using System.Runtime.InteropServices;
using System.Reflection;

namespace AutoNitro
{
  static class Program
  {
    static SystemState bHPState;

    // Music application name and path. Change here if your music application 
    // is different
    const string MUSIC_APP_EXE_NAME = "Nitrogen.exe";
    const string MUSIC_APP_PROGRAM_FOLDER = "\\Program Files\\Nitrogen";

    public const Int32 NATIVE_ERROR_ALREADY_EXISTS = 183;

    // .NetCF does not export CreateMutex. We have to explicitly import it here
    [DllImport("coredll.dll", EntryPoint = "CreateMutex", SetLastError = true)]
    public static extern IntPtr CreateMutex(IntPtr lpMutexAttributes,
                                            bool InitialOwner,
                                            string MutexName);

    /*************************************************************************/
    /*************************************************************************/
    /*************************************************************************/
    [MTAThread]
    static void Main()
    {
      // The name of this application
      String sThisApp = Assembly.GetExecutingAssembly().GetName().Name + ".exe";

      // Check if an instance is already running by trying to create a mutex
      // with a fixed name. If mutex already exists, we assume that this is
      // because another instance is running!
      IntPtr hMutex = CreateMutex(IntPtr.Zero, true, "AutoNitro");
      if (Marshal.GetLastWin32Error() == NATIVE_ERROR_ALREADY_EXISTS)
      {
        if (DialogResult.Yes == MessageBox.Show(sThisApp +
                               " is already running. Do you want to close it?",
                                                sThisApp,
                                                MessageBoxButtons.YesNo,
                                                MessageBoxIcon.Question,
                                                MessageBoxDefaultButton.Button1))
        {
          // Kill 'em All!  
          ProcessEntry[] processes = OpenNETCF.ToolHelp.ProcessEntry.GetProcesses();
          foreach (OpenNETCF.ToolHelp.ProcessEntry process in processes)
          {
            if (String.Compare(process.ExeFile,
                               sThisApp,
                               StringComparison.InvariantCultureIgnoreCase) == 0)
            {
              process.Kill();
            }
          }
        }
        return;
      }

      // Register to be notified for any change to the HeadsetPreset property
      bHPState = new SystemState(SystemProperty.HeadsetPresent);
      bHPState.Changed += bState_Changed;

      // Probably better to implement a message loop here instead of sleeping 
      // and DoEvents
      while (true)
      {
        Application.DoEvents();
        Thread.Sleep(1000);
      }
    }

    /*************************************************************************/
    /*************************************************************************/
    /*************************************************************************/
    // Returns true if the application with the name passed as parameter is
    // currently running
    static bool IsApplicationRunning(string pAppName)
    {
      ProcessEntry[] processes = OpenNETCF.ToolHelp.ProcessEntry.GetProcesses();
      foreach (OpenNETCF.ToolHelp.ProcessEntry process in processes)
      {
        if (String.Compare(process.ExeFile, 
                           pAppName, 
                           StringComparison.InvariantCultureIgnoreCase) == 0)
        {
          return true;
        }
      }
      return false;
    }

    /*************************************************************************/
    /*************************************************************************/
    /*************************************************************************/
    // Shutsdown all running instances of the application pAppName
    static void TerminateApplication(string pAppName)
    {
      ProcessEntry[] processes = OpenNETCF.ToolHelp.ProcessEntry.GetProcesses();
      foreach (OpenNETCF.ToolHelp.ProcessEntry process in processes)
      {
        if (String.Compare(process.ExeFile,
                           pAppName,
                           StringComparison.InvariantCultureIgnoreCase) == 0)
        {
          // We can directly kill the process here but it is not safe.
          // I don't prefer killing because the music app will not remember your
          // last played track and position if you kill it. 
          // Instead ask for a shutdown politely.
		  int iPID = (int)process.ProcessID
          Process p = System.Diagnostics.Process.GetProcessById(iPID);
          p.CloseMainWindow();
        }
      }
    }

    /*************************************************************************/
    /*************************************************************************/
    /*************************************************************************/
    private static void LaunchApplication(string pAppName)
    {
      System.Diagnostics.Process.Start(pAppName, "");
    }

    /*************************************************************************/
    /*************************************************************************/
    /*************************************************************************/
    static void bState_Changed(object sender, ChangeEventArgs args)
    {
      Boolean blNewHPState = Convert.ToBoolean(args.NewValue);
      bool blAppRunState = IsApplicationRunning(MUSIC_APP_EXE_NAME);

      if (!blNewHPState)
      {
        if (true == blAppRunState)
        {
          TerminateApplication(MUSIC_APP_EXE_NAME);
        }
      }
      else
      {
        if (false == blAppRunState)
        {
          string sApp = MUSIC_APP_PROGRAM_FOLDER + "\\" + MUSIC_APP_EXE_NAME;
          try
          {
            LaunchApplication(sApp);
          }
          catch
          {
            throw new Exception("Failed to start music player.\nPath was " + sApp);
          }
        }
      }
    }
  }
}

I use Nitrogen as my music player. The name and path of this application is hard coded in this app because I'm pretty lazy. You might want to change this if you use a different player.

Points of Interest

The tricky part of writing this application was to do with shutting down the application safely and in the right way. This aspect seems to be poorly documented or is poorly supported in .NET CF.

Things I Should Probably Do

  1. Allow user to select the music player instead of hard-coding it
  2. Get rid of the Sleep and DoEvents business and implement a proper main loop

History

  • 8th April, 2010: Initial post

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here