Browse Source

Add appendAudioMenu() and appendMidiMenu().

tags/v2.0.0
Andrew Belt 5 years ago
parent
commit
55852118f7
4 changed files with 260 additions and 117 deletions
  1. +7
    -0
      include/app/AudioWidget.hpp
  2. +7
    -0
      include/app/MidiWidget.hpp
  3. +145
    -73
      src/app/AudioWidget.cpp
  4. +101
    -44
      src/app/MidiWidget.cpp

+ 7
- 0
include/app/AudioWidget.hpp View File

@@ -1,6 +1,7 @@
#pragma once
#include <app/common.hpp>
#include <app/LedDisplay.hpp>
#include <ui/Menu.hpp>
#include <audio.hpp>


@@ -20,5 +21,11 @@ struct AudioWidget : LedDisplay {
};


/** Appends menu items to the given menu with driver, device, etc.
Useful alternative to putting an AudioWidget on your module's panel.
*/
void appendAudioMenu(ui::Menu* menu, audio::Port* port);


} // namespace app
} // namespace rack

+ 7
- 0
include/app/MidiWidget.hpp View File

@@ -1,6 +1,7 @@
#pragma once
#include <app/common.hpp>
#include <app/LedDisplay.hpp>
#include <ui/Menu.hpp>
#include <midi.hpp>


@@ -18,5 +19,11 @@ struct MidiWidget : LedDisplay {
};


/** Appends menu items to the given menu with driver, device, etc.
Useful alternative to putting a MidiWidget on your module's panel.
*/
void appendMidiMenu(ui::Menu* menu, midi::Port* port);


} // namespace app
} // namespace rack

+ 145
- 73
src/app/AudioWidget.cpp View File

@@ -6,7 +6,7 @@ namespace rack {
namespace app {


struct AudioDriverItem : ui::MenuItem {
struct AudioDriverValueItem : ui::MenuItem {
audio::Port* port;
int driverId;
void onAction(const event::Action& e) override {
@@ -14,22 +14,26 @@ struct AudioDriverItem : ui::MenuItem {
}
};

static void appendAudioDriverMenu(ui::Menu* menu, audio::Port* port) {
if (!port)
return;

for (int driverId : audio::getDriverIds()) {
AudioDriverValueItem* item = new AudioDriverValueItem;
item->port = port;
item->driverId = driverId;
item->text = audio::getDriver(driverId)->getName();
item->rightText = CHECKMARK(item->driverId == port->getDriverId());
menu->addChild(item);
}
}

struct AudioDriverChoice : LedDisplayChoice {
audio::Port* port;
void onAction(const event::Action& e) override {
if (!port)
return;

ui::Menu* menu = createMenu();
menu->addChild(createMenuLabel("Audio driver"));
for (int driverId : audio::getDriverIds()) {
AudioDriverItem* item = new AudioDriverItem;
item->port = port;
item->driverId = driverId;
item->text = audio::getDriver(driverId)->getName();
item->rightText = CHECKMARK(item->driverId == port->getDriverId());
menu->addChild(item);
}
appendAudioDriverMenu(menu, port);
}
void step() override {
text = "";
@@ -47,8 +51,17 @@ struct AudioDriverChoice : LedDisplayChoice {
}
};

struct AudioDriverItem : ui::MenuItem {
audio::Port* port;
ui::Menu* createChildMenu() override {
ui::Menu* menu = new ui::Menu;
appendAudioDriverMenu(menu, port);
return menu;
}
};


struct AudioDeviceItem : ui::MenuItem {
struct AudioDeviceValueItem : ui::MenuItem {
audio::Port* port;
int deviceId;
int offset;
@@ -58,39 +71,44 @@ struct AudioDeviceItem : ui::MenuItem {
}
};

static void appendAudioDeviceMenu(ui::Menu* menu, audio::Port* port) {
if (!port || !port->driver)
return;

{
AudioDeviceValueItem* item = new AudioDeviceValueItem;
item->port = port;
item->deviceId = -1;
item->text = "(No device)";
item->rightText = CHECKMARK(port->getDeviceId() == -1);
menu->addChild(item);
}

for (int deviceId : port->driver->getDeviceIds()) {
int channels = std::max(port->driver->getDeviceNumInputs(deviceId), port->driver->getDeviceNumOutputs(deviceId));
// Prevents devices with a ridiculous number of channels from being displayed
const int maxTotalChannels = 128;
channels = std::min(maxTotalChannels, channels);

for (int offset = 0; offset < channels; offset += port->maxChannels) {
AudioDeviceValueItem* item = new AudioDeviceValueItem;
item->port = port;
item->deviceId = deviceId;
item->offset = offset;
item->text = port->driver->getDeviceDetail(deviceId, offset, port->maxChannels);
item->rightText = CHECKMARK(item->deviceId == port->getDeviceId() && item->offset == port->offset);
menu->addChild(item);
}
}
}

struct AudioDeviceChoice : LedDisplayChoice {
audio::Port* port;

void onAction(const event::Action& e) override {
if (!port || !port->driver)
return;

ui::Menu* menu = createMenu();
menu->addChild(createMenuLabel("Audio device"));
{
AudioDeviceItem* item = new AudioDeviceItem;
item->port = port;
item->deviceId = -1;
item->text = "(No device)";
item->rightText = CHECKMARK(port->getDeviceId() == -1);
menu->addChild(item);
}
for (int deviceId : port->driver->getDeviceIds()) {
int channels = std::max(port->driver->getDeviceNumInputs(deviceId), port->driver->getDeviceNumOutputs(deviceId));
// Prevents devices with a ridiculous number of channels from being displayed
const int maxTotalChannels = 128;
channels = std::min(maxTotalChannels, channels);

for (int offset = 0; offset < channels; offset += port->maxChannels) {
AudioDeviceItem* item = new AudioDeviceItem;
item->port = port;
item->deviceId = deviceId;
item->offset = offset;
item->text = port->driver->getDeviceDetail(deviceId, offset, port->maxChannels);
item->rightText = CHECKMARK(item->deviceId == port->getDeviceId() && item->offset == port->offset);
menu->addChild(item);
}
}
appendAudioDeviceMenu(menu, port);
}
void step() override {
text = "";
@@ -108,8 +126,17 @@ struct AudioDeviceChoice : LedDisplayChoice {
}
};

struct AudioDeviceItem : ui::MenuItem {
audio::Port* port;
ui::Menu* createChildMenu() override {
ui::Menu* menu = new ui::Menu;
appendAudioDeviceMenu(menu, port);
return menu;
}
};

struct AudioSampleRateItem : ui::MenuItem {

struct AudioSampleRateValueItem : ui::MenuItem {
audio::Port* port;
int sampleRate;
void onAction(const event::Action& e) override {
@@ -117,26 +144,30 @@ struct AudioSampleRateItem : ui::MenuItem {
}
};

static void appendAudioSampleRateMenu(ui::Menu* menu, audio::Port* port) {
if (!port)
return;

std::vector<int> sampleRates = port->getSampleRates();
if (sampleRates.empty()) {
menu->addChild(createMenuLabel("(Locked by device)"));
}
for (int sampleRate : sampleRates) {
AudioSampleRateValueItem* item = new AudioSampleRateValueItem;
item->port = port;
item->sampleRate = sampleRate;
item->text = string::f("%g kHz", sampleRate / 1000.0);
item->rightText = CHECKMARK(item->sampleRate == port->getSampleRate());
menu->addChild(item);
}
}

struct AudioSampleRateChoice : LedDisplayChoice {
audio::Port* port;
void onAction(const event::Action& e) override {
if (!port)
return;

ui::Menu* menu = createMenu();
menu->addChild(createMenuLabel("Sample rate"));
std::vector<int> sampleRates = port->getSampleRates();
if (sampleRates.empty()) {
menu->addChild(createMenuLabel("(Locked by device)"));
}
for (int sampleRate : sampleRates) {
AudioSampleRateItem* item = new AudioSampleRateItem;
item->port = port;
item->sampleRate = sampleRate;
item->text = string::f("%g kHz", sampleRate / 1000.0);
item->rightText = CHECKMARK(item->sampleRate == port->getSampleRate());
menu->addChild(item);
}
appendAudioSampleRateMenu(menu, port);
}
void step() override {
text = "";
@@ -155,8 +186,17 @@ struct AudioSampleRateChoice : LedDisplayChoice {
}
};

struct AudioSampleRateItem : ui::MenuItem {
audio::Port* port;
ui::Menu* createChildMenu() override {
ui::Menu* menu = new ui::Menu;
appendAudioSampleRateMenu(menu, port);
return menu;
}
};


struct AudioBlockSizeItem : ui::MenuItem {
struct AudioBlockSizeValueItem : ui::MenuItem {
audio::Port* port;
int blockSize;
void onAction(const event::Action& e) override {
@@ -164,27 +204,31 @@ struct AudioBlockSizeItem : ui::MenuItem {
}
};

static void appendAudioBlockSizeMenu(ui::Menu* menu, audio::Port* port) {
if (!port)
return;

std::vector<int> blockSizes = port->getBlockSizes();
if (blockSizes.empty()) {
menu->addChild(createMenuLabel("(Locked by device)"));
}
for (int blockSize : blockSizes) {
AudioBlockSizeValueItem* item = new AudioBlockSizeValueItem;
item->port = port;
item->blockSize = blockSize;
float latency = (float) blockSize / port->getSampleRate() * 1000.0;
item->text = string::f("%d (%.1f ms)", blockSize, latency);
item->rightText = CHECKMARK(item->blockSize == port->getBlockSize());
menu->addChild(item);
}
}

struct AudioBlockSizeChoice : LedDisplayChoice {
audio::Port* port;
void onAction(const event::Action& e) override {
if (!port)
return;

ui::Menu* menu = createMenu();
menu->addChild(createMenuLabel("Block size"));
std::vector<int> blockSizes = port->getBlockSizes();
if (blockSizes.empty()) {
menu->addChild(createMenuLabel("(Locked by device)"));
}
for (int blockSize : blockSizes) {
AudioBlockSizeItem* item = new AudioBlockSizeItem;
item->port = port;
item->blockSize = blockSize;
float latency = (float) blockSize / port->getSampleRate() * 1000.0;
item->text = string::f("%d (%.1f ms)", blockSize, latency);
item->rightText = CHECKMARK(item->blockSize == port->getBlockSize());
menu->addChild(item);
}
appendAudioBlockSizeMenu(menu, port);
}
void step() override {
text = "";
@@ -202,6 +246,15 @@ struct AudioBlockSizeChoice : LedDisplayChoice {
}
};

struct AudioBlockSizeItem : ui::MenuItem {
audio::Port* port;
ui::Menu* createChildMenu() override {
ui::Menu* menu = new ui::Menu;
appendAudioBlockSizeMenu(menu, port);
return menu;
}
};


void AudioWidget::setAudioPort(audio::Port* port) {
clearChildren();
@@ -250,5 +303,24 @@ void AudioWidget::setAudioPort(audio::Port* port) {
}


void appendAudioMenu(ui::Menu* menu, audio::Port* port) {
AudioDriverItem* driverItem = createMenuItem<AudioDriverItem>("Audio driver", RIGHT_ARROW);
driverItem->port = port;
menu->addChild(driverItem);

AudioDeviceItem* deviceItem = createMenuItem<AudioDeviceItem>("Audio device", RIGHT_ARROW);
deviceItem->port = port;
menu->addChild(deviceItem);

AudioSampleRateItem* sampleRateItem = createMenuItem<AudioSampleRateItem>("Sample rate", RIGHT_ARROW);
sampleRateItem->port = port;
menu->addChild(sampleRateItem);

AudioBlockSizeItem* blockSizeItem = createMenuItem<AudioBlockSizeItem>("Block size", RIGHT_ARROW);
blockSizeItem->port = port;
menu->addChild(blockSizeItem);
}


} // namespace app
} // namespace rack

+ 101
- 44
src/app/MidiWidget.cpp View File

@@ -6,7 +6,7 @@ namespace rack {
namespace app {


struct MidiDriverItem : ui::MenuItem {
struct MidiDriverValueItem : ui::MenuItem {
midi::Port* port;
int driverId;
void onAction(const event::Action& e) override {
@@ -14,22 +14,26 @@ struct MidiDriverItem : ui::MenuItem {
}
};

static void appendMidiDriverMenu(ui::Menu* menu, midi::Port* port) {
if (!port)
return;

for (int driverId : port->getDriverIds()) {
MidiDriverValueItem* item = new MidiDriverValueItem;
item->port = port;
item->driverId = driverId;
item->text = port->getDriverName(driverId);
item->rightText = CHECKMARK(item->driverId == port->driverId);
menu->addChild(item);
}
}

struct MidiDriverChoice : LedDisplayChoice {
midi::Port* port;
void onAction(const event::Action& e) override {
if (!port)
return;

ui::Menu* menu = createMenu();
menu->addChild(createMenuLabel("MIDI driver"));
for (int driverId : port->getDriverIds()) {
MidiDriverItem* item = new MidiDriverItem;
item->port = port;
item->driverId = driverId;
item->text = port->getDriverName(driverId);
item->rightText = CHECKMARK(item->driverId == port->driverId);
menu->addChild(item);
}
appendMidiDriverMenu(menu, port);
}
void step() override {
text = port ? port->getDriverName(port->driverId) : "";
@@ -43,7 +47,17 @@ struct MidiDriverChoice : LedDisplayChoice {
}
};

struct MidiDeviceItem : ui::MenuItem {
struct MidiDriverItem : ui::MenuItem {
midi::Port* port;
ui::Menu* createChildMenu() override {
ui::Menu* menu = new ui::Menu;
appendMidiDriverMenu(menu, port);
return menu;
}
};


struct MidiDeviceValueItem : ui::MenuItem {
midi::Port* port;
int deviceId;
void onAction(const event::Action& e) override {
@@ -51,30 +65,35 @@ struct MidiDeviceItem : ui::MenuItem {
}
};

static void appendMidiDeviceMenu(ui::Menu* menu, midi::Port* port) {
if (!port)
return;

{
MidiDeviceValueItem* item = new MidiDeviceValueItem;
item->port = port;
item->deviceId = -1;
item->text = "(No device)";
item->rightText = CHECKMARK(item->deviceId == port->deviceId);
menu->addChild(item);
}

for (int deviceId : port->getDeviceIds()) {
MidiDeviceValueItem* item = new MidiDeviceValueItem;
item->port = port;
item->deviceId = deviceId;
item->text = port->getDeviceName(deviceId);
item->rightText = CHECKMARK(item->deviceId == port->deviceId);
menu->addChild(item);
}
}

struct MidiDeviceChoice : LedDisplayChoice {
midi::Port* port;
void onAction(const event::Action& e) override {
if (!port)
return;

ui::Menu* menu = createMenu();
menu->addChild(createMenuLabel("MIDI device"));
{
MidiDeviceItem* item = new MidiDeviceItem;
item->port = port;
item->deviceId = -1;
item->text = "(No device)";
item->rightText = CHECKMARK(item->deviceId == port->deviceId);
menu->addChild(item);
}
for (int deviceId : port->getDeviceIds()) {
MidiDeviceItem* item = new MidiDeviceItem;
item->port = port;
item->deviceId = deviceId;
item->text = port->getDeviceName(deviceId);
item->rightText = CHECKMARK(item->deviceId == port->deviceId);
menu->addChild(item);
}
appendMidiDeviceMenu(menu, port);
}
void step() override {
text = port ? port->getDeviceName(port->deviceId) : "";
@@ -88,7 +107,17 @@ struct MidiDeviceChoice : LedDisplayChoice {
}
};

struct MidiChannelItem : ui::MenuItem {
struct MidiDeviceItem : ui::MenuItem {
midi::Port* port;
ui::Menu* createChildMenu() override {
ui::Menu* menu = new ui::Menu;
appendMidiDeviceMenu(menu, port);
return menu;
}
};


struct MidiChannelValueItem : ui::MenuItem {
midi::Port* port;
int channel;
void onAction(const event::Action& e) override {
@@ -96,28 +125,41 @@ struct MidiChannelItem : ui::MenuItem {
}
};

static void appendMidiChannelMenu(ui::Menu* menu, midi::Port* port) {
if (!port)
return;

for (int channel : port->getChannels()) {
MidiChannelValueItem* item = new MidiChannelValueItem;
item->port = port;
item->channel = channel;
item->text = port->getChannelName(channel);
item->rightText = CHECKMARK(item->channel == port->channel);
menu->addChild(item);
}
}

struct MidiChannelChoice : LedDisplayChoice {
midi::Port* port;
void onAction(const event::Action& e) override {
if (!port)
return;

ui::Menu* menu = createMenu();
menu->addChild(createMenuLabel("MIDI channel"));
for (int channel : port->getChannels()) {
MidiChannelItem* item = new MidiChannelItem;
item->port = port;
item->channel = channel;
item->text = port->getChannelName(channel);
item->rightText = CHECKMARK(item->channel == port->channel);
menu->addChild(item);
}
appendMidiChannelMenu(menu, port);
}
void step() override {
text = port ? port->getChannelName(port->channel) : "Channel 1";
}
};

struct MidiChannelItem : ui::MenuItem {
midi::Port* port;
ui::Menu* createChildMenu() override {
ui::Menu* menu = new ui::Menu;
appendMidiChannelMenu(menu, port);
return menu;
}
};


void MidiWidget::setMidiPort(midi::Port* port) {
clearChildren();
@@ -154,5 +196,20 @@ void MidiWidget::setMidiPort(midi::Port* port) {
}


void appendMidiMenu(ui::Menu* menu, midi::Port* port) {
MidiDriverItem* driverItem = createMenuItem<MidiDriverItem>("MIDI driver", RIGHT_ARROW);
driverItem->port = port;
menu->addChild(driverItem);

MidiDeviceItem* deviceItem = createMenuItem<MidiDeviceItem>("MIDI device", RIGHT_ARROW);
deviceItem->port = port;
menu->addChild(deviceItem);

MidiChannelItem* channelItem = createMenuItem<MidiChannelItem>("MIDI channel", RIGHT_ARROW);
channelItem->port = port;
menu->addChild(channelItem);
}


} // namespace app
} // namespace rack

Loading…
Cancel
Save