- // Card choices.
- QComboBox *card_combo = new QComboBox;
- card_combo->addItem(QString("(none) "));
- for (const string &name : card_names) {
- card_combo->addItem(QString::fromStdString(name + " "));
- }
- switch (bus.device.type) {
- case InputSourceType::SILENCE:
- card_combo->setCurrentIndex(0);
- break;
- case InputSourceType::CAPTURE_CARD:
- card_combo->setCurrentIndex(mapping.buses[row].device.index + 1);
- break;
- default:
- assert(false);
+ // Card choices. If there's already a combobox here, we try to modify
+ // the elements in-place, so that the UI doesn't go away under the user's feet
+ // if they are in the process of choosing an item.
+ QComboBox *card_combo = static_cast<QComboBox *>(ui->table->cellWidget(row, 1));
+ if (card_combo == nullptr) {
+ card_combo = new QComboBox;
+ }
+ unsigned current_index = 0;
+ if (card_combo->count() == 0) {
+ card_combo->addItem(QString("(none) "));
+ }
+ for (const auto &spec_and_info : devices) {
+ QString label(QString::fromStdString(spec_and_info.second.display_name));
+ if (spec_and_info.first.type == InputSourceType::ALSA_INPUT) {
+ ALSAPool::Device::State state = global_audio_mixer->get_alsa_card_state(spec_and_info.first.index);
+ if (state == ALSAPool::Device::State::EMPTY) {
+ continue;
+ } else if (state == ALSAPool::Device::State::STARTING) {
+ label += " (busy)";
+ } else if (state == ALSAPool::Device::State::DEAD) {
+ label += " (dead)";
+ }
+ }
+ ++current_index;
+ if (unsigned(card_combo->count()) > current_index) {
+ card_combo->setItemText(current_index, label + " ");
+ card_combo->setItemData(current_index, qulonglong(DeviceSpec_to_key(spec_and_info.first)));
+ } else {
+ card_combo->addItem(
+ label + " ",
+ qulonglong(DeviceSpec_to_key(spec_and_info.first)));
+ }
+ if (bus.device == spec_and_info.first) {
+ card_combo->setCurrentIndex(current_index);
+ }
+ }
+ // Remove any excess items from earlier. (This is only for paranoia;
+ // they should be held, so it shouldn't matter.)
+ while (unsigned(card_combo->count()) > current_index + 1) {
+ card_combo->removeItem(current_index + 1);