Click here to Skip to main content
15,884,388 members
Home / Discussions / C#
   

C#

 
GeneralRe: Destructor peculiarity Pin
DaveyM6923-Oct-09 8:10
professionalDaveyM6923-Oct-09 8:10 
GeneralRe: Destructor peculiarity Pin
DaveyM6923-Oct-09 9:48
professionalDaveyM6923-Oct-09 9:48 
AnswerRe: Destructor peculiarity Pin
Gideon Engelberth23-Oct-09 7:55
Gideon Engelberth23-Oct-09 7:55 
GeneralRe: Destructor peculiarity Pin
DaveyM6923-Oct-09 9:40
professionalDaveyM6923-Oct-09 9:40 
AnswerRe: Destructor peculiarity Pin
Luc Pattyn27-Oct-09 3:36
sitebuilderLuc Pattyn27-Oct-09 3:36 
GeneralRe: Destructor peculiarity Pin
DaveyM6927-Oct-09 7:04
professionalDaveyM6927-Oct-09 7:04 
GeneralRe: Destructor peculiarity Pin
Luc Pattyn27-Oct-09 7:09
sitebuilderLuc Pattyn27-Oct-09 7:09 
GeneralRe: Destructor peculiarity Pin
DaveyM6927-Oct-09 10:45
professionalDaveyM6927-Oct-09 10:45 
If it helps at all - this is some demo code expanded from the listing I gave here earlier. The actual code is obviously far more involved but this should give you the idea.

Be careful when experimenting with this - if a port is left open and the application exits then it will probably freeze the app and to release the port will require a system reboot. That's why I'm concened about this as that is not a desirable situation. Note, the Input, Output, Port and Manager classes will be in a separate assembly so their internal constructors will not be accessible.

I apologise for the length of the code but I thought it may be hepful.
C#
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace MIDI.Test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Load += new EventHandler(Form1_Load);
            FormClosing += new FormClosingEventHandler(Form1_FormClosing);
        }

        void Form1_Load(object sender, EventArgs e)
        {
            foreach (Port port in Manager.Ports)
            {
                port.Closed += new EventHandler(port_Closed);
                port.Opened += new EventHandler(port_Opened);
                port.Open();
            }
        }

        void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            /* Commenting out the next line will rely on the manager finalizer's call to CloseAll.
             * Doing this seems (confusingly) to be reliable! */
            Manager.CloseAll();
        }

        void port_Closed(object sender, EventArgs e)
        {
            Port port = sender as Port;
            if(port !=null) 
                Console.WriteLine("{0}[{1}] closed", port.Type, port.ID);
        }

        void port_Opened(object sender, EventArgs e)
        {
            Port port = sender as Port;
            if (port != null)
                Console.WriteLine("{0}[{1}] opened", port.Type, port.ID);
        }
    }

    public class Manager
    {
        private static List<Input> inputs;
        private static List<Output> outputs;
        private static List<Port> ports;

        private static Manager manager = new Manager();

        static Manager()
        {
            Initialize();
        }
        private Manager()
        { }

        ~Manager()
        {
            CloseAll();
        }

        public static IList<Input> Inputs
        {
            get { return inputs.AsReadOnly(); }
        }
        public static IList<Output> Outputs
        {
            get { return outputs.AsReadOnly(); }
        }
        public static IList<Port> Ports
        {
            get { return ports.AsReadOnly(); }
        }

        public static void CloseAll()
        {
            foreach (Port port in ports)
                port.Close();
        }

        private static void Initialize()
        {
            int inputCount = Interop.midiInGetNumDevs();
            int outputCount = Interop.midiOutGetNumDevs();

            ports = new List<Port>(inputCount + outputCount);

            inputs = new List<Input>(inputCount);
            if (inputCount > 0)
                for (int i = 0; i < inputCount; i++)
                {
                    inputs.Add(new Input(i));
                    ports.Add(inputs[i]);
                }

            outputs = new List<Output>(outputCount);
            if (outputCount > 0)
                for (int i = 0; i < outputCount; i++)
                {
                    outputs.Add(new Output(i));
                    ports.Add(outputs[i]);
                }
        }
    }

    public class Input : Port
    {
        internal Input(int id)
            : base(PortType.Input, id)
        { }

        public override void Close()
        {
            if (handle != IntPtr.Zero)
            {
                Interop.midiInClose(handle);
                handle = IntPtr.Zero;
            }
        }

        public override void Open()
        {
            if (handle == IntPtr.Zero)
                Interop.midiInOpen(
                    out handle, id, callback, id, Interop.CALLBACK_FUNCTION);
        }
    }

    public class Output : Port
    {
        internal Output(int id)
            : base(PortType.Output, id)
        { }

        public override void Close()
        {
            if (handle != IntPtr.Zero)
            {
                Interop.midiOutClose(handle);
                handle = IntPtr.Zero;
            }
        }

        public override void Open()
        {
            if (handle == IntPtr.Zero)
                Interop.midiOutOpen(
                    out handle, id, callback, id, Interop.CALLBACK_FUNCTION);
        }
    }

    public abstract class Port
    {
        public event EventHandler Opened;
        public event EventHandler Closed;

        internal Interop.MidiProc callback;
        protected IntPtr handle;
        protected int id;

        internal Port(PortType type, int id)
        {
            callback = OnCallback;
            handle = IntPtr.Zero;
            this.id = id;
            Type = type;
        }

        public int ID
        {
            get { return id; }
        }

        public PortType Type
        {
            get;
            private set;
        }

        public abstract void Close();

        protected virtual void OnCallback(IntPtr hMidi, int wMsg, int dwInstance, int dwParam1, int dwParam2)
        {
            switch (wMsg)
            {
                case Interop.MIM_CLOSE:
                case Interop.MOM_CLOSE:
                    OnClosed(EventArgs.Empty);
                    break;
                case Interop.MIM_OPEN:
                case Interop.MOM_OPEN:
                    OnOpened(EventArgs.Empty);
                    break;
            }
        }

        protected virtual void OnClosed(EventArgs e)
        {
            EventHandler eh = Closed;
            if (eh != null)
                eh(this, e);
        }

        protected virtual void OnOpened(EventArgs e)
        {
            EventHandler eh = Opened;
            if (eh != null)
                eh(this, e);
        }

        public abstract void Open();
    }

    public enum PortType
    {
        Input = 0,
        Output = 1
    }

    internal static class Interop
    {
        public const int CALLBACK_FUNCTION = 0x00030000;
        public const int MIM_OPEN = 0x3C1;
        public const int MIM_CLOSE = 0x3C2;
        public const int MOM_OPEN = 0x3C7;
        public const int MOM_CLOSE = 0x3C8;

        public delegate void MidiProc(
            IntPtr hMidi,
            int wMsg,
            int dwInstance,
            int dwParam1,
            int dwParam2);

        [DllImport("winmm.dll")]
        public static extern int midiInClose(
            IntPtr hMidiIn
            );

        [DllImport("winmm.dll")]
        public static extern int midiInGetNumDevs();

        [DllImport("winmm.dll")]
        public static extern int midiInOpen(
            out IntPtr lphMidiIn,
            int uDeviceID,
            MidiProc dwCallback,
            int dwCallbackInstance,
            int dwFlags
            );

        [DllImport("winmm.dll")]
        public static extern int midiOutClose(
            IntPtr hmo
            );

        [DllImport("winmm.dll")]
        public static extern int midiOutGetNumDevs();

        [DllImport("winmm.dll")]
        public static extern int midiOutOpen(
            out IntPtr lphmo,
            int uDeviceID,
            MidiProc dwCallback,
            int dwCallbackInstance,
            int dwFlags
            );
    }
}


Dave

"My code works, but I don't understand why!" - DaveyM69 (Me)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
Why are you using VB6? Do you hate yourself? (Christian Graus)

GeneralRe: Destructor peculiarity Pin
Luc Pattyn27-Oct-09 11:17
sitebuilderLuc Pattyn27-Oct-09 11:17 
GeneralRe: Destructor progress report 1 Pin
Luc Pattyn27-Oct-09 17:20
sitebuilderLuc Pattyn27-Oct-09 17:20 
GeneralRe: Destructor progress report 1 Pin
DaveyM6928-Oct-09 8:58
professionalDaveyM6928-Oct-09 8:58 
GeneralRe: Destructor progress report 1 Pin
Luc Pattyn28-Oct-09 9:54
sitebuilderLuc Pattyn28-Oct-09 9:54 
GeneralRe: Destructor progress report 1 Pin
DaveyM6928-Oct-09 10:52
professionalDaveyM6928-Oct-09 10:52 
GeneralRe: Destructor progress report 1 Pin
DaveyM6928-Oct-09 22:19
professionalDaveyM6928-Oct-09 22:19 
GeneralRe: Destructor progress report 1 Pin
DaveyM6928-Oct-09 9:35
professionalDaveyM6928-Oct-09 9:35 
QuestionTheading problem Pin
Rick van Woudenberg23-Oct-09 0:52
Rick van Woudenberg23-Oct-09 0:52 
AnswerRe: Theading problem Pin
Not Active23-Oct-09 2:49
mentorNot Active23-Oct-09 2:49 
Questionneed some quick help thx : how can i access and open form2 from form1 menu item Pin
KIM K23-Oct-09 0:48
KIM K23-Oct-09 0:48 
AnswerRe: need some quick help thx : how can i access and open form2 from form1 menu item Pin
nagendrathecoder23-Oct-09 0:55
nagendrathecoder23-Oct-09 0:55 
AnswerRe: need some quick help thx : how can i access and open form2 from form1 menu item Pin
Rick van Woudenberg23-Oct-09 0:57
Rick van Woudenberg23-Oct-09 0:57 
Questionhow to update progressbar in Child Form from Parent Form Pin
sandy_55723-Oct-09 0:39
sandy_55723-Oct-09 0:39 
AnswerRe: how to update progressbar in Child Form from Parent Form Pin
Rick van Woudenberg23-Oct-09 1:03
Rick van Woudenberg23-Oct-09 1:03 
GeneralRe: how to update progressbar in Child Form from Parent Form Pin
benjymous23-Oct-09 1:08
benjymous23-Oct-09 1:08 
GeneralRe: how to update progressbar in Child Form from Parent Form Pin
sandy_55723-Oct-09 2:16
sandy_55723-Oct-09 2:16 
AnswerRe: how to update progressbar in Child Form from Parent Form Pin
benjymous23-Oct-09 1:07
benjymous23-Oct-09 1:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.