2013-01-13 22 views

risposta

11

No, non può. Ecco la fonte adattata da una risposta a Adjusting master volume su coderanch. La fonte itera le linee disponibili, controlla se hanno un controllo del tipo giusto, e in caso affermativo, li mette in una GUI attaccato ad una 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; 
    } 
} 

Su questo Windows 7 macchina ottengo due controlli, sia da il "Java Sound Audio Engine". Né ha alcun effetto sul volume di sistema corrente.

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 
... 

Swap FloatControl.Type.MASTER_GAIN per FloatControl.Type.VOLUME per vedere .. nessun controllo.

+1

+1 bel esempio –

+0

Quindi quello che stai dicendo qui è che * non * è possibile. È un bug JDK? – rogerdpack

+2

@rogerdpack Il JSE non ha alcuna pretesa di controllare il volume del sistema quindi immagino, no. Ma sentiti libero di aprire una segnalazione di bug con Oracle e ottenere una risposta 'diretta dal produttore'. –

1

aggiungere la riga seguente subito dopo l'inizializzazione della linea. questo è necessario per aprire la linea.

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

Bello. Ma mentre questo mostra altre due righe 'FloatControl.Type.MASTER_GAIN' * qui, nessuna di esse ha alcun effetto sul volume di sistema. * Ancora 0 per 'FloatControl.Type.VOLUME' –

+0

controlla il seguente codice. –

0

prova questo non ti deluderà .... possiamo modificare l'esempio superiore di conseguenza.

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<mixers.length;i++){ 
     Mixer.Info mixerInfo = mixers[i]; 
     System.out.println("Mixer Name:"+mixerInfo.getName()); 
     Mixer mixer = AudioSystem.getMixer(mixerInfo); 
     Line.Info[] lineinfos = mixer.getTargetLineInfo(); 
     for(Line.Info lineinfo : lineinfos){ 
      System.out.println("line:" + lineinfo); 
      try { 
       Line line = mixer.getLine(lineinfo); 
       line.open(); 
       if(line.isControlSupported(FloatControl.Type.VOLUME)){ 
        FloatControl control = (FloatControl) line.getControl(FloatControl.Type.VOLUME); 
        System.out.println("Volume:"+control.getValue()); 
        JProgressBar pb = new JProgressBar(); 
        // if you want to set the value for the volume 0.5 will be 50% 
        // 0.0 being 0% 
        // 1.0 being 100% 
        control.setValue((float) 0.5); 
        int value = (int) (control.getValue()*100); 
        pb.setValue(value); 
        j.add(new JLabel(lineinfo.toString())); 
        j.add(pb); 
        j.pack(); 
       } 
      } catch (LineUnavailableException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 
public static void main(String[] args) { 
    new SoundMeter(); 
} 
} 
+0

questo codice renderà il volume del sistema al 50% che è governato dal codice: control.setValue ((float) 0.5); –

+2

Questo non sembra regolare il volume principale per me (vittoria 7) – rogerdpack

0

Sto usando il tipo di controllo VOLUME. Questo codice funziona per me per XP e WIN 7, ma non per OSX. Vedere il mio esempio:

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); 
     } 
    } 
} 
+2

Il codice sopra riportato non modifica il volume principale su Windows 7. – Torque

0

Recentemente ho focalizzato lo stesso problema. Alla fine ho deciso di scrivere un piccolo programma chiamato VolumeChanger.exe in C++ e chiamarlo da java. Funziona alla grande. È possibile chiamare un exe da Java con

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

wehre vcpath è il percorso del file exe (potrebbe essere realtive ovviamente).

Se siete interessati come ho usato questo strumento mi visita sul muteFritz

Se siete interessati nel codice sorgente di tutta la sentitevi liberi di PM me ...

0

Ecco una soluzione che funziona solo su OS X (sto facendo funzionare 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); 
     } 
    } 
} 

Si potrebbe chiamare il metodo come questo:

MasterVolume.setMasterVolume(3.5f); 

Quale impostare il volume al 50% poiché l'intervallo è da .1 a 7.0

+0

Dato che non usa Java Sound, non riesco a vedere come questa sia una risposta alla domanda chiesto (che era piuttosto specifico sull'uso di Java Sound). –

+0

Il codice cambia l'intero valore sonoro del sistema o per alcune app multimediali specifiche nei frame del lettore audio, ad esempio? – user390525