//------------------------------------------------------------------------------
void MidiMappingManager::midiCcReceived(const MidiMessage& message,
										double secondsSinceStart)
{
	if(message.isController())
	{
		multimap<int, MidiMapping *>::iterator it;
		multimap<int, MidiAppMapping *>::iterator it2;
		int cc = message.getControllerNumber();
		int value = message.getControllerValue();

		//Check if it matches any MidiMappings.
		for(it=mappings.lower_bound(cc);
			it!=mappings.upper_bound(cc);
			++it)
		{
			it->second->ccReceived(value);
		}

		if(value > 64)
		{
			//Check if it matches any MidiAppMappings.
			for(it2=appMappings.lower_bound(cc);
				it2!=appMappings.upper_bound(cc);
				++it2)
			{
				CommandID id = it2->second->getId();
				MainPanel *panel = dynamic_cast<MainPanel *>(appManager->getFirstCommandTarget(MainPanel::TransportPlay));

				if(panel)
				{
					if(id != MainPanel::TransportTapTempo)
						panel->invokeCommandFromOtherThread(id);
					else
					{
						double tempo = tapHelper.updateTempo(secondsSinceStart);

						if(tempo > 0.0)
							panel->updateTempoFromOtherThread(tempo);
					}
				}
			}
		}
	}
	else if(message.isMidiMachineControlMessage())
	{
		if(PropertiesSingleton::getInstance().getUserSettings()->getBoolValue(L"mmcTransport", false))
		{
			CommandID id = -1;
			MainPanel *panel = dynamic_cast<MainPanel *>(appManager->getFirstCommandTarget(MainPanel::TransportPlay));

			switch(message.getMidiMachineControlCommand())
			{
				case MidiMessage::mmc_stop:
					id = MainPanel::TransportPlay;
					break;
				case MidiMessage::mmc_play:
					id = MainPanel::TransportPlay;
					break;
				case MidiMessage::mmc_rewind:
					id = MainPanel::TransportRtz;
					break;
				case MidiMessage::mmc_pause:
					id = MainPanel::TransportPlay;
					break;
				default:
					break;
			}
			if((id > -1) && panel)
				panel->invokeCommandFromOtherThread(id);
		}
	}
	else if(message.isProgramChange())
	{
		if(PropertiesSingleton::getInstance().getUserSettings()->getBoolValue(L"midiProgramChange", false))
		{
			int newPatch;
			MainPanel *panel = dynamic_cast<MainPanel *>(appManager->getFirstCommandTarget(MainPanel::TransportPlay));

			newPatch = message.getProgramChangeNumber();

			if(panel)
				panel->switchPatchFromProgramChange(newPatch);
		}
	}
}
//==============================================================================
void MidiMonitorEditor::timerCallback ()
{
    MidiBuffer tmpBuffer;
    int hours, minutes, seconds, frames;
    MidiMessage::SmpteTimecodeType timeCode;
    
    MidiMessageCollector* collector = owner->getMessageCollector ();
    collector->removeNextBlockOfMessages (tmpBuffer, 1024);
    
    if (! tmpBuffer.isEmpty())
	{
        String midiLine;

        int samplePos = 0;
        MidiMessage msg (0xf4, 0.0);
        MidiBuffer::Iterator eventIterator (tmpBuffer);

        while (eventIterator.getNextEvent (msg, samplePos))
        {
           midiLine.printf (T("[CH: %d] "), msg.getChannel());

           if (msg.isNoteOnOrOff ())
           {
                midiLine += MidiMessage::getMidiNoteName (msg.getNoteNumber(),
                                                          true, true, 0);
                midiLine += " ";
                midiLine += String ((int) msg.getVelocity ());

                if (msg.isNoteOn())
                {
                    midiLine += " ON";
                }
                else
                {
                    midiLine += " OFF";
                }
           }
           else if (msg.isAllNotesOff())
           {
                midiLine += "ALL NOTES OFF";
           }
           else if (msg.isAllSoundOff())
           {
                midiLine += "ALL SOUND OFF";
           }
           else if (msg.isPitchWheel())
           {
                midiLine += "PITCHWEEL: ";
                midiLine += String (msg.getPitchWheelValue());
           }
           else if (msg.isAftertouch())
           {
                midiLine += "AFTERTOUCH: ";
                midiLine += String (msg.getAfterTouchValue());
           }
           else if (msg.isChannelPressure())
           {
                midiLine += "CHANNELPRESSURE: ";
                midiLine += String (msg.getChannelPressureValue());
           }
           else if (msg.isSysEx())
           {
                midiLine += "SYSEX: ";
                midiLine += String (msg.getSysExDataSize());
                midiLine += " bytes";
           }
           else if (msg.isProgramChange())
           {
                midiLine += "PROGRAM CHANGE: ";
                midiLine += String (msg.getProgramChangeNumber());
                midiLine += " (";
                midiLine += MidiMessage::getGMInstrumentName (msg.getProgramChangeNumber());
                midiLine += ")";
           }
           else if (msg.isController())
           {
                midiLine += "CC: #";
                midiLine += String (msg.getControllerNumber());
                midiLine += " (";
                midiLine += MidiMessage::getControllerName (msg.getControllerNumber());
                midiLine += ") = ";
                midiLine += String (msg.getControllerValue());
           }
            else if (msg.isTimeSignatureMetaEvent ())
            {
                int newNumerator, newDenominator;
                msg.getTimeSignatureInfo (newNumerator, newDenominator);

                midiLine += "TIME SIGNATURE: ";
                midiLine += String (newNumerator);
                midiLine += " / ";
                midiLine += String (newDenominator);
            }
            else if (msg.isTempoMetaEvent ())
            {
                midiLine += "TEMPO: ";
                midiLine += String (msg.getTempoSecondsPerQuarterNote ());
                //midiLine += " ";
                //midiLine += String (msg.getTempoMetaEventTickLength (ticksPerQuarterNote));
            }
            else if (msg.isMidiMachineControlMessage())
            {
                midiLine += "MIDI CONTROL: ";
                
                switch (msg.getMidiMachineControlCommand())
                {
                    case MidiMessage::mmc_stop:             midiLine += "stop"; break;
                    case MidiMessage::mmc_play:             midiLine += "play"; break;
                    case MidiMessage::mmc_deferredplay:     midiLine += "deferredplay"; break;
                    case MidiMessage::mmc_fastforward:      midiLine += "fastforward"; break;
                    case MidiMessage::mmc_rewind:           midiLine += "rewind"; break;
                    case MidiMessage::mmc_recordStart:      midiLine += "recordStart"; break;
                    case MidiMessage::mmc_recordStop:       midiLine += "recordStop"; break;
                    case MidiMessage::mmc_pause:            midiLine += "pause"; break;
                }
            }
            else if (msg.isMidiStart ())
            {
                midiLine += "MIDI START: ";
            }
            else if (msg.isMidiContinue ())
            {
                midiLine += "MIDI CONTINUE: ";
            }
            else if (msg.isMidiStop ())
            {
                midiLine += "MIDI STOP: ";
            }
            else if (msg.isSongPositionPointer ())
            {
                midiLine += "SONG POSITION: ";
                midiLine += String (msg.getSongPositionPointerMidiBeat ());
            }
            else if (msg.isQuarterFrame ())
            {
                midiLine += "QUARTER FRAME: ";
                midiLine += String (msg.getQuarterFrameSequenceNumber ());
                midiLine += " ";
                midiLine += String (msg.getQuarterFrameValue ());
            }
            else if (msg.isFullFrame ())
            {
                midiLine += "FULL FRAME: ";

                msg.getFullFrameParameters (hours, minutes, seconds, frames, timeCode);

                midiLine += String (hours);
                midiLine += ":";
                midiLine += String (minutes);
                midiLine += ":";
                midiLine += String (seconds);
                midiLine += ":";
                midiLine += String (frames);

                midiLine += " timecode: ";
                switch (timeCode) {
                    case MidiMessage::fps24:      midiLine += "fps24"; break;
                    case MidiMessage::fps25:      midiLine += "fps25"; break;
                    case MidiMessage::fps30drop:  midiLine += "fps30drop"; break;
                    case MidiMessage::fps30:      midiLine += "fps30"; break;
                }
            }
            else if (msg.isMidiMachineControlGoto (hours, minutes, seconds, frames))
            {
                midiLine += "MIDI CONTROL GOTO: ";
                midiLine += String (hours);
                midiLine += ":";
                midiLine += String (minutes);
                midiLine += ":";
                midiLine += String (seconds);
                midiLine += ":";
                midiLine += String (frames);
            }

            midiOutputEditor->insertTextAtCursor (midiLine + T("\n"));
        }

	}

}