65.9K
CodeProject 正在变化。 阅读更多。
Home

使用耳机启动/停止音乐播放器

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.40/5 (7投票s)

2010 年 4 月 8 日

CPOL

2分钟阅读

viewsIcon

25577

downloadIcon

411

插入耳机时启动音乐应用,拔出耳机时停止音乐应用的应用程序!

引言

我工作时经常听音乐。当然,我必须戴上耳机,以免同事揍我。最近我开始用手机作为音乐播放器。由于我现在需要时不时地在办公室里走动,我经常发现自己不断地拔插耳机。每次我拔掉耳机时,我首先必须停止音乐播放器,以免它播放出Iron Maiden的歌曲。当然,由于我之前已经停止了它,当我回到座位时,我需要再次启动它!我需要一种在插入耳机时启动音乐播放器,在拔出耳机时停止音乐播放器的方法。

因此,这个应用程序诞生了。

Using the Code

注意:这个项目使用OpenNETCF,或者现在称为Smart Device Framework。它很棒!你可以在 http://www.opennetcf.com/ 获取副本。

另一个说明:我不是一个应用程序开发者,而且对C#还很陌生。所以我的代码可能看起来不太专业。但这里的意图只是展示这个想法,而不是应用程序本身。

代码本身很简单。它执行以下操作:

  1. 启动时,检查是否已经运行了另一个实例。如果是,应用程序会与用户确认是否要停止该应用程序。
  2. 为属性 SystemProperty.HeadsetPresent 注册一个 ChangeEventHandler
  3. 根据更改事件通知启动或停止音乐播放器应用程序
  4. 进入休眠状态很多次
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);
          }
        }
      }
    }
  }
}

我使用Nitrogen作为我的音乐播放器。这个应用程序中该应用程序的名称和路径是硬编码的,因为我有点懒。如果你使用不同的播放器,你可能需要更改它。

关注点

编写这个应用程序的棘手之处在于安全且正确地关闭应用程序。这个方面在.NET CF中似乎文档不足或支持不足。

我应该做的事情

  1. 允许用户选择音乐播放器,而不是硬编码它
  2. 消除 SleepDoEvents,并实现一个适当的主循环

历史

  • 2010年4月8日:初始发布
© . All rights reserved.