# Cannot open multiple MidiOutputs - Is this a bug?

**URL:** <https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595>\
**Category:** Development\
**Created:** [May 25, 2022, 7:47am UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595 "2022-05-25T07:47:41Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![SimonORorke](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/simonororke/32/13196_2.png) [@SimonORorke](https://forum.juce.com/u/SimonORorke)\
**Post date:** [May 25, 2022, 7:47am UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/1 "2022-05-25T07:47:42Z")

</div>

I hope this is OK, but this is a new thread on a subject covered in a thread I created two weeks ago: [https://forum.juce.com/t/cannot-open-multiple-midiouts](https://forum.juce.com/t/cannot-open-multiple-midiouts). Not only did I make a typo I cannot correct in the old thread title, I drew conclusions in that thread that have been proven by my subsequent investigations to have been incorrect.

But the problem remains the same. I cannot find a way to open multiple `MidiOutput`s, or at least not in a way that I can do any processing with them. I’ve developed this test project, which shows several attempts to solve the problem and documents how they fail:  
[MidiOutputTest.zip](https://forum.juce.com/uploads/short-url/mBNgdrJmwitgN18xKq2s1Qnxz8a.zip) (61.7 KB)

 ![MidiOutputTest](https://us1.discourse-cdn.com/flex026/uploads/juce/original/2X/d/d6607f5a4db4e9fb16e7a81c4da438fd14722f72.png)

I would appreciate it if anyone would run the project and see if the problem is replicated. I’m developing on Windows, so perhaps my code will behave differently on other operating systems or perhaps even on a different computer.

I hope this does not demonstrate a JUCE bug. Either way I hope someone can show me a way to make this work.

**How to use the test project**

You will need at least two MIDI output devices to connect to. If you are on Windows and happen to have the internal MIDI ports provided by LoopBe30, you can use the ones that are currently hard-coded. _(I hit the same problem with the virtual ports that are available with Bome’s MIDI Translator Pro. So the problem is not specific to the ports. And I need to be able to use virtual/internal MIDI ports.)_ To change the MIDI output device names, go to the top of `MainComponent`'s constructor.

The names of the test classes containing the code to open the devices are shown in the application’s Select a Test combo box. When you select a test, some details of the specific test are shown below the combo box.

Click Start to run a test and Stop before running another test or closing the application, though as explained in the test-specific notes, the Stop button only does any real work in the last test. When a test is run, diagnostics are shown below the buttons and, in most tests, one or more error message boxes are shown.

---

<div class="post-metadata">

**Author:** ![cpr2323](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/cpr2323/32/18682_2.png) [@cpr2323](https://forum.juce.com/u/cpr2323)\
**Post date:** [May 25, 2022, 1:23pm UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/2 "2022-05-25T13:23:32Z")

</div>

I have written many apps that open multiple midi ports, so it does work. Modulo any breaking change in JUCE since I built any of those apps.

I was going to look at your code, but I see there is a fair amount in there. Is it possible you could whittle the problem down to the minimal lines of code required to reproduce the problem? Maybe even something with a GUI?

---

<div class="post-metadata">

**Author:** ![SimonORorke](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/simonororke/32/13196_2.png) [@SimonORorke](https://forum.juce.com/u/SimonORorke)\
**Post date:** [May 25, 2022, 7:44pm UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/3 "2022-05-25T19:44:42Z")

</div>

@cpr2323, its a good point that there’s a lot in the my test program. I think if I provide some orientation, you will find that there’s very little you need to look at.

**The Main Example**

Though there are six examples, you could just look at the code for the last one, the `MidiOutputBusOnePerThread` class. It’s the only example that accesses each `MidiOutput` in its own thread, something I would prefer to do in the real application I’m working on. `MidiOutputBusOnePerThread::run` starts the multiple individual device threads, which are implemented in the `MidiOutputDevice` class.

**The Base Class**

As I wanted to show multiple examples, `MidiOutputBusOnePerThread` and all the other test classes derive from an abstract class, `MidiOutputBusBase`. This base class contains nothing of substance for accessing the `MidiOutput`s.

`MidiOutputBusBase::startMidiOutputDevices` is called when the Start button is clicked, in `MainComponent::startButtonClicked`. It stores the device names for later access via `getDeviceNameCount`, `getDeviceName` and `getDeviceNames`. Then it starts the thread. It is not virtual, as it does not need to be overridden in any of the derived classes.

`MidiOutputBusBase::stopMidiOutputDevices` is called when the Stop button is clicked, in `MainComponent::stoptButtonClicked`. In the base class, this method does nothing. But it is overridden in `MidiOutputBusOnePerThread`.

**The GUI**

There are many GUI classes, copied from my real application to provide style. But the only code that is relevant to processing `MidiOutput`s is in `MainComponent`. As mentioned in my first post, the device names are specified at the top of its constructor. And I described `MainComponent::startButtonClicked` and `MainComponent::stoptButtonClicked` above. I should just add that `MainComponent::startButtonClicked` also initiates the `Timer` usage, which is specific to `MidiOutputBusOnePerThread`.

**Going Forward**

Hopefully you will now have enough information to check my code with ease. However, if you find that a cut-down demo application would still be valuable, please let me know and I’ll make one. Or let me know if you have any questions. I really appreciate your help.

---

<div class="post-metadata">

**Author:** ![cpr2323](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/cpr2323/32/18682_2.png) [@cpr2323](https://forum.juce.com/u/cpr2323)\
**Post date:** [May 25, 2022, 9:07pm UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/4 "2022-05-25T21:07:23Z")

</div>

Sorry brother, doing full-time software development along with my own projects only leaves so much space in my head for new things. I want to be able to reason about your code, so I need as little as possible. Hopefully someone else can take a look using your notes. 🙂

---

<div class="post-metadata">

**Author:** ![SimonORorke](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/simonororke/32/13196_2.png) [@SimonORorke](https://forum.juce.com/u/SimonORorke)\
**Post date:** [May 25, 2022, 9:52pm UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/5 "2022-05-25T21:52:40Z")

</div>

No worries. I’ll make a single file demo application. You are welcome to look at that if it works out for you. I’m onto it.

---

<div class="post-metadata">

**Author:** ![SimonORorke](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/simonororke/32/13196_2.png) [@SimonORorke](https://forum.juce.com/u/SimonORorke)\
**Post date:** [May 25, 2022, 11:29pm UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/6 "2022-05-25T23:29:05Z")

</div>

@cpr2323, here’s the single file demo application:  
[MidiOutputSimple.zip](https://forum.juce.com/uploads/short-url/a3FjecUp3A2tC0CmEc110qpvUyj.zip) (44.3 KB)

 ![MidiOutputSimple](https://us1.discourse-cdn.com/flex026/uploads/juce/original/2X/6/686494bb88a19db91453b2966dbdcb39c0fc991b.png)

It only contains only one usage example, based on the `MidiOutputBusField` example of the more fulsome demo application. I chose that example because it is less complex than `MidiOutputBusOnePerThread`. The problem to be solved is essentially the same in both. All the code is in MainComponent.h.

---

<div class="post-metadata">

**Author:** ![cpr2323](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/cpr2323/32/18682_2.png) [@cpr2323](https://forum.juce.com/u/cpr2323)\
**Post date:** [May 26, 2022, 1:42am UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/7 "2022-05-26T01:42:34Z")

</div>

Perfect size! Looking over the code I don’t see anything obvious. Which leads me to suggest jumping into the debugger and stepping into the second call to `MidiOutput::openDevice` (ie. the first failure). I quickly looked at the Windows version of that juce code, and most of the failures relate to OS calls. I think understanding where that failure is would be the next step in diagnosing this. Does the failure occur if you don’t start/stop the background thread? If that isn’t required for the failure you should remove it from this test code.

---

<div class="post-metadata">

**Author:** ![SimonORorke](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/simonororke/32/13196_2.png) [@SimonORorke](https://forum.juce.com/u/SimonORorke)\
**Post date:** [May 26, 2022, 4:40am UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/8 "2022-05-26T04:40:59Z")

</div>

The failure occurs irrespective of whether the background thread is started/stopped. In the fulsome edition of the demo application, I had a comment that said so. In my zeal to cut down the code size, I left the comment out! You are right, of course, the good thing to do would have been to remove the start/stop altogether. I’ve done that in this new version:  
[MidiOutputSimple.zip](https://forum.juce.com/uploads/short-url/glQZJngGb6pRM2ycPwJwUKb4ogz.zip) (44.6 KB)

Following your suggestion, I have stepped into the JUCE code with the debugger. In `MidiOutput::openDevice`, the problem occurs at this line:

```auto
wrapper.reset (MidiService::getService().createOutputWrapper (deviceIdentifier));

```

From there, I stepped into `Win32MidiService::createOutputWrapper` which contains just one line:

```auto
return new Win32OutputWrapper (*this, deviceIdentifier);

```

So I stepped into `Win32OutputWrapper`'s constructor. Within that, for both the first device and the second device (the one that always fails to open) the code gets to the following line:

```auto
for (int i = parent.activeOutputHandles.size(); --i >= 0;)

```

That is the line that does not behave as expected. `parent.activeOutputHandles` is an `Array` of `MidiOutHandle`s. Regardless of how many MIDI output devices my computer has, or which devices I want to open, or the order in which I specify the required devices, `parent.activeOutputHandles` only ever contains one `MidiOutHandle`. That `MidiOutHandle`'s device identifier is queried in the following line:

```auto
if (activeHandle->deviceInfo.identifier == deviceIdentifier)

```

The `MidiOutHandle`'s device identifier always turns out to be that of the first device I asked to open. In my hard-coded list, that’s ‘01. Internal MIDI’, even when the device being looked for (as specified by the `deviceIdentifier` parameter of `Win32OutputWrapper`'s constructor) is ‘02. Internal MIDI’. I cannot usefully step further into either of the last quoted two lines, as they only access data items.

After failing to find a match for the device identifier, the traversal through the `Win32OutputWrapper` constructor code ends up here:

```auto
throw std::runtime_error ("Failed to create Windows output device wrapper");

```

But the exception is caught. So, rather than crash the program, `MidiOutput::openDevice` returns `nullptr`.

I wondered if the problem had to do with the fact that I’m trying to open internal/virtual MIDI devices. So I substituted a list of three MIDI devices that are actually physical ports on USB hardware controllers. The failure was exactly the same with the physical devices.

All I can usefully conclude is that

- The failure occurs in Windows-specific JUCE code, so this may not be a problem in macOS etc.
- And it does not matter what kind of devices I try to open or in what order: only the first device will open.

Can you run my code in Windows please Chris? It would be good to confirm whether you can replicate the problem. I’m running Windows 10, in case the Windows version turns out to be relevant. If you happen to have another operating system you can run this on, that would be great too. I’ve only got Windows.

---

<div class="post-metadata">

**Author:** ![oli1](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/oli1/32/15664_2.png) [@oli1](https://forum.juce.com/u/oli1)\
**Post date:** [May 26, 2022, 9:52am UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/9 "2022-05-26T09:52:28Z")

</div>

I will check it out later today. I suspect this is a potential MIDI driver issue though.

Are you using a virtual MIDI driver and if so, which one?

---

<div class="post-metadata">

**Author:** ![SimonORorke](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/simonororke/32/13196_2.png) [@SimonORorke](https://forum.juce.com/u/SimonORorke)\
**Post date:** [May 26, 2022, 10:46am UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/10 "2022-05-26T10:46:07Z")

</div>

Hello @oli1. I’ve got two virtual MIDI drivers, LoopBe v1.6 and Bome’s MIDI Translator Pro v1.9.0. In addition, I have two other MIDI Drivers, Korg USB MIDI Driver v1.15 and Novation USB MIDI Driver 2.24.1.75.

For good measure, I’ve just uninstalled all four and, after rebooting my PC, repeated the test. Unfortunately, the error was the same.

I should perhaps also mention that I’ve also coded multiple MIDI outputs using NAudio, an audio library for .Net that works only with Windows. If there’s something specific to my MIDI software environment that JUCE cannot cope with, NAudio works fine with it. I’m attempting to replace the NAudio MIDI with JUCE, so that I can make my application cross-platform.

---

<div class="post-metadata">

**Author:** ![SimonORorke](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/simonororke/32/13196_2.png) [@SimonORorke](https://forum.juce.com/u/SimonORorke)\
**Post date:** [May 26, 2022, 11:12am UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/11 "2022-05-26T11:12:14Z")

</div>

Hello again @oli1. I realised I also had the MIDI drivers than come with Native Instruments Komplete Kontrol 2.6.7.1. So I got rid of that too. It has made no difference to the test results. I know you only mentioned virtual MIDI drivers. I’m just removing these others just in case. My audio interface driver, MOTU Pro Audio 2.90067 is the only other driver I can think of that provides MIDI capability. As you can imagine, I’m reluctant to uninstall it, but I will if you want me to.

---

<div class="post-metadata">

**Author:** ![cpr2323](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/cpr2323/32/18682_2.png) [@cpr2323](https://forum.juce.com/u/cpr2323)\
**Post date:** [May 26, 2022, 1:15pm UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/12 "2022-05-26T13:15:20Z")

</div>

Great work! Being able to get under the hood is another reason I love JUCE. It is an interesting failure case, and you are right on track with wanting to verify the problem on another system. I can run the code, but it may not be for a day or two. Hopefully @oli1 can get you going more quickly! 🙂

---

<div class="post-metadata">

**Author:** ![oli1](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/oli1/32/15664_2.png) [@oli1](https://forum.juce.com/u/oli1)\
**Post date:** [May 26, 2022, 1:24pm UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/13 "2022-05-26T13:24:32Z")

</div>

Just had a quick look at your code. `MidiOutputWrapper` constructor parameter semantics is invoking the MidiOutput destructor because of incorrect copy/move semantics being used.

This might work if you used an `rvalue reference (&&)` and `std::move`, but really you should be using pointers.

If a JUCE method returns a pointer (raw or smart) you should assume that it shouldn’t be dereferenced unless you have a good reason to.

```auto
MidiOutputWrapper::MidiOutputWrapper(MidiOutput& midiOutput) {
  this->midiOutput.reset(&midiOutput); 
}

```

Should be:

```auto
MidiOutputWrapper::MidiOutputWrapper(std::unique_ptr<MidiOutput>&& outputPort) {
  this->midiOutput = std::move(outputPort);
}

```

---

<div class="post-metadata">

**Author:** ![SimonORorke](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/simonororke/32/13196_2.png) [@SimonORorke](https://forum.juce.com/u/SimonORorke)\
**Post date:** [May 26, 2022, 9:11pm UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/14 "2022-05-26T21:11:43Z")

</div>

@oli1, thanks for the tip about the `MidiOutputWrapper` constructor. Yes, that looks much better! However, as you say,

> [@oli1](#):
>
> This might work if you used an `rvalue reference (&&)` and `std::move` , but really you should be using pointers.
> 
> If a JUCE method returns a pointer (raw or smart) you should assume that it shouldn’t be dereferenced unless you have a good reason to.

Understood, and, as you will have seen, I avoided dereferencing the smart pointer in the other examples. So, unsurprisingly, the change to the `MidiOutputWrapper` constructor did not fix the problem.

Did you test my code and not reproduce the problem? That could be one of the reasons for your question about virtual MIDI drivers.

We are likely to sometimes have time lags in communication, as I am in New Zealand and you are probably in the UK. In that case, I’ll be writing this well after your working day has finished, whereas I am going to have breakfast when I’ve written this! However, I shall still be available to correspond this evening my time, which will be be your morning.

---

<div class="post-metadata">

**Author:** ![oli1](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/oli1/32/15664_2.png) [@oli1](https://forum.juce.com/u/oli1)\
**Post date:** [May 27, 2022, 10:03am UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/15 "2022-05-27T10:03:17Z")

</div>

Morning Simon,

I did run your project, and it failed to open the ports, So I put together a minimal example that successfully opened all ports on my machine.

```auto
std::vector<std::unique_ptr<MidiOutput>> ports;
        
for (const auto& port : MidiOutput::getAvailableDevices())
{
    if (auto p = MidiOutput::openDevice (port.identifier))
    {
        p->startBackgroundThread();
                
        Thread::sleep (1000);
                
        if (p->isBackgroundThreadRunning())
            ports.push_back (std::move (p));
    }
}

jassert (ports.size() == MidiOutput::getAvailableDevices().size());

```

---

<div class="post-metadata">

**Author:** ![SimonORorke](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/simonororke/32/13196_2.png) [@SimonORorke](https://forum.juce.com/u/SimonORorke)\
**Post date:** [May 27, 2022, 11:43am UTC](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug/51595/16 "2022-05-27T11:43:25Z")

</div>

Thanks, @oli1! I’ve figured out my big mistake. I was passing the device’s _name_ as a parameter to `MidiOutput::openDevice` when I should have been passing the device’s _identifier_. The manual does clearly state that the identifier is what is needed.

What confused me was the strange behaviour whereby `MidiOutput::openDevice` would always open the first device whose name I mistakenly gave it, no matter which particular device it was. What’s that all about, I wonder? If it had failed to open any devices or opened only those few devices that, I notice, have the same name as identifier, I would probably have been forced to work out my mistake. RTFM.

Problem solved!
