# Cannot open multiple MidiOuts

**URL:** <https://forum.juce.com/t/cannot-open-multiple-midiouts/51395>\
**Category:** Development\
**Created:** [May 11, 2022, 4:29am UTC](https://forum.juce.com/t/cannot-open-multiple-midiouts/51395 "2022-05-11T04:29:29Z")\
**Posts on this page:** 12\
**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 11, 2022, 4:29am UTC](https://forum.juce.com/t/cannot-open-multiple-midiouts/51395/1 "2022-05-11T04:29:29Z")

</div>

When I attempt to open multiple MidiOuts, only the first **MidiOutput::openDevice()** works. The subsequent ones return **nullptr**. I think at one stage this was happening intermittently. So it is possible you may not be able to reproduce the problem. But now it happens every time for me. In the following code, it makes no difference if I change the order in which the three named MIDI devices are opened. Every time, it is only the first one opened that works.

```auto
    const auto midiOutput1 = MidiOutput::openDevice("01. Internal MIDI");
    if (midiOutput1 == nullptr) {
      // Never happens with the first MidiOut opened.
      DBG("Failed to open midiOutput1");
    }
    const auto midiOutput2 = MidiOutput::openDevice("02. Internal MIDI"); 
    if (midiOutput2 == nullptr) {
      // Always happens with the second MidiOut opened.
      DBG("Failed to open midiOutput2");
    }
    const auto midiOutput3 = MidiOutput::openDevice("03. Internal MIDI"); 
    if (midiOutput3 == nullptr) {
      // Always happens with the third MidiOut opened.
      DBG("Failed to open midiOutput3");
    }

```

---

<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 11, 2022, 9:40am UTC](https://forum.juce.com/t/cannot-open-multiple-midiouts/51395/2 "2022-05-11T09:40:32Z")

</div>

In my previous post, when I mentioned that at one stage the problem may have been happening intermittently, that was when I had tried opening each MidiOutput in a separate thread. I have recreated that in the following code:

```auto
#pragma once
#include <JuceHeader.h>
using namespace juce;

class MidiOutputOpener : public Thread {
public:
  explicit MidiOutputOpener(const String& deviceName)
    : Thread(deviceName) {
  }

  String getDeviceName() const {
    return getThreadName();
  }

  void run() override {
    const auto deviceName = getDeviceName();
    if (const auto midiOutput = MidiOutput::openDevice(deviceName);
      midiOutput != nullptr) {
      DBG("Opened " + deviceName);
    } else {
      DBG("Failed to open " + deviceName);
    }
  }
};

class MidiOutTester {
public:
  OwnedArray<MidiOutputOpener> midiOutputOpeners;

  void startMidiOutTester() {
    midiOutputOpeners.add(new MidiOutputOpener("01. Internal MIDI"));
    midiOutputOpeners.add(new MidiOutputOpener("02. Internal MIDI"));
    midiOutputOpeners.add(new MidiOutputOpener("03. Internal MIDI"));
    DBG("=====================================");
    for (const auto midiOutputOpener : midiOutputOpeners) {
      midiOutputOpener->startThread();
    }
  }

   void stopMidiOutTester() {
    for (const auto midiOutputOpener : midiOutputOpeners) {
      if (midiOutputOpener->isThreadRunning()) {
        midiOutputOpener->stopThread(10);
      }
    }
    midiOutputOpeners.clear();
   }
};

```

And here are the results of a few attempts to open three MidiOuts in separate threads with the above code. The behaviour has indeed been variable. Sometimes two out of three succeed in opening, sometimes only one:

```auto
=====================================
Opened 03. Internal MIDI
Failed to open 01. Internal MIDI
Failed to open 02. Internal MIDI
=====================================
Opened 02. Internal MIDI
Failed to open 03. Internal MIDI
Failed to open 01. Internal MIDI
=====================================
Opened 01. Internal MIDI
Failed to open 03. Internal MIDI
Opened 02. Internal MIDI
=====================================
Opened 02. Internal MIDI
Failed to open 01. Internal MIDI
Opened 03. Internal MIDI

```

---

<div class="post-metadata">

**Author:** ![Rincewind](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/rincewind/32/10645_2.png) [@Rincewind](https://forum.juce.com/u/Rincewind)\
**Post date:** [May 11, 2022, 9:51am UTC](https://forum.juce.com/t/cannot-open-multiple-midiouts/51395/3 "2022-05-11T09:51:17Z")

</div>

Have you tried to add small sleep in between the opening tries? I‘d start with five seconds to be sure and then narrow it down if it is indeed working this way.

---

<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 11, 2022, 10:59am UTC](https://forum.juce.com/t/cannot-open-multiple-midiouts/51395/4 "2022-05-11T10:59:32Z")

</div>

Thanks @Rincewind! That worked. I got the **sleep** down to 0. **sleep(0)** is equivalent to **yield()**, which is defined as

> Yields the current thread’s CPU time-slot and allows a new thread to run. If there are no other threads of equal or higher priority currently running then this will return immediately and the current thread will continue to run.

So I replaced **sleep(0)** with **yield()**. That works too. Here’s a working version of the code:

```auto
class MidiOutputOpener : public Thread {
public:
  explicit MidiOutputOpener()
    : Thread("MidiOutputOpener") {
  }

  void run() override {
    DBG("=====================================");
    openMidiOutput("01. Internal MIDI");
    yield();
    openMidiOutput("02. Internal MIDI");
    yield();
    openMidiOutput("03. Internal MIDI");
  }

  void openMidiOutput(const String& deviceName) const {
    if (const auto midiOutput = MidiOutput::openDevice(deviceName);
      midiOutput != nullptr) {
      DBG("Opened " + deviceName);
    } else {
      DBG("Failed to open " + deviceName);
    }
  }
};

class MidiOutTester {
public:
  MidiOutputOpener midiOutputOpener;
  
  void startMidiOutTester() {
    midiOutputOpener.startThread();
  }

   void stopMidiOutTester() {
    if (midiOutputOpener.isThreadRunning()) {
      midiOutputOpener.stopThread(10);
    }
   }
};

```

And here is the consistent result:

```auto
=====================================
Opened 01. Internal MIDI
Opened 02. Internal MIDI
Opened 03. Internal MIDI

```

It would be interesting, though not essential, to know more about why the **yield()** is necessary. For a start, it shows that **MidiOutput::openDevice** must be running one or more new threads behind the scenes.

---

<div class="post-metadata">

**Author:** ![Rincewind](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/rincewind/32/10645_2.png) [@Rincewind](https://forum.juce.com/u/Rincewind)\
**Post date:** [May 11, 2022, 11:05am UTC](https://forum.juce.com/t/cannot-open-multiple-midiouts/51395/5 "2022-05-11T11:05:42Z")

</div>

It is very much possible, that every OS deals with that differently.

> [@SimonORorke](#):
>
> For a start, it shows that **MidiOutput::openDevice** must be running one or more new threads behind the scenes.

I wouldn’t necessarily draw this conclusion. If that is the fact and without the yield you run into a try lock from the OS, you would be better of by sleeping actually a second since this kind of behaviour is not deterministic and just because it worked the first five tries, doesn’t mean it always works.

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [May 11, 2022, 11:12am UTC](https://forum.juce.com/t/cannot-open-multiple-midiouts/51395/6 "2022-05-11T11:12:34Z")

</div>

The easiest and most robust solution would be to open sequentially from the message thread, if that is not stopping for too long.

---

<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 11, 2022, 11:42am UTC](https://forum.juce.com/t/cannot-open-multiple-midiouts/51395/7 "2022-05-11T11:42:57Z")

</div>

@Rincewind and @daniel, those are both most informative comments, thanks. It’s a good point that I’ve not proven that my fix will work always and everywhere. And I did not know that doing this in the GUI thread would be more robust. Those yields should not tie up the GUI thread too long. So I shall do that.

---

<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 11, 2022, 11:55am UTC](https://forum.juce.com/t/cannot-open-multiple-midiouts/51395/8 "2022-05-11T11:55:00Z")

</div>

And if yields on the message thread proven not to be robust enough, I can go with longer sleeps on another thread. There are multiple good options.

---

<div class="post-metadata">

**Author:** ![Rincewind](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/rincewind/32/10645_2.png) [@Rincewind](https://forum.juce.com/u/Rincewind)\
**Post date:** [May 11, 2022, 1:34pm UTC](https://forum.juce.com/t/cannot-open-multiple-midiouts/51395/9 "2022-05-11T13:34:27Z")

</div>

I think you shouldn’t yield on the message thread, since there is always stuff to do. Just use a `juce::Timer` as I suggested to delay it 1ms in case you want to go down that route.

---

<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 11, 2022, 7:18pm UTC](https://forum.juce.com/t/cannot-open-multiple-midiouts/51395/10 "2022-05-11T19:18:15Z")

</div>

Ah yes, that sounds optimal. Thanks @Rincewind.

---

<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 19, 2022, 1:41am UTC](https://forum.juce.com/t/cannot-open-multiple-midiouts/51395/11 "2022-05-19T01:41:15Z")

</div>

For efficiency, I would like each `MidiOutput` to have its own thread from which to send MIDI messages. But I have only been able to access a `MidiOutput`'s member functions on the thread on which the `MidiOutput` was instantiated/opened. So I need either

- a way to access the member functions from a different thread from where the `MidiOutput` was opened
- or a way to open each `MidiOutput` on its own thread.

The latter approach is shown in the following code. Unfortunately it only succeeds in opening one `MidiOutput`, regardless of how many are requested. First, here’s the `MidiOutBus` class, which attempts to open a `MidiOutput` on a thread. After that, I’ll put the code that attempts to use `MidiOutBus` to open multiple `MidiOutput`s.

```auto
#pragma once
#include <JuceHeader.h>
using namespace juce;

class MidiOutBus : Thread {
public:
  MidiOutBus(
    const String& deviceName,
    const int deviceIndex) :
    Thread("MidiOutBus" + String(deviceIndex)) {
    mDeviceName = deviceName;
    mDeviceIndex = deviceIndex;
  }

  void startMidiOutBus() {
    startThread();
  }

  void stopMidiOutBus() const {
    if (isThreadRunning()) {
      notify();
    }
  }

private:
  int mDeviceIndex;
  String mDeviceName;
  std::unique_ptr<MidiOutput> mMidiOutput;
  
  void run() override {
    openMidiOutput();
    if (wait(-1)) {
      if (mMidiOutput != nullptr && mMidiOutput->isBackgroundThreadRunning()) {
        mMidiOutput->stopBackgroundThread();
        DBG("Stopped background thread for MIDI output device '" +
          mDeviceName + "'.");
      }
    }
  }

  void openMidiOutput() {
    bool foundDevice = false;
    for (const auto& device : MidiOutput::getAvailableDevices()) {
      if (device.name == mDeviceName) {
        foundDevice = true;
        break;
      }
    }
    if (!foundDevice) {
      DBG("Cannot find MIDI output device '" + mDeviceName + "'.");
      return;
    }
    DBG("Found MIDI output device '" + mDeviceName + "'.");
    // Staggering the opening of the devices, but it does not help.
    sleep(100 * mDeviceIndex); 
    //yield(); // Before or after openDevice? Either way, it does not help.
    // sleep(1000); // Sleeping instead of yielding does not help.
    mMidiOutput = MidiOutput::openDevice(mDeviceName);
    //yield(); // Before or after openDevice? Either way, it does not help.
    // sleep(1000); // Sleeping instead of yielding does not help.
    if (mMidiOutput == nullptr) {
      // If this happens, the yield or sleep has not had the desired effect.
      DBG("MIDI output device '" + mDeviceName +
        "' has been found but could not be opened.");
      return;
    }
    DBG("Opened MIDI output device '" + mDeviceName + "'.");
    // It makes no difference to whether the next MidiOutput will open
    // whether the background thread is opened or not.
    mMidiOutput->startBackgroundThread();
    DBG("Started background thread for MIDI output device '" +
      mDeviceName + "'.");
  }
};

```

And here’s the `MidiOuManager` class, which runs instances of `MidiOutBus`.

```auto
#pragma once
#include <JuceHeader.h>
#include "MidiOutBus.h"
using namespace juce;

class MidiOutManager {
public:
  void startOpeningMidiOuts(
    const StringArray& deviceNames) {
    mMidiOutBuses.clear();
    for (int i = 0; i < deviceNames.size(); ++i) {
      mMidiOutBuses.add(
        new MidiOutBus(
          deviceNames[i],
          i));
      mMidiOutBuses[i]->startMidiOutBus();
    }
  }

  void stopMidiOuts() {
    for (const auto midiOutBus : mMidiOutBuses) {
      midiOutBus->stopMidiOutBus();
    }
  }

private:
  OwnedArray<MidiOutBus> mMidiOutBuses;
};

```

And here’s the result of a test run of `MidiOutManager.startOpeningMidiOuts`:

```auto
Found MIDI output device '02. Internal MIDI'.
Found MIDI output device '01. Internal MIDI'.
Found MIDI output device '03. Internal MIDI'.
Opened MIDI output device '01. Internal MIDI'.
Started background thread for MIDI output device '01. Internal MIDI'.
MIDI output device '02. Internal MIDI' has been found but could not be opened.
MIDI output device '03. Internal MIDI' has been found but could not be opened.

```

I would appreciate any suggestions. My fallback solution would be to open and access all the `MidiOutput`s on the same thread. I should be able to do that with what I’ve learned already. And it may well only slow the processing down to a negligible extent. But hopefully accessing each `MidiOutput` on a separate thread will turn out to be a soluble problem.

---

<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:36pm UTC](https://forum.juce.com/t/cannot-open-multiple-midiouts/51395/12 "2022-05-25T23:36:58Z")

</div>

I’ve started a new thread on the same subject: [https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug](https://forum.juce.com/t/cannot-open-multiple-midioutputs-is-this-a-bug). Please make any further contributions in the new thread.
