Click here to Skip to main content
15,911,789 members
Home / Discussions / C#
   

C#

 
AnswerRe: PInvoke, varaible length arrays Pin
Luc Pattyn14-Aug-09 11:46
sitebuilderLuc Pattyn14-Aug-09 11:46 
GeneralRe: PInvoke, varaible length arrays Pin
Pete O'Hanlon14-Aug-09 11:54
mvePete O'Hanlon14-Aug-09 11:54 
GeneralRe: PInvoke, varaible length arrays Pin
Luc Pattyn14-Aug-09 11:56
sitebuilderLuc Pattyn14-Aug-09 11:56 
GeneralRe: PInvoke, varaible length arrays Pin
Pete O'Hanlon14-Aug-09 11:59
mvePete O'Hanlon14-Aug-09 11:59 
GeneralRe: PInvoke, varaible length arrays Pin
Luc Pattyn14-Aug-09 12:03
sitebuilderLuc Pattyn14-Aug-09 12:03 
GeneralRe: PInvoke, varaible length arrays [Solved] Pin
DaveyM6914-Aug-09 12:09
professionalDaveyM6914-Aug-09 12:09 
GeneralRe: PInvoke, varaible length arrays [Solved] Pin
Luc Pattyn14-Aug-09 12:17
sitebuilderLuc Pattyn14-Aug-09 12:17 
GeneralRe: PInvoke, varaible length arrays [Solved] Pin
DaveyM6914-Aug-09 12:54
professionalDaveyM6914-Aug-09 12:54 
In case you're interested - this is the working test code.

This is just for testing - the actual app will have lots of error checking/exception catching, the PInvoke stuff will be alot safer, stuff will be handled in threads and events used to unprepare buffers and close streams etc... but it shows how complicated something like this can be to get just right!
using System;
using System.Runtime.InteropServices;

namespace MIDITest
{
    public delegate void MidiProc(IntPtr hMidiIn, int wMsg, int dwInstance, uint dwParam1, uint dwParam2);

    class Program
    {
        static void Main(string[] args)
        {
            MIDI midi = new MIDI();
            midi.BrokenCMajorTriad();
            Console.ReadKey();
        }
    }

    class MIDI
    {
        MidiProc midiProc;

        public void BrokenCMajorTriad()
        {
            midiProc = MessageHandler;
            int id = 0;
            IntPtr handle = IntPtr.Zero;
            int result = 0;

            Console.WriteLine("Stream Out Message");
            Console.WriteLine("------------------");
            MIDIHDR header = new MIDIHDR();


            MIDIEVENT ev0 = new MIDIEVENT();
            ev0.dwEvent = 0x00403C90;

            MIDIEVENT ev1 = new MIDIEVENT();
            ev1.dwDeltaTime = 10;
            ev1.dwEvent = 0x00404090;

            MIDIEVENT ev2 = new MIDIEVENT();
            ev2.dwDeltaTime = 10;
            ev2.dwEvent = 0x00404390;

            MIDIEVENT ev3 = new MIDIEVENT();
            ev3.dwDeltaTime = 80;
            ev3.dwEvent = 0x00403C80;

            MIDIEVENT ev4 = new MIDIEVENT();
            ev4.dwDeltaTime = 0;
            ev4.dwEvent = 0x00404080;

            MIDIEVENT ev5 = new MIDIEVENT();
            ev5.dwDeltaTime = 0;
            ev5.dwEvent = 0x00404380;

            MIDIEVENT[] events = new MIDIEVENT[] 
            {
                ev0, ev1, ev2, ev3, ev4, ev5
            };
            int eventSize = Marshal.SizeOf(typeof(MIDIEVENT));
            int blockSize = eventSize * events.Length;
            IntPtr eventPointer = Marshal.AllocHGlobal(blockSize);
            for (int i = 0; i < events.Length; i++)
                Marshal.StructureToPtr(events[i], (IntPtr)((int)eventPointer + (eventSize * i)), false);
            
            result = midiStreamOpen(ref handle, ref id, 1, midiProc, 0, CALLBACK_FUNCTION);
            header.lpData = eventPointer;
            header.dwBufferLength = blockSize;
            header.dwBytesRecorded = blockSize;
            int headerSize = Marshal.SizeOf(header);
            IntPtr headerPointer = Marshal.AllocHGlobal(headerSize);
            Marshal.StructureToPtr(header, headerPointer, false);
            result = midiOutPrepareHeader(handle, headerPointer, headerSize);
            result = midiStreamOut(handle, headerPointer, headerSize);
            result = midiStreamRestart(handle);
            while (((BufferFlags)Marshal.ReadInt32(headerPointer, 16) & BufferFlags.Done) != BufferFlags.Done)
            { }
            result = midiOutUnprepareHeader(handle, headerPointer, headerSize);
            Marshal.FreeHGlobal(headerPointer);
            Marshal.FreeHGlobal(eventPointer);
            System.Threading.Thread.Sleep(2000);
            result = midiStreamClose(handle);
            handle = IntPtr.Zero;
        }

        void MessageHandler(IntPtr hMidiIn, int wMsg, int dwInstance, uint dwParam1, uint dwParam2)
        {
            switch (wMsg)
            {
                case MOM_OPEN:
                    Console.WriteLine("Opened");
                    break;
                case MOM_CLOSE:
                    Console.WriteLine("Closed");
                    break;
                case MOM_DONE:
                    Console.WriteLine("Done");
                    break;
            }
        }

        [Flags]
        public enum BufferFlags
        {
            None = 0,
            Done = MHDR_DONE,
            Prepared = MHDR_PREPARED,
            Queued = MHDR_INQUEUE,
            ISStream = MHDR_ISSTRM
        }

        // Source MMSystem.h
        public const int CALLBACK_FUNCTION = 0x00030000;
        public const int MOM_OPEN = 0x3C7;
        public const int MOM_CLOSE = 0x3C8;
        public const int MOM_DONE = 0x3C9;
        public const int MHDR_DONE = 0x00000001;
        public const int MHDR_PREPARED = 0x00000002;
        public const int MHDR_INQUEUE = 0x00000004;
        public const int MHDR_ISSTRM = 0x00000008;

        // Function References: http://msdn.microsoft.com/en-us/library/ms712038(VS.85).aspx
        [DllImport("winmm.dll")]
        public static extern int midiOutPrepareHeader(
            IntPtr hmo,
            IntPtr lpMidiOutHdr,
            int cbMidiOutHdr);

        [DllImport("winmm.dll")]
        public static extern int midiOutUnprepareHeader(
            IntPtr hmo,
            IntPtr lpMidiOutHdr,
            int cbMidiOutHdr);

        [DllImport("winmm.dll")]
        public static extern int midiStreamClose(
            IntPtr hStream);

        [DllImport("winmm.dll")]
        public static extern int midiStreamOpen(
            ref IntPtr lphStream,
            ref int puDeviceID,
            int cMidi,
            MidiProc dwCallback,
            int dwInstance,
            int fdwOpen);

        [DllImport("winmm.dll")]
        public static extern int midiStreamOut(
            IntPtr hMidiStream,
            IntPtr lpMidiHdr,
            int cbMidiHdr);

        [DllImport("winmm.dll")]
        public static extern int midiStreamRestart(
            IntPtr hms);
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct MIDIHDR
    {
        public IntPtr lpData;
        public int dwBufferLength;
        public int dwBytesRecorded;
        public IntPtr dwUser;
        public int dwFlags;
        public IntPtr lpNext;
        public IntPtr reserved;
        public int dwOffset;
        public IntPtr dwReserved;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct MIDIEVENT
    {
        public uint dwDeltaTime;
        public uint dwStreamID;
        public uint dwEvent;
        //public uint[] dwParms; // Only for Sysex stream
    }
}


Dave
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
Why are you using VB6? Do you hate yourself? (Christian Graus)

GeneralRe: PInvoke, varaible length arrays [Solved] Pin
Luc Pattyn14-Aug-09 13:01
sitebuilderLuc Pattyn14-Aug-09 13:01 
GeneralRe: PInvoke, varaible length arrays [Solved] Pin
DaveyM6914-Aug-09 13:08
professionalDaveyM6914-Aug-09 13:08 
GeneralRe: PInvoke, varaible length arrays [Solved] Pin
DaveyM6921-Apr-10 10:38
professionalDaveyM6921-Apr-10 10:38 
AnswerRe: PInvoke, varaible length arrays Pin
Hristo-Bojilov14-Aug-09 12:15
Hristo-Bojilov14-Aug-09 12:15 
GeneralRe: PInvoke, varaible length arrays Pin
DaveyM6914-Aug-09 12:20
professionalDaveyM6914-Aug-09 12:20 
GeneralRe: PInvoke, varaible length arrays [modified] Pin
Hristo-Bojilov14-Aug-09 12:33
Hristo-Bojilov14-Aug-09 12:33 
QuestionUpdate db table Linq Pin
spankyleo12314-Aug-09 10:05
spankyleo12314-Aug-09 10:05 
AnswerCross posted from the LINQ forum Pin
Pete O'Hanlon14-Aug-09 10:33
mvePete O'Hanlon14-Aug-09 10:33 
GeneralRe: Cross posted from the LINQ forum Pin
spankyleo12314-Aug-09 10:39
spankyleo12314-Aug-09 10:39 
GeneralRe: Cross posted from the LINQ forum Pin
Pete O'Hanlon14-Aug-09 10:54
mvePete O'Hanlon14-Aug-09 10:54 
QuestionError handling for WMI queries [Solved] Pin
eeffoc4214-Aug-09 9:32
eeffoc4214-Aug-09 9:32 
AnswerRe: Error handling for WMI queries Pin
Saksida Bojan14-Aug-09 9:47
Saksida Bojan14-Aug-09 9:47 
AnswerRe: Error handling for WMI queries Pin
Luc Pattyn14-Aug-09 9:48
sitebuilderLuc Pattyn14-Aug-09 9:48 
AnswerRe: Error handling for WMI queries [modified] Pin
Hristo-Bojilov14-Aug-09 10:18
Hristo-Bojilov14-Aug-09 10:18 
QuestionComparing files on another computer. Pin
murktinez14-Aug-09 8:03
murktinez14-Aug-09 8:03 
AnswerRe: Comparing files on another computer. Pin
Saksida Bojan14-Aug-09 8:27
Saksida Bojan14-Aug-09 8:27 
GeneralRe: Comparing files on another computer. Pin
murktinez14-Aug-09 21:00
murktinez14-Aug-09 21:00 

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.