첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

■ MIDI 출력 장치 설정하기

----------------------------------------------------------------------------------------------------


TestProject.zip


MainForm.cs

 

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Runtime.InteropServices;

using System.Threading;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : Form

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// MIDI 출력 디바이스 리스트

        /// </summary>

        private IList<MIDIOutputDevice> midiOutputDeviceList;

 

        /// <summary>

        /// 디폴트 ID

        /// </summary>

        private int defaultID = -2; // MIDI Mapper는 장치 ID로 -1을 갖고 다른 모든 장치들은 0 이상이다.

 

        /// <summary>

        /// 새로운 ID

        /// </summary>

        private int newID = -2;

 

        /// <summary>

        /// 쓰기 모드 여부

        /// </summary>

        private bool isWriteMode = false;

 

        /// <summary>

        /// 쓰기 결과 여부

        /// </summary>

        private bool isWriteResult = false;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region MIDI 출력 장치 리스트 - MIDIOutputDeviceList

 

        /// <summary>

        /// MIDI 출력 장치 리스트

        /// </summary>

        public IList<MIDIOutputDevice> MIDIOutputDeviceList

        {

            get

            {

                if(this.midiOutputDeviceList == null || this.midiOutputDeviceList.Count == 0)

                {

                    LoadList();

                }

 

                return this.midiOutputDeviceList;

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            Load                                     += new EventHandler(Form_Load);

            this.listView.SelectedIndexChanged       += new EventHandler(listView_SelectedIndexChanged);

            this.selectButton.Click                  += new EventHandler(selectButton_Click);

            this.backgroundWorker.DoWork             += new DoWorkEventHandler(backgroundWorker_DoWork);

            this.backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 폼 로드시 처리하기 - Form_Load(sender, e)

 

        /// <summary>

        /// 폼 로드시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Form_Load(object sender, EventArgs e)

        {

            this.backgroundWorker.RunWorkerAsync();

        }

 

        #endregion

        #region 출력 장치 리스트뷰 선택 인덱스 변경시 처리하기 - listView_SelectedIndexChanged(sender, e)

 

        /// <summary>

        /// 출력 장치 리스트뷰 선택 인덱스 변경시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        void listView_SelectedIndexChanged(object sender, EventArgs e)

        {

            if(this.listView.SelectedItems.Count == 1)

            {

                this.selectButton.Enabled = ((MIDIOutputDevice)this.listView.SelectedItems[0].Tag).ID != this.defaultID;

            }

            else

            {

                this.selectButton.Enabled = false;

            }

        }

 

        #endregion

        #region 선택 버튼 클릭시 처리하기 - selectButton_Click(sender, e)

 

        /// <summary>

        /// 선택 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        void selectButton_Click(object sender, EventArgs e)

        {

            this.isWriteResult = false;

 

            this.selectButton.Enabled          = false;

            this.midiOutputDeviceLabel.Enabled = false;

            this.listView.Enabled              = false;

 

            this.statusLabel.Text = "레지스트리 작성중... 기다려 주시기 바랍니다.";

 

            this.statusLabel.Visible = true;

 

            this.newID = ((MIDIOutputDevice)this.listView.SelectedItems[0].Tag).ID;

 

            this.isWriteMode = true;

 

            this.backgroundWorker.RunWorkerAsync();

        }

 

        #endregion

        #region 백그라운드 작업자 작업시 처리하기 - backgroundWorker_DoWork(sender, e)

 

        /// <summary>

        /// 백그라운드 작업자 작업시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)

        {

            if(this.isWriteMode)

            {

                try

                {

                    MIDIOutputDevice.DefaultDeviceID = this.newID;

 

                    this.isWriteResult = true;

                }

                catch

                {

                    this.isWriteResult = false;

                }

            }

            else

            {

                LoadList();

 

                this.defaultID = MIDIOutputDevice.DefaultDeviceID;

            }

        }

 

        #endregion

        #region 백그라운드 작업자 작업 종료시 처리하기 - backgroundWorker_RunWorkerCompleted(sender, e)

 

        /// <summary>

        /// 백그라운드 작업자 작업 종료시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

        {

            if(this.isWriteMode)

            {

                if(this.isWriteResult)

                {

                    this.statusLabel.Text = "디폴트 MIDI 출력 장치 업데이트가 성공했습니다.";

 

                    this.statusLabel.Update();

 

                    Thread.Sleep(1000);

 

                    this.defaultID = this.newID;

 

                    this.midiOutputDeviceLabel.Enabled = true;

                    this.listView.Enabled      = true;

 

                    this.listView.Focus();

 

                    this.statusLabel.Visible = false;

                }

                else

                {

                    MessageBox.Show

                    (

                        this,

                        "레지스트리 업데이트 중 에러가 발생했습니다.",

                        "레지스트리 에러",

                        MessageBoxButtons.OK,

                        MessageBoxIcon.Error

                    );

 

                    this.midiOutputDeviceLabel.Enabled = true;

                    this.listView.Enabled      = true;

 

                    this.listView.Focus();

 

                    this.selectButton.Enabled = true;

 

                    this.statusLabel.Visible = false;

                }

            }

            else

            {

                int itemCount = 0;

 

                foreach(MIDIOutputDevice midiOutputDevice in this.midiOutputDeviceList)

                {

                    ListViewItem listViewItem = new ListViewItem(midiOutputDevice.ProductName);

 

                    listViewItem.Tag = midiOutputDevice;

 

                    listViewItem.SubItems.Add(new ListViewItem.ListViewSubItem(listViewItem, midiOutputDevice.ID.ToString()));

 

                    this.listView.Items.Add(listViewItem);

 

                    this.listView.Items[itemCount].Selected = (midiOutputDevice.ID == this.defaultID);

                    this.listView.Items[itemCount].Focused  = true;

 

                    itemCount++;

                }

 

                this.midiOutputDeviceLabel.Enabled = true;

                this.listView.Enabled      = true;

 

                this.listView.Focus();

 

                this.statusLabel.Visible = false;

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// 기능

 

        #region 리스트 로드하기 - LoadList()

 

        /// <summary>

        /// 리스트 로드하기

        /// </summary>

        private void LoadList()

        {

            this.midiOutputDeviceList = null;

 

            List<MIDIOutputDevice> midiOutputDeviceList = new List<MIDIOutputDevice>();

 

            int midiOutputDeviceCount = Convert.ToInt32(WIN32API.midiOutGetNumDevs());

 

            if(midiOutputDeviceCount > 0)

            {

                for(int i = 0; i < midiOutputDeviceCount; i++)

                {

                    MIDIOUTCAPS midioutcaps = new MIDIOUTCAPS();

 

                    if(WIN32API.midiOutGetDevCaps(i, ref midioutcaps, (uint)Marshal.SizeOf(midioutcaps)) == WIN32API.MMSYSERR_NOERROR)

                    {

                        midiOutputDeviceList.Add(new MIDIOutputDevice(i, midioutcaps));

                    }

                }

            }

 

            this.midiOutputDeviceList = midiOutputDeviceList.AsReadOnly();

        }

 

        #endregion

    }

}

 

 

MIDIOUTCAPS.cs

 

 

using System;

using System.Runtime.InteropServices;

 

namespace TestProject

{

    /// <summary>

    /// MIDI 출력 성능

    /// </summary>

    [StructLayout(LayoutKind.Sequential)]

    public struct MIDIOUTCAPS

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region Field

 

        /// <summary>

        /// 제조사 ID

        /// </summary>

        public UInt16 ManufacturerID;

 

        /// <summary>

        /// 제품 ID

        /// </summary>

        public UInt16 ProductID;

 

        /// <summary>

        /// 드라이버 버전

        /// </summary>

        public UInt32 DriverVersion;

 

        /// <summary>

        /// 제품명

        /// </summary>

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]

        public string ProductName;

 

        /// <summary>

        /// 디바이스 타입

        /// </summary>

        public UInt16 DeviceType;

 

        /// <summary>

        /// 보이스 수

        /// </summary>

        public UInt16 VoiceCount; // 내부 신세사이저 장치가 지원하는 음성 수, 장치가 포트인 경우 0으로 설정됨

 

        /// <summary>

        /// 동시 노트 최대 수

        /// </summary>

        public UInt16 SimultaneousNoteMaximunCount;

 

        /// <summary>

        /// 채널 마스크

        /// </summary>

        public UInt16 ChannelMask;

 

        /// <summary>

        /// 부가 기능

        /// </summary>

        public UInt32 OptionalFunction;

 

        #endregion

    }

}

 

 

MIDIOutputDevice.cs

 

 

using Microsoft.Win32;

using System.Security.AccessControl;

 

namespace TestProject

{

    /// <summary>

    /// MIDO 출력 장치

    /// </summary>

    public class MIDIOutputDevice

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Constant

        //////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 디폴트 MIDI 출력 디바이스 키

        /// </summary>

        private const string DEFAULT_MIDI_OUTPUT_DEVICE_KEY =

            @"Software\Microsoft\ActiveMovie\devenum\{4EFE2452-168A-11D1-BC76-00C04FB9453B}\Default MidiOut Device";

 

        /// <summary>

        /// MIDI 출력 디바이스 ID 명칭

        /// </summary>

        private const string MIDI_OUTPUT_DEVICE_ID_NAME = "MidiOutId";

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

        //////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// ID

        /// </summary>

        private int id;

 

        /// <summary>

        /// MIDI 출력 성능

        /// </summary>

        private MIDIOUTCAPS midioutcaps;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region 디폴트 장치 ID - DefaultDeviceID

 

        /// <summary>

        /// 디폴트 장치 ID

        /// </summary>

        public static int DefaultDeviceID

        {

            get

            {

                RegistryKey registryKey = null;

 

                try

                {

                    registryKey = Registry.CurrentUser.OpenSubKey(DEFAULT_MIDI_OUTPUT_DEVICE_KEY);

 

                    return (int)registryKey.GetValue(MIDI_OUTPUT_DEVICE_ID_NAME);

                }

                catch

                {

                    return -2;

                }

                finally

                {

                    if(registryKey != null)

                    {

                        registryKey.Close();

                    }

                }

            }

            set

            {

                RegistryKey registryKey = null;

 

                try

                {

                    registryKey = Registry.CurrentUser.OpenSubKey

                    (

                        DEFAULT_MIDI_OUTPUT_DEVICE_KEY,

                        RegistryKeyPermissionCheck.ReadWriteSubTree,

                        RegistryRights.SetValue

                    );

 

                    registryKey.SetValue(MIDI_OUTPUT_DEVICE_ID_NAME, value);

                }

                finally

                {

                    if(registryKey != null)

                    {

                        registryKey.Close();

                    }

                }

            }

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region ID - ID

 

        /// <summary>

        /// ID

        /// </summary>

        public int ID

        {

            get

            {

                return this.id;

            }

        }

 

        #endregion

        #region 제품명 - ProductName

 

        /// <summary>

        /// 제품명

        /// </summary>

        public string ProductName

        {

            get

            {

                return this.midioutcaps.ProductName;

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MIDIOutputDevice(id, midioutcaps)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="id">ID</param>

        /// <param name="midioutcaps">MIDI 출력 성능</param>

        public MIDIOutputDevice(int id, MIDIOUTCAPS midioutcaps)

        {

            this.id          = id;

            this.midioutcaps = midioutcaps;

        }

 

        #endregion

    }

}

 

 

WIN32API.cs

 

 

using System;

using System.Runtime.InteropServices;

 

namespace TestProject

{

    /// <summary>

    /// WIN32 API

    /// </summary>

    public class WIN32API

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Constant

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region Field

 

        /// <summary>

        /// MAXPNAMELEN

        /// </summary>

        public const int MAXPNAMELEN = 32;

 

        /// <summary>

        /// MMSYSERR_BASE

        /// </summary>

        public const uint MMSYSERR_BASE = 0;

 

        /// <summary>

        /// MMSYSERR_NOERROR

        /// </summary>

        public const uint MMSYSERR_NOERROR = MMSYSERR_BASE;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region MIDI 출력 장치 수 구하기 - midiOutGetNumDevs()

 

        /// <summary>

        /// MIDI 출력 장치 수 구하기

        /// </summary>

        /// <returns>MIDI 출력 장치 수 구하기</returns>

        [DllImport("winmm.dll")]

        public static extern UInt32 midiOutGetNumDevs();

 

        #endregion

        #region MIDI 출력 장치 성능 구하기 - midiOutGetDevCaps(deviceID, midioutcaps, midioutcapsSize)

 

        /// <summary>

        /// MIDI 출력 장치 성능 구하기

        /// </summary>

        /// <param name="deviceID">장치 ID</param>

        /// <param name="midioutcaps">MIDIOUTCAPS</param>

        /// <param name="midioutcapsSize">MIDIOUTCAPS 크기</param>

        /// <returns>처리 결과</returns>

        [DllImport("winmm.dll")]

        public static extern UInt32 midiOutGetDevCaps(int deviceID, ref MIDIOUTCAPS midioutcaps, uint midioutcapsSize);

 

        #endregion

    }

}

 

----------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker
TAG

댓글을 달아 주세요