I have a Java (1.6) application which plays Wave files using the JavaSound API.
The problem I'm having is that after each reboot of the machine, the master volume control on the machine is set to zero (I think it's the motherboard monitor software doing this, but haven't been able to get anywhere with the manufacturer).
What I would like to do is to have my Java application just adjust the volume to 100% each time it begins to play the Wave file (note: The application sends the sound to a home theater system, where the user controls the volume. The application (machine's) volume should always be 100%).
I've been going through the JavaSound documentation, and can't find a way to do this.
I've written a simple test program to play with this. This program calls AudioSystem.getMixerInfo() to get a list of Mixer.Info objects.
My machine has 8 Mixer.Info objects.
I then call mixer.getSourceLineInfo() to get a list of Line.Info objects.
I then call mixer.getLine(lineInfo) to get a line.
I then call line.getControl(FloatControl.Type.MASTER_GAIN) on the line to get the volume control.
No matter what I set the master volume to on the machine, the volume control's getValue() returns 0.0
No matter what I pass to the volume control's setValue(), the master volume doesn't change.
Is it possible to adjust the volume control on the PC from within a Java application?
Can anyone point me to a tutorial/sample which shows how to do it?
Here is the code from my sample application, if it helps:
Your desired volume or master gain control may be embedded into another control. What happens if you print out all controls?
By the way, instead of trying to retrieve the control and catching an exception, use isControlSupported to check.
Thanks, Rob. Now I'm seeing lots of controls, and one of them includes a volume setting which appears to be tracking what I set the PC's volume control to. It's under a mixer named "Port SoundMAX HD Audio" -> Line.Info: "SPEAKER target port", then under a Control named "Wave Control", sub control named "Volume".
I will start playing with this and see if I can set the volume next.
Mark E Hansen
posted 10 years ago
Thanks so much for your help. I finally got it working. It seem really complicated the way they lay out the controls in such a hierarchical manner, but I have it adjusting both the Master controls as well as the controls which belong to the Wave Controls, and it's doing what I want.
The control layout is not determined by Java but by the operating system. I've written a volume control-like program in Java that just uses this grouping. The only custom grouping I'm doing is take all non-compound controls of the line and group them in the user interface under the "master" group. So if I would have this structure
then I have two panes: one called master with the first three controls and one called wave control.
Thanks again, Rob. I guess I have mine set up the same way. The thing I don't like is that it seems like magic to locate the proper controls. For example, when looking for the correct line, I'm using lineInfo.toString().contains("SPEAKER"). This seems a little fragile - will the line I want always include the word "SPEAKER", or is that just the word used by the particular sound driver used by the O/S on my machine?
I have a similar concern when locating the Wave controls. I'm using control.toString().contains("Wave Control")
Finally, when identifying the specific controls, some of them are not too hard. For example, the Volume control can be identified this way: if (controlType.equals(FloatControl.Type.VOLUME)), but there are others which aren't so easy. For example there's one which disables digital output. I'm guessing this is particular to my sound card/drivers. I have to identify it this way: if ("Disable digital output".equals(controlType.toString())).
The speaker can be retrieved using Port.Info.SPEAKER with Mixer.getLine (after of course checking the return value of Mixer.isLineSupported). For controls it is possible to use the same technique, but only for a few controls and it probably doesn't work if the volume is stored in a compound control.
The following prints out all mixers with their SPEAKER port and their volume control - if they have them:
Does anyone know if this same code will work on Mac OS X? I'm not able to get it to. . . this is what I get when I run the above code:
There are 3 mixer info objects
mixer name: Java Sound Audio Engine
mixer name: Built-in Microphone
Line.Info: interface TargetDataLine supporting 64 audio formats
java.lang.IllegalArgumentException: Unsupported control type: Volume
java(19564,0x100501000) malloc: *** error for object 0x4000000000004: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug