Я столкнулся со странным поведением при запросе имен устройств захвата звука в потоке JavaFX по сравнению с «простым» потоком Java.
Обычно я, вероятно, не заметил бы, кроме есть некоторые приложения, не относящиеся к JavaFX, которые используют общий пул конфигурации с приложением JavaFX, и это вызвало некоторые проблемы при программной настройке используемого аудиоустройства захвата.
В двух словах, тот же самый запрос main в простой Поток 1045 * возвращает имена устройств захвата, усеченные до 31 символа, тогда как в потоке JavaFX имена устройств захвата являются «полными».
Например, усеченные результаты ...
Primary Sound Capture Driver
Microphone (HD Pro Webcam C910)
Microphone (Realtek(R) Audio)
Headset (Bose QuietComfort 35 H
Headset Microphone (Oculus Virt
. ..vs 'полные' результаты:
Primary Sound Capture Driver
Microphone (HD Pro Webcam C910)
Microphone (Realtek(R) Audio)
Headset (Bose QuietComfort 35 Hands-Free)
Headset Microphone (Oculus Virtual Audio Device)
Минимальный код приложения JavaFX ниже демонстрирует проблему, и в моем тестировании это происходит как в 32-битной, так и в 64-битной версиях Java8 JDK на Windows 10 . Я не тестировал платформы, отличные от Windows, поэтому я не уверен, происходит ли такое поведение за пределами этой среды.
Метод showCaptureDeviceNames()
делает то Электронный запрос и распечатка названий устройств. При вызове из метода main
отображаются усеченные имена устройств. Если закомментировано из main
и вызвано нажатием кнопки в потоке JavaFX, отображаются «полные» имена устройств.
Интересно, что при вызове в main
сначала , а затем в потоке JavaFX показаны усеченные имена, указывающие на то, что происходит какое-то кеширование (которое, к счастью, обеспечивает обходной путь для моей проблемы). Простого вызова AudioSystem.getMixerInfo();
самого по себе достаточно, чтобы вызвать эффект «кэширования»
Кроме того, это происходит только для устройств захвата ; если TargetDataLine.class
переключен на SourceDataLine.class
для фильтрации устройств воспроизведения , имя устройства всегда будет «полным».
Может ли кто-нибудь подсказать, почему это может происходить ?
Мой текущий обходной путь - убедиться, что приложение JavaFX запрашивает все аудиоустройства до , поток JavaFX запускается с вызова AudioSystem.getMixerInfo();
в main(...)
. Это работает, но ... в качестве "исправления" это больше похоже на ошибку, которая возникает сама по себе без видимой причины (хотя адекватные комментарии помогут будущим разработчикам, которые столкнутся с этим).
Я бы люблю, когда кто-то говорит мне, что я делаю что-то не так, и есть способ получше.
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Line;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.Mixer.Info;
import javax.sound.sampled.TargetDataLine;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class CaptureDeviceListTest extends Application
{
@Override
public void start( Stage primaryStage )
throws Exception
{
primaryStage.setTitle( "Test Capture Device Queries" );
Button btn = new Button( "Get capture device names" );
btn.setOnAction( event -> showCaptureDeviceNames() );
StackPane root = new StackPane();
root.getChildren().add( btn );
primaryStage.setScene( new Scene( root, 200, 200 ) );
primaryStage.show();
}
private static void showCaptureDeviceNames()
{
// filter for capture devices - change to `SourceTargetData.class` for playback devices
Line.Info captureLine = new Line.Info( TargetDataLine.class );
for( Info mixerInfo : AudioSystem.getMixerInfo() )
{
Mixer mixer = AudioSystem.getMixer( mixerInfo );
if( mixer.isLineSupported( captureLine ) )
System.out.println( mixerInfo.getName() );
}
}
public static void main( String[] args )
{
// COMMENT / UNCOMMENT THE NEXT LINE
// showCaptureDeviceNames();
launch( args );
}
}