# Configure Track A as MidiTrack input for Track B

**URL:** <https://forum.juce.com/t/configure-track-a-as-miditrack-input-for-track-b/42106>\
**Category:** Tracktion Engine\
**Created:** [October 8, 2020, 12:26am UTC](https://forum.juce.com/t/configure-track-a-as-miditrack-input-for-track-b/42106 "2020-10-08T00:26:03Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![dikadk13](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dikadk13/32/17750_2.png) [@dikadk13](https://forum.juce.com/u/dikadk13)\
**Post date:** [October 8, 2020, 12:26am UTC](https://forum.juce.com/t/configure-track-a-as-miditrack-input-for-track-b/42106/1 "2020-10-08T00:26:03Z")

</div>

I cannot figure out how to configure Midi Input for tracks in project I’m working on.  
I have te::VirtualMidiInputDevice on te::AudioTrack A ("Drum 1 Input"on screenshot) and Arrpegiator plugin on same track.  
I would like to use te::AudioTrack B (“Drum 1” on screenshot) as destination for Midi data sent from te::AudioTrack A, so it get’s recorded into te::MidiClip on te::AudioTrack B (“Drum 1” on screenshot).  
I tried setting te::AudioTrack output and it seem to affect only audio, not Midi

> trackA -\>getOutput().setOutputToTrack(trackB)

Also tried:

> ```
> if (auto* virMidi = dynamic_cast<te::VirtualMidiInputDevice*>(&track->getMidiInputDevice())){
> virMidi->setEnabled(true);
> if(auto instance = edit.getCurrentInstanceForInputDevice(virMidi)){ // and track->getMidiInputDevice() as argument as well
> instance->setRecordingEnabled(*track, true);
> }
> }
> 
> ```

But I’m not getting any instances for this InputDevice

Screenshot from Waveform shows exactly was I want to achieve “Drum 1 Input” track as MidiTrack Input for “Drum 1” and be able to record all generated Midi from Arpeggiator.

Thanks for all help in advance!

 ![Screen Shot 2020-10-07 at 7.59.04 PM](https://us1.discourse-cdn.com/flex026/uploads/juce/original/2X/8/81df7ea254f476aa257a631ef7a678ca9559abf4.png)

---

<div class="post-metadata">

**Author:** ![dave96](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dave96/32/8487_2.png) [@dave96](https://forum.juce.com/u/dave96)\
**Post date:** [October 8, 2020, 9:43am UTC](https://forum.juce.com/t/configure-track-a-as-miditrack-input-for-track-b/42106/2 "2020-10-08T09:43:06Z")

</div>

This is where the myriad of routing options becomes confusing 😉

`setOutputToTrack` sets the “Track Destination” property in Waveform which send the track’s output to the start of the plugin chain of the destination track.

I think what you’re after is using "Drum Input 1"s `WaveInputDevice` as an input to track “Drum 1”.  
This should be achievable with the following:

```auto
                InputDevice& id = sourceTrack->getWaveInputDevice();
                
                // Make the track's InputDeviceInstance visible to the EditPlaybackContext
                edit.getEditInputDevices().getInstanceStateForInputDevice (id);

                if (auto epc = edit.getCurrentPlaybackContext())
                    if (auto sourceTrackInputDeviceInstance = epc->getInputFor (&id))
                        sourceTrackInputDeviceInstance->setTargetTrack (destTrack, inputSlotIndex, moveToTrack);

```

---

<div class="post-metadata">

**Author:** ![dikadk13](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dikadk13/32/17750_2.png) [@dikadk13](https://forum.juce.com/u/dikadk13)\
**Post date:** [October 9, 2020, 12:45am UTC](https://forum.juce.com/t/configure-track-a-as-miditrack-input-for-track-b/42106/3 "2020-10-09T00:45:07Z")

</div>

Hmmm. I tried and didn’t quite work for me.

I’m only receiving Midi Events on “Destination track” if I use inputTrack-\>“getMidiInputDevice()” instead of “getWaveInputDevice()”, but Midi Messages are original from te::VirtualMidiInputDevice, not modified by my Arpeggiator.

I modified MidiRecording Example to demonstrate issue. Added function with all setup I’m doing.

> void createVirtualMidiAndAssignToTrack()

> <https://github.com/dikadk/tracktion_engine/blob/virt_midi_test/examples/MidiRecordingDemo.h#L291>

---

<div class="post-metadata">

**Author:** ![dave96](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dave96/32/8487_2.png) [@dave96](https://forum.juce.com/u/dave96)\
**Post date:** [October 9, 2020, 10:46am UTC](https://forum.juce.com/t/configure-track-a-as-miditrack-input-for-track-b/42106/4 "2020-10-09T10:46:12Z")

</div>

Sorry, the audio/midi device was my mistake, as you say it should be the MIDI device if you want MIDI message 🤦‍♂️

There’s a few problems with your code though, I’m not sure if they are the source of the problem though (I’ve also added some spacing to make it a bit more readable):

```auto
            for (const auto instance : edit->getAllInputDevices())
            {
                DBG(instance->getInputDevice().getName());

                if (instance->getInputDevice().getDeviceType() == te::InputDevice::virtualMidiDevice
                    && instance->getInputDevice().getName() == virtualDeviceName)
                {
                    if (auto inputTrack = EngineHelpers::getOrInsertAudioTrackAt(*edit, 0))
                    {
                        instance->setTargetTrack(*inputTrack, 0, true);
                        instance->isLivePlayEnabled(*inputTrack); //!!! This call doesn't make any sense, it's a const method that returns a bool so won't actually do anything...
                        
                        inputTrack->setName("InputTrack");
                    
                        if (auto destTrack = EngineHelpers::getOrInsertAudioTrackAt(*edit, 1))
                        {
                            destTrack->setName("DestTrack");
                            
                            //Setup MidiTrackInput
                            te::InputDevice& id = inputTrack->getMidiInputDevice();

                            // Make the track's InputDeviceInstance visible to the EditPlaybackContext
                            edit->getEditInputDevices().getInstanceStateForInputDevice (id);

                            if (auto epc = edit->getCurrentPlaybackContext())
                            {
                                if (auto sourceTrackInputDeviceInstance = epc->getInputFor (&id))
                                {
                                    sourceTrackInputDeviceInstance->setRecordingEnabled (*destTrack, true);
                                    sourceTrackInputDeviceInstance->setTargetTrack (*destTrack, 0, true); //!!! This probably needs to go above the setRecordingEnabled call or the setRecordingEnabled will fail as it hasn't been assigned to the track yet
                                    sourceTrackInputDeviceInstance->isLivePlayEnabled(*destTrack); //!!! As above: This call doesn't make any sense, it's a const method that returns a bool so won't actually do anything...
                                }
                            }
                        }
                    }

                    virtualMidi = dynamic_cast<te::VirtualMidiInputDevice * >(&instance->getInputDevice());
                }
            }

```

With those changes, does it work as expected?  
If not, have you stepped through that method to check all your ifs are actually being entered?

---

<div class="post-metadata">

**Author:** ![dikadk13](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dikadk13/32/17750_2.png) [@dikadk13](https://forum.juce.com/u/dikadk13)\
**Post date:** [October 9, 2020, 2:08pm UTC](https://forum.juce.com/t/configure-track-a-as-miditrack-input-for-track-b/42106/5 "2020-10-09T14:08:02Z")

</div>

Thanks for fast reply and sorry for formatting. I usually use CLion and it takes care of it, unlike xCode, which I’ve used for modifying my example.

I updated my code after your remarks. But it still doesn’t work as expected. I don’t see any midi or audio passed “inputTrack” -\> “destTrack”.  
te::InputDeviceInstance\* state looks correct though.

```
<?xml version="1.0" encoding="UTF-8"?>
<INPUTDEVICE sourceTrack="1012" type="MIDI">
  <INPUTDEVICEDESTINATION targetTrack="1002" targetIndex="0" armed="1"/>
</INPUTDEVICE> 

```

* * *

```
                   for (const auto instance : edit->getAllInputDevices())
                    {
                        DBG(instance->getInputDevice().getName());

                        if (instance->getInputDevice().getDeviceType() == te::InputDevice::virtualMidiDevice
                            && instance->getInputDevice().getName() == virtualDeviceName)
                        {
                            if (auto inputTrack = EngineHelpers::getOrInsertAudioTrackAt(*edit, 0))
                            {
                                instance->setTargetTrack(*inputTrack, 0, true);
                                inputTrack->setName("InputTrack");
                            
                                if (auto destTrack = EngineHelpers::getOrInsertAudioTrackAt(*edit, 1))
                                {
                                    destTrack->setName("DestTrack");
                                    
                                    //Setup MidiTrackInput
                                    te::InputDevice& id = inputTrack->getMidiInputDevice();

                                    // Make the track's InputDeviceInstance visible to the EditPlaybackContext
                                    edit->getEditInputDevices().getInstanceStateForInputDevice (id);

                                    if (auto epc = edit->getCurrentPlaybackContext())
                                    {
                                        if (auto sourceTrackInputDeviceInstance = epc->getInputFor (&id))
                                        {
                                            sourceTrackInputDeviceInstance->setTargetTrack (*destTrack, 0, true);
                                            sourceTrackInputDeviceInstance->setRecordingEnabled (*destTrack, true);
                                            
                                            DBG(sourceTrackInputDeviceInstance->state.toXmlString());
                                            DBG(inputTrack->state.toXmlString());
                                            DBG(destTrack->state.toXmlString());
                                        }
                                    }
                                }
                            }

                            virtualMidi = dynamic_cast<te::VirtualMidiInputDevice * >(&instance->getInputDevice());
                        }
                    }

```

It’s easy to reproduce by running my modified MidiRecording example from above.  
Anything else I can check or try?

---

<div class="post-metadata">

**Author:** ![dikadk13](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dikadk13/32/17750_2.png) [@dikadk13](https://forum.juce.com/u/dikadk13)\
**Post date:** [October 9, 2020, 8:41pm UTC](https://forum.juce.com/t/configure-track-a-as-miditrack-input-for-track-b/42106/6 "2020-10-09T20:41:13Z")

</div>

Woohoo! Looks like code above gets me to result I want. I actually had to add Arpeggiator plugin to inputTrack, once it was added it generates and sends Midi to destTrack.  
For scenarios where I don’t have Midi Plugin (arpeggiator plugin in my case) on inputTrack, but still want to route Midi to destTrack, I used function below which routed output to destTrack.

> inputTrack-\>getOutput().setOutputToTrack(destTrack);

Thank’s @dave96 for help!
