2012-03-26 7 views
5

Anbringen Ich habe eine einfache Capture/Wiedergabe-Swing-Anwendung, die zu erkennen ist, wenn es keine geeigneten Mikrofon an den Computer und den Benutzer zu warnen, angebracht ist. Nach vielen Hantieren habe ich die einzige Lösung gefunden, die mir das neu angebracht oder entfernt Mikrofon zu erkennen erlaubt:Java Sound-Refresh-Linien-Liste nach einem Mikrofon

 com.sun.media.sound.JDK13Services.setCachingPeriod(0); 

    private static boolean isMicrophoneAvailable() { 
     try { 
      if (!AudioSystem.isLineSupported(Port.Info.MICROPHONE)) { 
       log.debug("NO MICROPHONE FOUND"); 
       return false; 
      } else { 
       log.debug("MICROPHONE FOUND"); 
       return true; 
      } 
     } catch (IllegalArgumentException e) { 
      log.debug("INCONSISTENT"); 
     } 
     return false; 
    } 

im Hintergrund-Thread wie folgt aufgerufen:

new Thread() { 
     public void run() { 
      while(!thisFrame.isClosed()){ 
       if(isMicrophoneAvailable() == true){ 
        //OK 
       }else{ 
        //WARN 
       } 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    }).start(); 

Das Problem ist, dass Obwohl das Gerät mit der beschriebenen Methode korrekt erkannt wird, wird die Liste der zugrunde liegenden Zeilen nicht aktualisiert. Das heißt, wenn das Programm gestartet wird, und das Gerät später angebracht, wird die folgende Ausnahme ausgelöst wird, wenn man versucht, den Ton zu notieren:

java.lang.IllegalArgumentException: No line matching interface TargetDataLine supporting format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, big-endian is supported. 

Gibt es eine Möglichkeit, die Linien Liste von Audiosystem aufgefrischt zu bekommen? Vielleicht etwas ähnliches wie die JDK13Services Workaround, die am Anfang verwendet wurde, um Caching zu vermeiden?

UPDATE: Code, der eine Ausnahme auslöst:

 AudioFormat format = formatControls.getDefaultFormat(); 
     DataLine.Info info = new DataLine.Info(TargetDataLine.class,format); 
     try { 
      line = (TargetDataLine) AudioSystem.getLine(info); 
      line.open(format, line.getBufferSize()); 
     } catch (LineUnavailableException ex) { 
      shutDown("No audio input device available. Please make sure that a microphone is attached to your computer"); 
      return; 
     } catch (Exception ex) { 
      log.error(ex.toString()); 
      shutDown(ex.toString()); 
      return; 
     } 

und die Ausnahme selbst:

java.lang.IllegalArgumentException: No line matching interface TargetDataLine supporting format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, big-endian is supported. 
+0

Interessante Frage, +1. Aber um das zu überprüfen, erkennen Sie die Zerbrechlichkeit der Verwendung einer Klasse in den com.sun-Paketen, richtig? Sogar in den JREs, in denen es existiert, könnte es in der nächsten Version entfernt/verschoben/umbenannt werden. –

+0

In der Tat, ich weiß, dass dies zumindest eine schlechte Praxis ist, aber es war wirklich mein letzter Ausweg. Ich nehme an, dass es sich um einen Java Sound Implementierungsfehler handelt. –

+0

Einer von vielen. JavaSound ist gut für die begrenzte Anzahl von Dingen, die es unterstützen soll, aber Sun hat es nie wirklich weiterentwickelt. –

Antwort

0

Posting den Code, der die Ausnahme auslöst helfen könnte.

Ich nehme an, Sie sind nur die Port.Info mit der Anwesenheit eines Mikrofons erkennen dann eine Datenleitung immer aufnehmen:

TargetDataLine dataLine = (TargetDataLine) AudioSystem.getLine(new DataLine.Info(TargetDataLine.class, audioFormat));      
dataLine.open(); 
dataLine.start();    
dataLine.read(b, offset, len); 

Beachten Sie, dass Sie immer noch eine ähnliche Ausnahme erhalten könnten, wenn das Mikrofon trennen Wenn das Mikrofon zwischen der Zeit, zu der Sie die Anwesenheit überprüfen, und der Zeit, zu der Sie versuchen, die Dataline aufzeichnen zu lassen, physisch getrennt wird, sollte das Anschließen des Mikrohoppons kein Problem darstellen.

+0

Es scheint, dass ich ziemlich genau dasselbe mache. Jedenfalls habe ich die Frage mit dem Code und der Ausnahme aktualisiert. –

+0

Stellen Sie sicher, dass die Leitung dieses Audioformat unterstützt. Um alle von der Zeile unterstützten Audioformate aufzulisten: AudioFormat adfs [] = ((DataLine.Info) dataLine.getLineInfo()). GetFormats(); für (AudioFormat adf: adfs) { System.out.println (adf.toString()); } – msam

+0

Ich verstehe nicht ganz Ihre Idee. line = (TargetDataLine) AudioSystem.getLine (Info); ist, wo die Ausnahme geworfen wird, so kann ich die Linie an erster Stelle nicht bekommen. Vielleicht war ich nicht klar genug: Das Mikrofon funktioniert gut, wenn es vor dem Start des Programms an den Computer angeschlossen ist. Die Trennung wird korrekt erkannt, die Schaltfläche "Record" ist deaktiviert. Beim Zurückstecken funktioniert es wieder. Das Problem tritt auf, wenn das Mikrofon vor dem Start nicht angeschlossen wurde. In diesem Fall sind seine Zeilen auch dann nicht funktionsfähig, wenn das Port.Info.MICROPHONE erkannt wird. –

0

den Original-Beitrag als Inspiration benutzt, kam ich mit dieser als Mittel bis zu erfassen, wenn ein Mikrofon verloren oder gewonnen. Es erkennt (auf meinem System), wenn ein USB-Mikrofon eingesteckt oder ausgesteckt ist. Ich rufe es aus einer Hintergrund-Thread-Schleife. Die ursprüngliche Methode funktionierte nicht für mich, da es ein eingebautes Mikrofon auf dem Laptop gibt, also musste ich das Hinzufügen des zweiten Mikrofons feststellen.

... 
//call this once somewhere to turn the caching period down for faster detection 
    try 
    { 
     //try to set the caching period, defaults to something like 55 seconds 
     com.sun.media.sound.JDK13Services.setCachingPeriod(5); 
    } 
    catch(Exception e) 
    { 
     System.err.println("exception attempting to call com.sun.media.sound.JDK13Services.setCachingPeriod->" + e); 
    } 
... 

private int lastNumMics = -1; 
private synchronized void micCheck() 
{ 
    Line.Info[] lineInfoArray = AudioSystem.getSourceLineInfo(Port.Info.MICROPHONE); 
    int numMics = lineInfoArray == null ? 0 : lineInfoArray.length; 
    if(lastNumMics > -1) 
    { 
     if(numMics < lastNumMics) 
     { 
      //MICROPHONE_LOST 
     } 
     else if(numMics > lastNumMics) 
     { 
      //MICROPHONE_GAINED 
     } 
    } 
    lastNumMics = numMics; 
}