¿Se puede usar el sonido de Java para controlar el volumen del sistema?

Java Sound ofrece instancias de FloatControl para varias funcionalidades de línea de sonido, y un tipo de control MASTER_GAIN & VOLUME .

¿Se pueden usar estos controles para cambiar el volumen del sistema?

No, no puede. Aquí está la fuente adaptada de una respuesta al Ajuste del volumen maestro en coderanch. La fuente itera las líneas disponibles, comprueba si tienen un control del tipo correcto y, de ser así, las coloca en una GUI adjunta a un JSlider

 import java.awt.*; import javax.swing.*; import javax.sound.sampled.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; public class SoundMixer { public Component getGui() { JPanel gui = new JPanel(new GridLayout(0,1)); Mixer.Info[] mixers = AudioSystem.getMixerInfo(); System.out.println( "There are " + mixers.length + " mixer info objects"); for (Mixer.Info mixerInfo : mixers) { System.out.println("mixer name: " + mixerInfo.getName()); Mixer mixer = AudioSystem.getMixer(mixerInfo); Line.Info[] lineInfos = mixer.getSourceLineInfo(); for (Line.Info lineInfo : lineInfos) { System.out.println(" Line.Info: " + lineInfo); try { Line line = mixer.getLine(lineInfo); FloatControl volCtrl = (FloatControl)line.getControl( FloatControl.Type.MASTER_GAIN); VolumeSlider vs = new VolumeSlider(volCtrl); gui.add( new JLabel(volCtrl.toString()) ); gui.add( vs.getVolume() ); System.out.println( " volCtrl.getValue() = " + volCtrl.getValue()); } catch (LineUnavailableException e) { e.printStackTrace(); } catch (IllegalArgumentException iaEx) { System.out.println(" " + iaEx); } } } return gui; } public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() { SoundMixer sm = new SoundMixer(); Component c = sm.getGui(); JOptionPane.showMessageDialog(null, c); } }; // Swing GUIs should be created and updated on the EDT // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html SwingUtilities.invokeLater(r); } } class VolumeSlider { JSlider volume; VolumeSlider(final FloatControl volumeControl) { volume = new JSlider( (int) volumeControl.getMinimum() * 100, (int) volumeControl.getMaximum() * 100, (int) volumeControl.getValue() * 100); ChangeListener listener = new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { float val = volume.getValue() / 100f; volumeControl.setValue(val); System.out.println( "Setting volume of " + volumeControl.toString() + " to " + val); } }; volume.addChangeListener(listener); } public JSlider getVolume() { return volume; } } 

En esta máquina con Windows 7, recibo dos controles, ambos del “Java Sound Audio Engine”. Ninguno tiene ningún efecto en el volumen del sistema actual.

 run: There are 4 mixer info objects mixer name: Primary Sound Driver Line.Info: interface SourceDataLine supporting 8 audio formats, and buffers of at least 32 bytes java.lang.IllegalArgumentException: Unsupported control type: Master Gain Line.Info: interface Clip supporting 8 audio formats, and buffers of at least 32 bytes java.lang.IllegalArgumentException: Unsupported control type: Master Gain mixer name: Speakers (VIA High Definition Audio) Line.Info: interface SourceDataLine supporting 8 audio formats, and buffers of at least 32 bytes java.lang.IllegalArgumentException: Unsupported control type: Master Gain Line.Info: interface Clip supporting 8 audio formats, and buffers of at least 32 bytes java.lang.IllegalArgumentException: Unsupported control type: Master Gain mixer name: Java Sound Audio Engine Line.Info: interface SourceDataLine supporting 8 audio formats volCtrl.getValue() = 0.0 Line.Info: interface Clip supporting 8 audio formats, and buffers of 0 to 4194304 bytes volCtrl.getValue() = 0.0 mixer name: Port Speakers (VIA High Definition A Setting volume of Master Gain with current value: 0.0 dB (range: -80.0 - 13.9794) to 0.0 Setting volume of Master Gain with current value: 0.0 dB (range: -80.0 - 13.9794) to -0.41 Setting volume of Master Gain with current value: 0.0 dB (range: -80.0 - 13.9794) to -0.68 ... 

Cambie FloatControl.Type.MASTER_GAIN para FloatControl.Type.VOLUME para ver … sin controles.

agregue la siguiente línea justo después de inicializar la línea. esto es requerido para abrir la línea.

 boolean opened = line.isOpen() || line instanceof Clip; if(!opened){ System.out.println("Line is not open, trying to open it..."); line.open(); opened = true; } 

intenta esto, no te decepcionará … podemos modificar el ejemplo superior en consecuencia.

 import javax.sound.sampled.AudioSystem; import javax.sound.sampled.FloatControl; import javax.sound.sampled.Line; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.Mixer; import javax.swing.BoxLayout; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JProgressBar; public class SoundMeter { JFrame j; public SoundMeter() { j = new JFrame("SoundMeter"); j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); j.setLayout(new BoxLayout(j.getContentPane(), BoxLayout.Y_AXIS)); printMixersDetails(); j.setVisible(true); } public void printMixersDetails(){ javax.sound.sampled.Mixer.Info[] mixers = AudioSystem.getMixerInfo(); System.out.println("There are " + mixers.length + " mixer info objects"); for(int i=0;i 

Estoy usando el tipo de control VOLUME . Este código funciona para mí para XP y WIN 7, pero no para OSX. Ver mi ejemplo:

 import java.io.IOException; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.FloatControl; import javax.sound.sampled.Line; import javax.sound.sampled.Mixer; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; public class VolumeExample extends JPanel { /** * @return main sound control object * @throws Exception for any problem */ private FloatControl getVolumeControl() throws Exception { try { Mixer.Info mixers[] = AudioSystem.getMixerInfo(); for (Mixer.Info mixerInfo : mixers) { Mixer mixer = AudioSystem.getMixer(mixerInfo); mixer.open(); //we check only target type lines, because we are looking for "SPEAKER target port" for (Line.Info info : mixer.getTargetLineInfo()) { if (info.toString().contains("SPEAKER")) { Line line = mixer.getLine(info); try { line.open(); } catch (IllegalArgumentException iae) {} return (FloatControl) line.getControl(FloatControl.Type.VOLUME); } } } } catch (Exception ex) { System.out.println("problem creating volume control object:"+ex); throw ex; } throw new Exception("unknown problem creating volume control object"); } VolumeExample() { JSlider slider = new JSlider(); add(slider); //this is for setting the value slider.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { JSlider src = (JSlider)e.getSource(); //if (src.getValueIsAdjusting()) return; //optional if (src.getValue() % 5 !=0) return; float value = src.getValue() / 100.0f; try { getVolumeControl().setValue(value); //you can put a click play code here to have nice feedback when moving slider } catch (Exception ex) { System.out.println(ex); } } }); //and this is for getting the value try { slider.setValue((int) (getVolumeControl().getValue()*100.0f)); } catch (Exception e) { System.out.println(e); } } } 

Hace poco estuve enfocando el mismo problema. Al final, decidí escribir un pequeño progtwig llamado VolumeChanger.exe en C ++ y llamarlo desde Java. Funciona genial. Puede llamar a un exe de Java con

Process process = new ProcessBuilder(vcpath,"-u").start();

wehre vcpath es la ruta a su archivo exe (podría ser real, por supuesto).

Si le interesa cómo utilicé esta herramienta, visíteme en muteFritz

Si está interesado en el código fuente completo, siéntase libre de enviarme un mensaje PM …

Aquí hay una solución que funciona ÚNICAMENTE en OS X (estoy ejecutando 10.10):

 import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; public class MasterVolume { public void setMasterVolume(float value) { String command = "set volume " + value; try { ProcessBuilder pb = new ProcessBuilder("osascript","-e",command); pb.directory(new File("/usr/bin")); System.out.println(command); StringBuffer output = new StringBuffer(); Process p = pb.start(); p.waitFor(); BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); String line; while ((line = reader.readLine())!= null) { output.append(line + "\n"); } System.out.println(output); } catch(Exception e) { System.out.println(e); } } } 

Llamarías al método así:

 MasterVolume.setMasterVolume(3.5f); 

Lo que establecería el volumen al 50% ya que el rango es de .1 a 7.0