2

I'm trying to write a small program in order to change the master volume of a given device. Currently it looks like this

import java.util.*;
import javax.sound.sampled.*;

public class VolumeControl {

    public static void main(String[] args) throws Exception {
        Mixer mixer = findMixer(args[0]);

        changeVolume(mixer, Integer.valueOf(args[1]));
    }

    private static Mixer findMixer(String name) {
        Mixer.Info mixerInfo = Arrays.stream(AudioSystem.getMixerInfo())
            .filter(info -> name.equals(info.getName()))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException(String.format("no mixer with the name '%s' found", name)));
        return AudioSystem.getMixer(mixerInfo);
    }

    private static void changeVolume(Mixer mixer, int level) throws LineUnavailableException {
        for(Line.Info info : mixer.getSourceLineInfo()) {
            try(Line line = mixer.getLine(info)) {
                if (!line.isOpen()) line.open();

                FloatControl control = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN);
                control.setValue(limit(control.getMinimum(), control.getMaximum(), (float) level));
            }
        }
    }

    private static float limit(float min, float max, float level) {
        return Math.min(max, Math.max(min, level));
    }
}

When I compile and run this with my device name I always get the following exception

Exception in thread "main" java.lang.IllegalArgumentException: illegal call to open() in interface Clip
        at com.sun.media.sound.DirectAudioDevice$DirectClip.implOpen(Unknown Source)
        at com.sun.media.sound.AbstractDataLine.open(Unknown Source)
        at com.sun.media.sound.AbstractDataLine.open(Unknown Source)
        at VolumeControl.changeVolume(VolumeControl.java:23)
        at VolumeControl.main(VolumeControl.java:9)

Am I doing anything wrong? I searched for this error on the internet but didn't found anything useful.

How can I get rid of this exception and/or understand what this actually means?

halfer
  • 19,824
  • 17
  • 99
  • 186
JeffreyH
  • 31
  • 5
  • Answer is already [here](http://stackoverflow.com/questions/36536144/error-loading-audio-in-java-illegal-call-to-open-in-interface-clip). First Google result for your exception. (I would flag, but I accidentally removed my flag) – Salem Jan 30 '17 at 19:31
  • I also saw that post.. but this guy wants to play an audio file. I just want to change the master volume of my sound interface – JeffreyH Jan 30 '17 at 20:47
  • The context doesn't matter, the solution to your exception was provided in the answers.. – Salem Jan 30 '17 at 21:39

1 Answers1

0

I have updated my code. Now it looks like this

import java.util.*;
import javax.sound.sampled.*;

public class VolumeControl {

    public static void main(String[] args) throws Exception {
        Mixer mixer = findMixer(args[0]));

        changeVolume(mixer, Integer.valueOf(args[1]));
    }

    private static Mixer findMixer(String name) {
        Mixer.Info mixerInfo = Arrays.stream(AudioSystem.getMixerInfo())
            .filter(info -> name.equals(info.getName()))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException(String.format("no mixer with the name '%s' found", name)));
        return AudioSystem.getMixer(mixerInfo);
    }

    private static void changeVolume(Mixer mixer, int level) throws LineUnavailableException {
        for(Line.Info info : mixer.getSourceLineInfo()) {
            Line line = mixer.getLine(info);
            boolean shouldOpen = !(line.isOpen() || line instanceof Clip);
            try {
                if (shouldOpen) line.open();

                FloatControl control = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN);
                control.setValue(limit(control.getMinimum(), control.getMaximum(), (float) level));
            } finally {
                if (shouldOpen) {
                    line.close();
                }
            }
        }
    }

    private static float limit(float min, float max, float level) {
        return Math.min(max, Math.max(min, level));
    }
}

Now I am not getting any exceptions but the master volume does not change anyway.

I also tried to use mixer.getTargetLineInfo() but the volume didn't changed neither.

I read that with Windows Vista a new sound architecture was introduced so I tried to create an exe file and ran it in Windows XP compatibility mode with the same result.

After some research I found this class which - as expected - didnt work too. It gave me a master volume of null as the method getMasterOutputLine() returned null.

I have no glue what to do next :( Maybe anyone of you can give me some hints or even an SSCCE.

JeffreyH
  • 31
  • 5