/// <summary> /// Adds a message to the queue. /// </summary> /// <param name="message">The message to add to the queue.</param> /// The message must have a valid timestamp (not MidiMessage.Now), but other than that /// there is no restriction on the timestamp. For example, it is legal to add a message with /// a timestamp earlier than some other message which was previously removed from the queue. /// Such a message would become the new "earliest" message, and so would be be the first message /// returned by PopEarliest(). public void AddMessage(Message message) { // If the list is empty or message is later than any message we already have, we can add this // as a new timeslice to the end. if (IsEmpty || message.Time > messages.Last.Value[0].Time) { List<Message> timeslice = new List<Message>(); timeslice.Add(message); messages.AddLast(timeslice); return; } // We need to scan through the list to find where this should be inserted. LinkedListNode<List<Message>> node = messages.Last; while (node.Previous != null && node.Value[0].Time > message.Time) { node = node.Previous; } // At this point, node refers to a LinkedListNode which either has the correct // timestamp, or else a new timeslice needs to be added before or after node. if (node.Value[0].Time < message.Time) { List<Message> timeslice = new List<Message>(); timeslice.Add(message); messages.AddAfter(node, timeslice); } else if (node.Value[0].Time > message.Time) { List<Message> timeslice = new List<Message>(); timeslice.Add(message); messages.AddBefore(node, timeslice); } else { node.Value.Add(message); } }
/// <summary> /// Schedules a single message based on its beatTime. /// </summary> /// <param name="message">The message to schedule.</param> /// <remarks> /// <para>This method schedules a message to be sent at the time indicated in the message's /// <see cref="Message.Time"/> property. It may be called at any time, whether /// the clock is running or not. The message will not be sent until the clock progresses /// to the specified time. (If the clock is never started, or is paused before that time /// and not re-started, then the message will never be sent.)</para> /// <para>If a message is scheduled for a time that has already passed, then the scheduler /// will send the message at the first opportunity.</para> /// </remarks> public void Schedule(Message message) { lock (threadLock) { threadMessageQueue.AddMessage(message); Monitor.Pulse(threadLock); } }