Merge branch 'master' of github.com:badvision/lawless-legends

This commit is contained in:
Martin Haye 2018-09-29 09:46:27 -07:00
commit bca78c5040
13 changed files with 226 additions and 182 deletions

View File

@ -167,5 +167,10 @@
<artifactId>poi-ooxml</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.controlsfx</groupId>
<artifactId>controlsfx</artifactId>
<version>8.40.14</version>
</dependency>
</dependencies>
</project>

View File

@ -96,7 +96,7 @@ public class DataUtilities {
}
private static void logScripts(Scripts scripts, PrintWriter logger) {
if (scripts != null && scripts.getScript() != null || !scripts.getScript().isEmpty()) {
if (scripts != null && scripts.getScript() != null && !scripts.getScript().isEmpty()) {
scripts.getScript().forEach((script) -> {
if (script.getBlock() == null) {
return;

View File

@ -23,6 +23,8 @@ import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import org.badvision.outlaweditor.data.xml.Rows.Row;
import org.badvision.outlaweditor.data.xml.UserType;
import org.controlsfx.control.spreadsheet.SpreadsheetColumn;
import org.controlsfx.control.spreadsheet.SpreadsheetView;
/**
*
@ -35,10 +37,10 @@ public abstract class SheetEditorController implements Initializable {
protected URL location;
@FXML
protected TableColumn<UserType, String> addColumn;
protected SpreadsheetColumn addColumn;
@FXML
protected TableView<Row> table;
protected SpreadsheetView table;
@FXML
protected TextField sheetNameField;

View File

@ -17,25 +17,20 @@ package org.badvision.outlaweditor.ui.impl;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.stage.FileChooser;
import javafx.util.converter.DefaultStringConverter;
import javax.xml.bind.JAXBException;
import org.badvision.outlaweditor.SheetEditor;
import org.badvision.outlaweditor.TransferHelper;
@ -49,12 +44,16 @@ import org.badvision.outlaweditor.data.xml.UserType;
import org.badvision.outlaweditor.ui.ApplicationUIController;
import org.badvision.outlaweditor.ui.SheetEditorController;
import org.badvision.outlaweditor.ui.UIAction;
import org.controlsfx.control.spreadsheet.GridBase;
import org.controlsfx.control.spreadsheet.SpreadsheetCell;
import org.controlsfx.control.spreadsheet.SpreadsheetCellBase;
public class SheetEditorControllerImpl extends SheetEditorController {
private SheetEditor editor;
private ObservableList<Row> tableData;
private final ListChangeListener columnChangeListener = c -> syncData();
private ObservableList<ObservableList<SpreadsheetCell>> tableData;
private int lastEditRow = 0;
private int lastEditCol = 0;
/**
* Initializes the controller class.
@ -62,24 +61,17 @@ public class SheetEditorControllerImpl extends SheetEditorController {
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize();
tableData = FXCollections.observableArrayList();
table.setItems(tableData);
tableData = table.getGrid().getRows();
table.setEditable(true);
table.setRowFactory(tableView -> {
final TableRow<Row> row = new TableRow<>();
final ContextMenu contextMenu = new ContextMenu(
createMenuItem("Insert Row", () -> tableData.add(row.getIndex(), new Row())),
createMenuItem("Clone Row", () -> cloneRow(row.getItem())),
createMenuItem("Delete Row", () -> deleteRowWithConfirmation(row.getItem()))
);
row.contextMenuProperty().bind(
Bindings.when(row.emptyProperty())
.then((ContextMenu) null)
.otherwise(contextMenu)
);
return row;
});
table.getContextMenu().getItems().addAll(
createMenuItem("Insert Row", () -> insertRow(new Row(), getSelectedRow())),
createMenuItem("Clone Row", () -> cloneRow(editor.getSheet().getRows().getRow().get(getSelectedRow()))),
createMenuItem("Delete Row", () -> deleteRowWithConfirmation(editor.getSheet().getRows().getRow().get(getSelectedRow())))
);
}
private int getSelectedRow() {
return table.getSelectionModel().getFocusedCell().getRow();
}
@Override
@ -132,86 +124,52 @@ public class SheetEditorControllerImpl extends SheetEditorController {
if (editor.getSheet().getColumns() == null) {
editor.getSheet().setColumns(new Columns());
}
editor.getSheet().getColumns().getColumn().add(col);
insertViewColumn(col);
insertColumn(col);
rebuildGridUI();
}
}
@Override
public void addRowAction(ActionEvent event) {
insertViewRow(new Row());
insertRow(new Row(), -1);
}
//--------
private void buildTableFromSheet() {
table.getColumns().removeListener(columnChangeListener);
if (editor.getSheet().getColumns() != null) {
editor.getSheet().getColumns().getColumn().stream().forEach(this::insertViewColumn);
}
if (editor.getSheet().getRows() != null) {
tableData.setAll(editor.getSheet().getRows().getRow());
rebuildGridUI();
}
sheetNameField.textProperty().set(editor.getSheet().getName());
sheetNameField.textProperty().addListener((value, oldValue, newValue) -> {
editor.getSheet().setName(newValue);
ApplicationUIController.getController().updateSelectors();
});
table.getColumns().addListener(columnChangeListener);
}
private void insertViewColumn(UserType col) {
insertViewColumn(col, -1);
private void insertColumn(UserType col) {
insertColumn(col, -1);
}
private void insertViewColumn(UserType col, int pos) {
if (pos < 0) {
pos = table.getColumns().size();
private void insertColumn(UserType col, int pos) {
table.getGrid().getColumnHeaders().clear();
if (pos < 0 || pos >= editor.getSheet().getColumns().getColumn().size()) {
editor.getSheet().getColumns().getColumn().add(col);
} else {
editor.getSheet().getColumns().getColumn().add(pos, col);
}
TableColumn<Row, String> tableCol = new TableColumn<>(col.getName());
tableCol.setCellValueFactory((features) -> {
String val = getValue(features.getValue().getOtherAttributes(), col.getName());
if (val == null) {
val = "";
}
return new SimpleObjectProperty(val);
});
tableCol.setCellFactory((TableColumn<Row, String> param) -> {
TextFieldTableCell<Row, String> myCell = new TextFieldTableCell<Row, String>(new DefaultStringConverter()) {
@Override
/**
* Patch behavior so that any change is immediately persisted,
* enter is not required.
*/
public void startEdit() {
super.startEdit();
TextField textField = (TextField) getGraphic();
textField.textProperty().addListener((p, o, n) -> {
setItem(n);
int index = this.getTableRow().getIndex();
Row row = tableData.get(index);
setValue(row.getOtherAttributes(), col.getName(), n);
});
}
};
return myCell;
});
tableCol.setOnEditCommit((event) -> {
table.requestFocus();
table.getSelectionModel().clearSelection();
});
tableCol.setEditable(true);
tableCol.setContextMenu(new ContextMenu(
createMenuItem("Rename Column", () -> renameColumn(col)),
createMenuItem("Delete Column", () -> deleteColumnWithConfirmation(col))
));
table.getColumns().add(pos, tableCol);
rebuildColumnHeaders();
}
private void insertViewRow(Row row) {
tableData.add(row);
syncData();
private void insertRow(Row row, int pos) {
if (editor.getSheet().getRows() == null) {
editor.getSheet().setRows(new Rows());
}
if (pos < 0 || pos >= editor.getSheet().getRows().getRow().size()) {
editor.getSheet().getRows().getRow().add(row);
} else {
editor.getSheet().getRows().getRow().add(pos, row);
}
rebuildGridUI();
}
private MenuItem createMenuItem(String text, Runnable action) {
@ -232,60 +190,80 @@ public class SheetEditorControllerImpl extends SheetEditorController {
UserType newCol = new UserType();
newCol.setName(newColName);
editor.getSheet().getColumns().getColumn().add(newCol);
tableData.forEach(row -> setValue(row.getOtherAttributes(), newColName, getValue(row.getOtherAttributes(), col.getName())));
int oldPos = deleteColumn(col);
insertViewColumn(newCol, oldPos);
editor.getSheet().getRows().getRow()
.forEach(row -> {
setValue(row.getOtherAttributes(), newColName, getValue(row.getOtherAttributes(), col.getName()));
});
deleteColumn(col);
}
}
private int deleteColumn(UserType col) {
private void deleteColumn(UserType col) {
editor.getSheet().getColumns().getColumn().remove(col);
tableData.stream()
editor.getSheet().getRows().getRow().stream()
.map(Row::getOtherAttributes)
.forEach(
m -> m.keySet().removeIf(n -> n.getLocalPart().equals(col.getName()))
);
int colNumber = findColumn(col);
if (colNumber >= 0) {
table.getColumns().remove(colNumber);
}
return colNumber;
rebuildGridUI();
}
private void deleteRowWithConfirmation(Row row) {
UIAction.confirm("Delete row, are you sure?", ()->{
tableData.remove(row);
syncData();
}, ()->{});
UIAction.confirm("Delete row, are you sure?", () -> {
editor.getSheet().getRows().getRow().remove(row);
rebuildGridUI();
}, () -> {
});
}
private void cloneRow(Row row) {
try {
Row newRow = TransferHelper.cloneObject(row, Row.class, "row");
tableData.add(tableData.lastIndexOf(row), newRow);
syncData();
Row newRow = TransferHelper.cloneObject(row, Row.class, "row");
int pos = editor.getSheet().getRows().getRow().indexOf(row);
insertRow(newRow, pos);
} catch (JAXBException ex) {
Logger.getLogger(SheetEditorControllerImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void syncData() {
if (editor.getSheet().getRows() == null) {
editor.getSheet().setRows(new Rows());
}
editor.getSheet().getRows().getRow().clear();
editor.getSheet().getRows().getRow().addAll(tableData);
editor.getSheet().getColumns().getColumn().sort((t1, t2) -> {
return Integer.compare(findColumn(t1), findColumn(t2));
});
}
private int findColumn(UserType col) {
for (int i = 0; i < table.getColumns().size(); i++) {
if (table.getColumns().get(i).getText().equals(col.getName())) {
return i;
private void rebuildGridUI() {
int numCols = editor.getSheet().getColumns().getColumn().size();
int numRows = editor.getSheet().getRows() == null ? 0 : editor.getSheet().getRows().getRow().size();
table.setGrid(new GridBase(numRows, numCols));
rebuildColumnHeaders();
tableData = FXCollections.observableList(new ArrayList(numRows));
if (editor.getSheet().getRows() != null) {
int rowNum = 0;
for (Row row : editor.getSheet().getRows().getRow()) {
int colNum = 0;
ObservableList<SpreadsheetCell> rowUi = FXCollections.observableList(new ArrayList<>(numCols));
tableData.add(rowUi);
for (UserType col : editor.getSheet().getColumns().getColumn()) {
String value = getValue(row.getOtherAttributes(), col.getName());
SpreadsheetCellBase cell = new SpreadsheetCellBase(rowNum, colNum, 1, 1);
cell.setItem(value);
cell.itemProperty().addListener((ObservableValue<? extends Object> val, Object oldVal, Object newVal) -> {
setValue(row.getOtherAttributes(), col.getName(), String.valueOf(newVal));
});
rowUi.add(cell);
colNum++;
}
rowNum++;
}
}
return -1;
table.getGrid().setRows(tableData);
}
private void rebuildColumnHeaders() {
int numCols = editor.getSheet().getColumns().getColumn().size();
table.getGrid().getColumnHeaders().addAll(
editor.getSheet().getColumns().getColumn().stream()
.map(UserType::getName)
.collect(Collectors.toCollection(
() -> FXCollections.observableList(new ArrayList<>(numCols))
))
);
}
}

View File

@ -12,6 +12,7 @@
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<?import org.controlsfx.control.spreadsheet.SpreadsheetView?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" styleClass="sheetEditor" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.badvision.outlaweditor.ui.impl.SheetEditorControllerImpl">
<stylesheets>
@ -48,7 +49,7 @@
<Button mnemonicParsing="false" onAction="#addRowAction" text="Add Row" />
</items>
</ToolBar>
<TableView fx:id="table" editable="true" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" />
<SpreadsheetView fx:id="table" editable="true" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" />
</children>
</VBox>
</children>

View File

@ -209,8 +209,6 @@ public class Apple2e extends Computer {
}
super.reconfigure();
RAM128k currentMemory = (RAM128k) getMemory();
if (currentMemory != null && ramCard.getValue() != null && !(currentMemory.getClass().equals(ramCard.getValue()))) {
try {
@ -242,46 +240,38 @@ public class Apple2e extends Computer {
accelerator = new ZipWarpAccelerator(this);
}
if (acceleratorEnabled) {
accelerator.attach();
motherboard.miscDevices.add(accelerator);
motherboard.addChildDevice(accelerator);
} else {
accelerator.detach();
motherboard.miscDevices.remove(accelerator);
motherboard.removeChildDevice(accelerator);
}
if (joy1enabled) {
if (joystick1 == null) {
joystick1 = new Joystick(0, this);
motherboard.miscDevices.add(joystick1);
joystick1.attach();
motherboard.addChildDevice(joystick1);
}
} else if (joystick1 != null) {
joystick1.detach();
motherboard.miscDevices.remove(joystick1);
motherboard.removeChildDevice(joystick1);
joystick1 = null;
}
if (joy2enabled) {
if (joystick2 == null) {
joystick2 = new Joystick(1, this);
motherboard.miscDevices.add(joystick2);
joystick2.attach();
motherboard.addChildDevice(joystick2);
}
} else if (joystick2 != null) {
joystick2.detach();
motherboard.miscDevices.remove(joystick2);
motherboard.removeChildDevice(joystick2);
joystick2 = null;
}
if (clockEnabled) {
if (clock == null) {
clock = new NoSlotClock(this);
motherboard.miscDevices.add(clock);
clock.attach();
motherboard.addChildDevice(clock);
}
} else if (clock != null) {
motherboard.miscDevices.remove(clock);
clock.detach();
motherboard.removeChildDevice(clock);
clock = null;
}
}
@ -344,7 +334,7 @@ public class Apple2e extends Computer {
if (cheatEngine.getValue() == null) {
if (activeCheatEngine != null) {
activeCheatEngine.detach();
motherboard.miscDevices.remove(activeCheatEngine);
motherboard.addChildDevice(activeCheatEngine);
}
activeCheatEngine = null;
} else {
@ -353,9 +343,8 @@ public class Apple2e extends Computer {
if (activeCheatEngine.getClass().equals(cheatEngine.getValue())) {
startCheats = false;
} else {
activeCheatEngine.detach();
motherboard.removeChildDevice(activeCheatEngine);
activeCheatEngine = null;
motherboard.miscDevices.remove(activeCheatEngine);
}
}
if (startCheats) {
@ -364,13 +353,15 @@ public class Apple2e extends Computer {
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
}
activeCheatEngine.attach();
motherboard.miscDevices.add(activeCheatEngine);
motherboard.addChildDevice(activeCheatEngine);
}
}
} catch (IOException ex) {
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
}
super.reconfigure();
if (restart) {
resume();
}

View File

@ -80,10 +80,6 @@ public class MOS65C02 extends CPU {
clearState();
}
@Override
public void reconfigure() {
}
@Override
public void clearState() {
A = 0x0ff;

View File

@ -25,6 +25,7 @@ import jace.core.Device;
import jace.core.Motherboard;
import jace.core.RAMEvent;
import jace.core.RAMListener;
import jace.core.SoundGeneratorDevice;
import jace.core.SoundMixer;
import java.io.File;
import java.io.FileNotFoundException;
@ -44,7 +45,7 @@ import javax.sound.sampled.SourceDataLine;
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class Speaker extends Device {
public class Speaker extends SoundGeneratorDevice {
static boolean fileOutputActive = false;
static OutputStream out;
@ -126,10 +127,10 @@ public class Speaker extends Device {
* Double-buffer used for playing processed sound -- as one is played the
* other fills up.
*/
byte[] primaryBuffer;
byte[] secondaryBuffer;
int bufferPos = 0;
Timer playbackTimer;
private byte[] primaryBuffer;
private byte[] secondaryBuffer;
private int bufferPos = 0;
private Timer playbackTimer;
private final double TICKS_PER_SAMPLE = ((double) Motherboard.SPEED) / SoundMixer.RATE;
private final double TICKS_PER_SAMPLE_FLOOR = Math.floor(TICKS_PER_SAMPLE);
private RAMListener listener = null;
@ -292,6 +293,8 @@ public class Speaker extends Device {
@Override
public final void reconfigure() {
super.reconfigure();
if (primaryBuffer != null && secondaryBuffer != null) {
return;
}

View File

@ -101,6 +101,7 @@ public abstract class Card extends Device {
@Override
public void reconfigure() {
super.reconfigure();
boolean restart = suspend();
unregisterListeners();
if (restart) {

View File

@ -20,6 +20,10 @@ package jace.core;
import jace.state.Stateful;
import jace.config.Reconfigurable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
@ -39,9 +43,14 @@ import javafx.beans.property.SimpleBooleanProperty;
@Stateful
public abstract class Device implements Reconfigurable {
protected Computer computer;
private Device() {
private List<Device> children;
private Device() {
children = Collections.synchronizedList(new ArrayList<>());
}
public Device(Computer computer) {
this();
this.computer = computer;
}
@ -52,6 +61,31 @@ public abstract class Device implements Reconfigurable {
private final BooleanProperty run = new SimpleBooleanProperty(true);
@Stateful
public boolean isPaused = false;
@Stateful
public boolean isAttached = false;
public void addChildDevice(Device d) {
children.add(d);
if (isAttached) {
d.attach();
}
}
public void removeChildDevice(Device d) {
children.remove(d);
d.suspend();
if (isAttached) {
d.detach();
}
}
public void addAllDevices(Collection<Device> devices) {
devices.forEach(this::addChildDevice);
}
public List<Device> getChildren() {
return Collections.unmodifiableList(children);
}
public BooleanProperty getRunningProperty() {
return run;
@ -86,6 +120,7 @@ public abstract class Device implements Reconfigurable {
return;
}
// Implicit else...
children.forEach(Device::doTick);
tick();
}
@ -113,17 +148,24 @@ public abstract class Device implements Reconfigurable {
setRun(false);
return true;
}
children.forEach(Device::suspend);
return false;
}
public void resume() {
setRun(true);
waitCycles = 0;
children.forEach(Device::resume);
}
public abstract void attach();
public void attach() {
isAttached = true;
children.forEach(Device::attach);
}
public void detach() {
Keyboard.unregisterAllHandlers(this);
children.forEach(Device::suspend);
children.forEach(Device::detach);
}
}

View File

@ -41,7 +41,6 @@ import java.util.logging.Logger;
*/
public class Motherboard extends TimedDevice {
final public Set<Device> miscDevices = Collections.synchronizedSet(new LinkedHashSet<>());
@ConfigurableField(name = "Enable Speaker", shortName = "speaker", defaultValue = "true")
public static boolean enableSpeaker = true;
public Speaker speaker;
@ -64,7 +63,7 @@ public class Motherboard extends TimedDevice {
public Motherboard(Computer computer, Motherboard oldMotherboard) {
super(computer);
if (oldMotherboard != null) {
miscDevices.addAll(oldMotherboard.miscDevices);
addAllDevices(oldMotherboard.getChildren());
speaker = oldMotherboard.speaker;
accelorationRequestors.addAll(oldMotherboard.accelorationRequestors);
setSpeedInHz(oldMotherboard.getSpeedInHz());
@ -99,7 +98,6 @@ public class Motherboard extends TimedDevice {
for (Optional<Card> card : cards) {
card.ifPresent(Card::doTick);
}
miscDevices.forEach(Device::doTick);
} catch (Throwable t) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, t);
}
@ -127,7 +125,7 @@ public class Motherboard extends TimedDevice {
speaker = new Speaker(computer);
if (computer.mixer.lineAvailable) {
speaker.attach();
miscDevices.add(speaker);
addChildDevice(speaker);
} else {
System.out.print("No lines available! Speaker not running.");
}
@ -135,14 +133,12 @@ public class Motherboard extends TimedDevice {
speaker.reconfigure();
} catch (Throwable t) {
System.out.println("Unable to initalize sound -- deactivating speaker out");
speaker.detach();
miscDevices.remove(speaker);
removeChildDevice(speaker);
}
} else {
System.out.println("Speaker not enabled, leaving it off.");
if (speaker != null) {
speaker.detach();
miscDevices.remove(speaker);
removeChildDevice(speaker);
}
}
if (startAgain && computer.getMemory() != null) {
@ -200,11 +196,6 @@ public class Motherboard extends TimedDevice {
@Override
public void detach() {
System.out.println("Detaching motherboard");
miscDevices.stream().forEach((d) -> {
d.suspend();
d.detach();
});
miscDevices.clear();
// halt();
super.detach();
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 2018 org.badvision.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jace.core;
/**
* Encapsulate a thread-managed sound device, abstracting aspects of buffer and device management
*/
public abstract class SoundGeneratorDevice extends Device {
public SoundGeneratorDevice(Computer computer) {
super(computer);
}
@Override
public void reconfigure() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void attach() {
super.attach();
}
@Override
public void detach() {
super.detach();
}
}

View File

@ -154,16 +154,14 @@ public class SoundMixer extends Device {
sdl = availableLines.iterator().next();
availableLines.remove(sdl);
}
activeLines.put(requester, sdl);
sdl.start();
activeLines.put(requester, sdl);
return sdl;
}
public void returnLine(Object requester) {
if (activeLines.containsKey(requester)) {
SourceDataLine sdl = activeLines.remove(requester);
// Calling drain on pulse driver can cause it to freeze up (?)
// sdl.drain();
if (sdl.isRunning()) {
sdl.flush();
sdl.stop();
@ -207,16 +205,18 @@ public class SoundMixer extends Device {
@Override
public void attach() {
// if (Motherboard.enableSpeaker)
// Motherboard.speaker.attach();
}
@Override
public void detach() {
availableLines.stream().forEach((line) -> {
line.flush();
line.stop();
line.close();
});
});
Set requesters = new HashSet(activeLines.keySet());
availableLines.clear();
activeLines.clear();
requesters.stream().map((o) -> {
if (o instanceof Device) {
((Device) o).detach();
@ -225,15 +225,6 @@ public class SoundMixer extends Device {
}).filter((o) -> (o instanceof Card)).forEach((o) -> {
((Reconfigurable) o).reconfigure();
});
if (theMixer != null) {
for (Line l : theMixer.getSourceLines()) {
// if (l.isOpen()) {
// l.close();
// }
}
}
availableLines.clear();
activeLines.clear();
super.detach();
}