/// <summary> /// Midi out device callback handler. /// </summary> /// <param name="message">The type of callback event.</param> /// <param name="parameter1">First parameter dependent on <paramref name="message"/>.</param> /// <param name="parameter2">Second parameter dependent on <paramref name="message"/>.</param> /// <returns>Returns true when handled.</returns> protected override bool OnMessage(int message, IntPtr parameter1, IntPtr parameter2) { bool handled = true; switch ((uint)message) { case NativeMethods.MOM_OPEN: // don't change status here, MidiSafeHandle has not been set yet. break; case NativeMethods.MOM_CLOSE: Status = MidiPortStatus.Closed; MidiSafeHandle = null; break; case NativeMethods.MOM_DONE: MidiBufferStream buffer = BufferManager.FindBuffer(parameter1); if (buffer != null) { if (NextCallback != null) { NextCallback.LongData(buffer, MidiDataCallbackType.Done); } BufferManager.ReturnBuffer(buffer); } break; default: handled = false; break; } return(handled); }
/// <summary> /// Allocates the unmanaged memory for the midi headers and buffers. /// </summary> private void AllocateBuffers() { if (this.BufferSize > 0 && this.BufferCount > 0) { this.memHeaders = MemoryUtil.Alloc(MemoryUtil.SizeOfMidiHeader * this.BufferCount); this.memBuffers = MemoryUtil.Alloc(this.BufferSize * this.BufferCount); GC.AddMemoryPressure((MemoryUtil.SizeOfMidiHeader + this.BufferSize) * this.BufferCount); IntPtr headerMem = IntPtr.Add(this.memHeaders, 0); IntPtr bufferMem = IntPtr.Add(this.memBuffers, 0); for (int i = 0; i < this.BufferCount; i++) { var buffer = new MidiBufferStream(headerMem, bufferMem, this.BufferSize, this.StreamAccess); try { this.unusedBuffers.Enqueue(buffer); this.mapBuffers.Add(headerMem, buffer); headerMem = IntPtr.Add(headerMem, MemoryUtil.SizeOfMidiHeader); bufferMem = IntPtr.Add(bufferMem, this.BufferSize); } catch { buffer.Dispose(); throw; } } } }
public virtual void ReturnBuffer(MidiBufferStream buffer) { Contract.Requires(buffer != null); Check.IfArgumentNull(buffer, "buffer"); ThrowIfDisposed(); if (!this.mapBuffers.ContainsKey(buffer.HeaderMemory)) { throw new InvalidOperationException("Specified buffer is not owned by this instance."); } if (!this.usedBuffers.Contains(buffer)) { throw new InvalidOperationException("Specified buffer was not in the used buffer list of this instance."); } if ((buffer.HeaderFlags & NativeMethods.MHDR_INQUEUE) > 0) { throw new InvalidOperationException(Properties.Resources.MidiBufferManager_BufferStillInQueue); } //// could be an error ////if ((buffer.HeaderFlags & NativeMethods.MHDR_DONE) == 0) ////{ //// throw new InvalidOperationException(Properties.Resources.MidiBufferManager_BufferNotDone); ////} lock (this.locker) { this.usedBuffers.Remove(buffer); this.unusedBuffers.Enqueue(buffer); } buffer.Position = 0; }
protected override void OnUnprepareBuffer(MidiBufferStream buffer) { Check.IfArgumentNull(buffer, "buffer"); int result = NativeMethods.midiOutUnprepareHeader( MidiPort.MidiSafeHandle, buffer.ToIntPtr(), (uint)MemoryUtil.SizeOfMidiHeader); MidiOutPortBase.ThrowIfError(result); }
protected override void OnPrepareBuffer(MidiBufferStream buffer) { Check.IfArgumentNull(buffer, "buffer"); base.OnPrepareBuffer(buffer); // mark buffers as streams buffer.HeaderFlags |= NativeMethods.MHDR_ISSTRM; }
/// <summary> /// Adds the <paramref name="buffer"/> to the midi port. /// </summary> /// <param name="buffer">Must not be null.</param> private void AddBufferToPort(MidiBufferStream buffer) { Check.IfArgumentNull(buffer, "buffer"); // make sure the stream is rewound. buffer.Position = 0; int result = NativeMethods.midiInAddBuffer( MidiPort.MidiSafeHandle, buffer.ToIntPtr(), (uint)MemoryUtil.SizeOfMidiHeader); MidiInPort.ThrowIfError(result); }
/// <summary> /// Returns the <paramref name="buffer"/> to the pool. /// </summary> /// <param name="buffer">Must not be null.</param> /// <remarks>Call this method when the <paramref name="buffer"/> is no longer needed.</remarks> public override void ReturnBuffer(MidiBufferStream buffer) { Check.IfArgumentNull(buffer, "buffer"); // do not re-add buffers during a Reset (or Close) that is meant to return all // buffers from the MidiInPort to the buffer manager. if (!MidiPort.HasStatus(MidiPortStatus.Reset | MidiPortStatus.Closed)) { // returned buffers are added to the midi in port again // to make them available for recording sysex. AddBufferToPort(buffer); } else { OnUnprepareBuffer(buffer); base.ReturnBuffer(buffer); } }
/// <summary> /// Registers all buffers in the pool with the Midi In Port. /// </summary> /// <exception cref="InvalidOperationException">Thrown when the Midi In Port is not open.</exception> /// <remarks>After <see cref="M:MidiInPort.Reset"/> has been called, all buffers are /// returned to this buffer manager. Use this function to register all the (unused) buffers /// with the midi port again in order to receive long midi messages. /// Note that the <see cref="P:MidiInPort.IsOpen"/> must be true - the port must be open.</remarks> public void RegisterAllBuffers() { if (!MidiPort.IsOpen) { throw new InvalidOperationException(Properties.Resources.MidiInPort_PortNotOpen); } // add unused buffers to port MidiBufferStream buffer = RetrieveBuffer(); while (buffer != null) { OnPrepareBuffer(buffer); AddBufferToPort(buffer); buffer = RetrieveBuffer(); } }
/// <summary> /// Retrieves a fresh (unused) buffer for the application to use. /// </summary> /// <returns>Returns null when no more buffers are unused.</returns> /// <remarks>This method is only called by the application logic for an <see cref="MidiOutPort"/> /// or a <see cref="MidiOutStreamPort"/>. The <see cref="MidiInPort"/> registers its own buffers.</remarks> public virtual MidiBufferStream RetrieveBuffer() { MidiBufferStream buffer = null; if (this.unusedBuffers.Count > 0) { lock (this.locker) { if (this.unusedBuffers.Count > 0) { buffer = this.unusedBuffers.Dequeue(); this.usedBuffers.Add(buffer); } } } return(buffer); }
public override void LongData(MidiBufferStream buffer) { Check.IfArgumentNull(buffer, "buffer"); ////if ((buffer.HeaderFlags & NativeMethods.MHDR_PREPARED) == 0) ////{ //// throw new InvalidOperationException("LongData cannot be called with a MidiBufferStream that has not been prepared."); ////} buffer.BytesRecorded = buffer.Position; int result = NativeMethods.midiStreamOut( MidiSafeHandle, buffer.ToIntPtr(), (uint)MemoryUtil.SizeOfMidiHeader); ThrowIfError(result); }
/// <summary> /// Contract. /// </summary> /// <param name="buffer">Must not be null.</param> void IMidiDataSender.LongData(MidiBufferStream buffer) { Contract.Requires(buffer != null); throw new NotImplementedException(); }
protected abstract void OnUnprepareBuffer(MidiBufferStream buffer);
/// <summary> /// Contract. /// </summary> /// <param name="buffer">Must not be null.</param> protected override void OnUnprepareBuffer(MidiBufferStream buffer) { Contract.Requires(buffer != null); throw new NotImplementedException(); }
/// <summary> /// Contract. /// </summary> /// <param name="buffer">Must not be null.</param> /// <param name="timestamp">No contract.</param> void IMidiDataErrorReceiver.LongError(MidiBufferStream buffer, long timestamp) { Contract.Requires(buffer != null); throw new NotImplementedException(); }
/// <summary> /// Contract. /// </summary> /// <param name="buffer">Must not be null.</param> /// <param name="notificationType">No contract.</param> void IMidiDataCallback.LongData(MidiBufferStream buffer, MidiDataCallbackType notificationType) { Contract.Requires(buffer != null); throw new System.NotImplementedException(); }