+
+void InputMappingDialog::ok_clicked()
+{
+ global_mixer->get_audio_mixer()->set_input_mapping(mapping);
+ accept();
+}
+
+void InputMappingDialog::cancel_clicked()
+{
+ global_mixer->get_audio_mixer()->set_input_mapping(old_mapping);
+ reject();
+}
+
+void InputMappingDialog::cell_changed(int row, int column)
+{
+ if (column != 0) {
+ // Spurious; only really the name column should fire these.
+ return;
+ }
+ mapping.buses[row].name = ui->table->item(row, column)->text().toStdString();
+}
+
+void InputMappingDialog::card_selected(QComboBox *card_combo, unsigned row, int index)
+{
+ uint64_t key = card_combo->itemData(index).toULongLong();
+ mapping.buses[row].device = key_to_DeviceSpec(key);
+ setup_channel_choices_from_bus(row, mapping.buses[row]);
+}
+
+void InputMappingDialog::channel_selected(unsigned row, unsigned channel, int index)
+{
+ mapping.buses[row].source_channel[channel] = index - 1;
+}
+
+void InputMappingDialog::add_clicked()
+{
+ QTableWidgetSelectionRange all(0, 0, ui->table->rowCount() - 1, ui->table->columnCount() - 1);
+ ui->table->setRangeSelected(all, false);
+
+ InputMapping::Bus new_bus;
+ new_bus.name = "New input";
+ new_bus.device.type = InputSourceType::SILENCE;
+ mapping.buses.push_back(new_bus);
+ ui->table->setRowCount(mapping.buses.size());
+
+ unsigned row = mapping.buses.size() - 1;
+ fill_row_from_bus(row, new_bus);
+ ui->table->editItem(ui->table->item(row, 0)); // Start editing the name.
+ update_button_state();
+}
+
+void InputMappingDialog::remove_clicked()
+{
+ assert(ui->table->rowCount() != 0);
+
+ set<int, greater<int>> rows_to_delete; // Need to remove in reverse order.
+ for (const QTableWidgetSelectionRange &range : ui->table->selectedRanges()) {
+ for (int row = range.topRow(); row <= range.bottomRow(); ++row) {
+ rows_to_delete.insert(row);
+ }
+ }
+ if (rows_to_delete.empty()) {
+ rows_to_delete.insert(ui->table->rowCount() - 1);
+ }
+
+ for (int row : rows_to_delete) {
+ ui->table->removeRow(row);
+ mapping.buses.erase(mapping.buses.begin() + row);
+ }
+ update_button_state();
+}
+
+void InputMappingDialog::updown_clicked(int direction)
+{
+ assert(ui->table->selectedRanges().size() == 1);
+ const QTableWidgetSelectionRange &range = ui->table->selectedRanges()[0];
+ int a_row = range.bottomRow();
+ int b_row = range.bottomRow() + direction;
+
+ swap(mapping.buses[a_row], mapping.buses[b_row]);
+ fill_row_from_bus(a_row, mapping.buses[a_row]);
+ fill_row_from_bus(b_row, mapping.buses[b_row]);
+
+ QTableWidgetSelectionRange a_sel(a_row, 0, a_row, ui->table->columnCount() - 1);
+ QTableWidgetSelectionRange b_sel(b_row, 0, b_row, ui->table->columnCount() - 1);
+ ui->table->setRangeSelected(a_sel, false);
+ ui->table->setRangeSelected(b_sel, true);
+}
+
+void InputMappingDialog::update_button_state()
+{
+ ui->add_button->setDisabled(mapping.buses.size() >= MAX_BUSES);
+ ui->remove_button->setDisabled(mapping.buses.size() == 0);
+ ui->up_button->setDisabled(
+ ui->table->selectedRanges().empty() ||
+ ui->table->selectedRanges()[0].bottomRow() == 0);
+ ui->down_button->setDisabled(
+ ui->table->selectedRanges().empty() ||
+ ui->table->selectedRanges()[0].bottomRow() == ui->table->rowCount() - 1);
+}