77
88import javax .sound .sampled .*;
99import java .util .*;
10+ import java .util .concurrent .atomic .AtomicBoolean ;
1011
1112/**
1213 * @author Gianlu
1314 */
1415public 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