Thanks for the input everyone! I would still be happy to get more responses, but here is what I’m thinking so far:
First, I’ll add a buffer size when opening a line as nsigma suggested and I’ll probably also add another init() function that takes a Mixer.Info so the user of the library can select a Mixer or pass that responsibility onto the user of the software via a panel or something.
When a Mixer.Info is not provided, however, I’ll have to decide where to get a SourceDataLine. Right now, I just leave that up to the AudioSystem. That seems to work for most everyone, so I don’t want to make the library less robust for rare cases. If, however, I can add a little complexity to the internals to account for some rare cases and still be robust I’d like to do that. Based on nsigma’s input about the index of the best mixer, and Nyhm and nsigma’s input on Java Sound needing exclusive access to the soundcard, I figure that I want to pick the first Mixer that can support my Line and which has fewer Lines open than it can handle. Looking at the API docs, I’ve come up with this:
public static Mixer findMixer(AudioFormat format) {
DataLine.Info lineInfo = new DataLine.Info(SourceDataLine.class,
format);
Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
//check each available mixer to see if it is acceptable
for (int i = 0; i < mixerInfos.length; i++) {
Mixer mixer = AudioSystem.getMixer(mixerInfos[i]);
//first check if it supports our line
if (!mixer.isLineSupported(lineInfo)) {
continue; //nope
}
//now check if we've used up our lines
int maxLines = mixer.getMaxLines(lineInfo);
//if it's not specified, it's supposedly unlimited
if (maxLines == AudioSystem.NOT_SPECIFIED) {
return mixer;
}
//otherwise we should count them
int linesOpen = 0;
Line[] sourceLines = mixer.getSourceLines();
for (int s = 0; s < sourceLines.length; s++) {
//check if it matches our line
if (sourceLines[s].getLineInfo().matches(lineInfo)) {
linesOpen++; //one line used up
}
}
//now we can see if any are available
if (maxLines > linesOpen) {
return mixer;
}
}
//couldn't find one
return null;
}
Alternatively, I could just iterate through trying to open Lines until I get one, but I don’t like using Exceptions as normal behavior. I’ll play around with this, but if anyone knows of any undocumented reasons that this code is broken (there seems to be a lot of pitfalls in the Linux implementations) I would be glad to know.