Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: DeviceManager doesn't work on Linux #246

Open
1 task done
wang-edward opened this issue Jan 28, 2025 · 6 comments
Open
1 task done

[Bug]: DeviceManager doesn't work on Linux #246

wang-edward opened this issue Jan 28, 2025 · 6 comments

Comments

@wang-edward
Copy link

Detailed steps on how to reproduce the bug

Summary

I'm unable to set the Midi In Device with dm.setDefaultMidiInDevice() on linux devices.

  • The same code runs correctly on MacOS.

Context

My use case is playing virtual midi messages with:

int note = 60; // C3
te::MidiInputDevice *dev = engine_.getDeviceManager().getDefaultMidiInDevice();
dev->keyboardState.noteOn(1, note, 1.0);

Reproducing

I created a program fake_main.cc (below) in order to reproduce this behaviour.
Even though I'm setting the default midi in device, dm.getDefaultMidiInDevice() keeps returning nullptr

Here's my log from the github runner CI:

  • I truncated the raylib init messages for clarity
JUCE v8.0.3
ALSA lib seq_hw.c:466:(snd_seq_hw_open) open /dev/snd/seq failed: No such file or directory
ALSA lib seq_hw.c:466:(snd_seq_hw_open) open /dev/snd/seq failed: No such file or directory
ALSA lib seq_hw.c:466:(snd_seq_hw_open) open /dev/snd/seq failed: No such file or directory
Audio block size: 256  Rate: 44100
Creating Default Controllers...
Edit loaded in: 2 ms
-----------
begin tests
ALSA::VirtualMidi begin
FakeMain: /home/runner/work/box/box/test/fake_main.cc:30: int main(): Assertion `ptr != nullptr' failed.
Aborted (core dumped)
Error: Process completed with exit code 134.

Solution?

I think this has to do with the line, since ALSA handles midi messages:

ALSA lib seq_hw.c:466:(snd_seq_hw_open) open /dev/snd/seq failed: No such file or directory

I saw the same error message on tracktion_engine:master.

Am I doing something wrong? Like not setting up the audio server correctly?

Note:

  • I'm using int main() instead of the Juce application harness
  • I would prefer to proceed this way because it's simpler. Especially since it works fine on macOS.

What is the expected behaviour?

The test should pass.

  • On my Macbook (Air M1), the FakeMain program runs without failing the assert.
    • It correctly prints out how many Midi Devices there are.
  • I tested different linux platforms:
    • my PC (x86 ubuntu 22.04)
    • the github runner CI environment (x86 ubuntu 22.04)
    • Raspberry Pi CM4 (ARM Raspberry Pi OS)

Unit test to reproduce the error?

// fake_main.cc

#include <filesystem>
#include <iostream>
#include <raylib.h>

#include <tracktion_engine/tracktion_engine.h>
namespace te = tracktion;

int main()
{
    const juce::ScopedJuceInitialiser_GUI initialiser; // need this

    te::Engine engine{"Tracktion Hello World"};
    std::filesystem::path curr_path = std::filesystem::current_path();
    juce::File my_file{juce::String{curr_path.string() + "/tmp.box"}};

    std::unique_ptr<te::Edit> my_edit = createEmptyEdit(engine, my_file);
    te::Edit &edit = *my_edit;
    edit.ensureNumberOfAudioTracks(8);
    edit.getTransport().ensureContextAllocated();
    engine.getDeviceManager().rescanMidiDeviceList();

    // need this line for the test to pass on macOS for some reason
    InitWindow(512, 512, "fake main test");

    std::cout << "-----------" << std::endl;
    std::cout << "begin tests" << std::endl;

    // test ALSA::VirtualMidi
    {
        std::cout << "ALSA::VirtualMidi begin" << std::endl;
        engine.getDeviceManager().createVirtualMidiDevice("box_midi");
        engine.getDeviceManager().setDefaultMidiInDevice("box_midi");
        auto ptr = engine.getDeviceManager().getDefaultMidiInDevice();
        assert(ptr != nullptr);
        std::cout << "ALSA::VirtualMidi end" << std::endl;
    }

    std::cout << std::endl;

    // test ALSA::PrintMidiIn
    {
        std::cout << "ALSA::PrintMidiIn begin:" << std::endl;
        auto vec = engine.getDeviceManager().getMidiInDevices();
        std::cout << "midiInputs.size(): " << vec.size() << std::endl;
        for (auto &x : vec)
        {
            std::cout << "\t" << x->getName() << std::endl;
        }
        std::cout << "ALSA::PrintMidiIn end" << std::endl;
    }


    std::cout << "end tests" << std::endl;
    std::cout << "-----------" << std::endl;

    return 0;
}

Operating systems

Linux

What versions of the operating systems?

Ubuntu 22.04

Architectures

x86_64, ARM

Stacktrace

Plug-in formats (if applicable)

No response

Plug-in host applications (DAWs) (if applicable)

No response

Testing on the develop branch

The bug is present on the develop branch

Code of Conduct

  • I agree to follow the Code of Conduct
@drowaudio
Copy link
Contributor

Some the the functions you're calling there are asyncronous. You can't really run them in a straight procedural app like that.

Also, your ALSA::VirtualMidi I don't think is doing what you expect. In Tracktion Engine, a "VirtualMidiDevice" is local to the app, it's not a system device. More like an internal aggregate MIDI device that you can assign multiple MIDI devices to.

I would run the juce demo app first to see if that picks up your OS MIDI devices. If that does, TE should be able to find them.

@wang-edward
Copy link
Author

Thank you. I will try that.

@wang-edward
Copy link
Author

Just to clarify. By "juce demo app", do you mean this?

https://github.com/juce-framework/JUCE/blob/master/examples/CMake/GuiApp/Main.cpp

@drowaudio
Copy link
Contributor

No, I think that's a template. It's this one: https://github.com/juce-framework/JUCE/blob/master/examples/DemoRunner/CMakeLists.txt

@wang-edward
Copy link
Author

OK. I tried the tracktion_engine::DemoRunner on my ubuntu PC and it seemed to be working:

...
Default Wave Out: channel 1 + 2
Default MIDI Out: 
Default Wave In: channel 1
Default MIDI In: 
MIDI Input devices scanned in: 1 ms
Updating MIDI I/O devices
Found MIDI in: midiin_170f06 ("Midi Through Port-0") (enabled)
Found MIDI in: all_midi_in ("All MIDI Ins") (enabled)
Found MIDI out: out_c31d4a06 ("Midi Through Port-0") (enabled)
opening MIDI out device: out_c31d4a06 (Midi Through Port-0)
opening MIDI in device: midiin_170f06 (Midi Through Port-0)
closing MIDI output: Midi Through Port-0
Closing MIDI in device: Midi Through Port-0
...

How is this code compiled? I can't find an int main() or a START_JUCE_APPLICATION().

@drowaudio
Copy link
Contributor

It's a PIP so I think the juce_add_pip function in cmake generates a cpp file which has that in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants