Skip to content

Commit 1cc24bb

Browse files
committed
Fixed no audio when selecting another track (#101)
1 parent 7b6ddd5 commit 1cc24bb

1 file changed

Lines changed: 57 additions & 33 deletions

File tree

core/src/main/java/xyz/gianlu/librespot/player/LinesHolder.java

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77

88
import javax.sound.sampled.*;
99
import java.util.*;
10+
import java.util.concurrent.atomic.AtomicBoolean;
1011

1112
/**
1213
* @author Gianlu
1314
*/
1415
public class LinesHolder {
1516
private static final Logger LOGGER = Logger.getLogger(LinesHolder.class);
16-
private final Map<Mixer, Line> openLines = new HashMap<>();
17+
private final Map<Mixer, LineWithState> openLines = new HashMap<>();
1718

1819
LinesHolder() {
1920
}
@@ -52,15 +53,6 @@ private static Mixer findMixer(@NotNull List<Mixer> mixers, @Nullable String[] k
5253
return list.get(0);
5354
}
5455

55-
private static boolean isCompatible(@NotNull DataLine.Info line, @NotNull DataLine.Info other) {
56-
for (AudioFormat format : other.getFormats()) {
57-
if (!line.isFormatSupported(format))
58-
return false;
59-
}
60-
61-
return true;
62-
}
63-
6456
@NotNull
6557
public LineWrapper getLine(@NotNull Mixer mixer, @NotNull DataLine.Info info) {
6658
return new LineWrapper(mixer, info);
@@ -81,10 +73,48 @@ public static class MixerException extends Exception {
8173
}
8274
}
8375

76+
private static class LineWithState {
77+
private final SourceDataLine line;
78+
private final AtomicBoolean free = new AtomicBoolean(true);
79+
80+
LineWithState(@NotNull SourceDataLine line) {
81+
this.line = line;
82+
}
83+
84+
boolean isCompatible(@NotNull DataLine.Info other) {
85+
for (AudioFormat format : other.getFormats()) {
86+
if (!((DataLine.Info) line.getLineInfo()).isFormatSupported(format))
87+
return false;
88+
}
89+
90+
return true;
91+
}
92+
93+
void waitFreed() throws InterruptedException {
94+
synchronized (free) {
95+
if (free.get()) return;
96+
free.wait();
97+
}
98+
}
99+
100+
void free() {
101+
synchronized (free) {
102+
free.set(true);
103+
free.notifyAll();
104+
}
105+
}
106+
107+
void busy() {
108+
synchronized (free) {
109+
free.set(false);
110+
}
111+
}
112+
}
113+
84114
public class LineWrapper {
85115
private Mixer mixer;
86116
private DataLine.Info info;
87-
private SourceDataLine openLine;
117+
private LineWithState openLine;
88118

89119
private LineWrapper(@NotNull Mixer mixer, @NotNull DataLine.Info info) {
90120
this.mixer = mixer;
@@ -93,60 +123,54 @@ private LineWrapper(@NotNull Mixer mixer, @NotNull DataLine.Info info) {
93123

94124
public void write(byte[] buffer, int from, int to) {
95125
if (openLine == null) throw new IllegalStateException();
96-
openLine.write(buffer, from, to);
126+
openLine.line.write(buffer, from, to);
97127
}
98128

99129
public void open(@NotNull AudioFormat format) throws LineUnavailableException, InterruptedException {
100-
Line line = openLines.get(mixer);
101-
if (line != null && isCompatible((DataLine.Info) line.getLineInfo(), info)) {
102-
openLine = (SourceDataLine) line;
103-
synchronized (openLine) {
104-
openLine.wait();
105-
}
130+
LineWithState line = openLines.get(mixer);
131+
if (line != null && line.isCompatible(info)) {
132+
openLine = line;
133+
line.waitFreed();
106134

107135
LOGGER.trace(String.format("Reused line for mixer '%s'.", mixer.getMixerInfo().getName()));
108136
} else {
109137
if (line != null) {
110-
synchronized (line) {
111-
line.wait();
112-
line.close();
113-
}
138+
line.waitFreed();
139+
line.line.close();
114140
}
115141

116-
openLine = (SourceDataLine) mixer.getLine(info);
142+
openLine = new LineWithState((SourceDataLine) mixer.getLine(info));
117143
openLines.put(mixer, openLine);
118-
openLine.open(format);
144+
openLine.line.open(format);
119145
LOGGER.trace(String.format("New line opened for mixer '%s'.", mixer.getMixerInfo().getName()));
120146
}
147+
148+
openLine.busy();
121149
}
122150

123151
public void close() {
124-
if (openLine != null) {
125-
synchronized (openLine) {
126-
openLine.notifyAll();
127-
}
128-
}
152+
if (openLine != null) openLine.free();
129153
}
130154

131155
public void stop() {
132156
if (openLine == null) throw new IllegalStateException();
133-
openLine.stop();
157+
openLine.line.stop();
134158
}
135159

136160
public void start() {
137161
if (openLine == null) throw new IllegalStateException();
138-
openLine.start();
162+
openLine.line.start();
139163
}
140164

141165
public boolean isControlSupported(@NotNull Control.Type type) {
142166
if (openLine == null) throw new IllegalStateException();
143-
return openLine.isControlSupported(type);
167+
return openLine.line.isControlSupported(type);
144168
}
145169

146170
@NotNull
147171
public Control getControl(@NotNull Control.Type type) {
148172
if (openLine == null) throw new IllegalStateException();
149-
return openLine.getControl(type);
173+
return openLine.line.getControl(type);
150174
}
151175
}
152176
}

0 commit comments

Comments
 (0)