JAVA - Управление громкостью системы с помощью ползунка

Ну а чтобы начать с вопроса, сначала хочу уточнить, что я новичок в программировании на Java, так что извините, если что-то неосознанно спрашиваю.

Недавно я работал над проектом, который состоит в основном в управлении звонками SIP VoIP с помощью библиотеки, которая делает все кропотливые дела, связанные со структурированием и управлением протоколом SIP, в двух словах, просто своего рода базовый софтфон. Эта библиотека также отвечает за захват, отправку и передачу звука на соответствующие источники и цели.

Моя проблема в том, что я хочу управлять громкостью системы с помощью ползунка в графическом интерфейсе, который я создал, но я не знаю, как передать параметр FloatControl ползунку из-за следующих обстоятельств:

  • Если слайдер нужно создать и показать с момента запуска программы, какой параметр FloatControl я должен передать объекту JSlider?, потому что аудиопорты открыты методами библиотеки или, другими словами, экземпляром объекта JavaSoundManager создается только тогда, когда я делаю или принимаю вызов. Насколько я знаю, чтобы получить звуковую линию, необходимо получить системный микшер, затем LineInfos, затем SourceLine и, наконец, открыть эту строку, как раз в этот момент я могу создать параметр de FloatControl для SourceLine и передать это к объекту JSlider или есть другой способ сделать это?

  • Просто для того, чтобы вы имели более полную картину ситуации, я до сих пор не понимаю на сто процентов, как работает библиотека в целом, но, проверяя ее классы, я замечаю, что класс JavaSoundManager использует методы doPrivileged и Synchronized, с которыми я не знаком, это используется для открытия и закрытия аудиолиний, когда вызовы стабильны.

В резюме, это мои сомнения:

  • Как я могу получить доступ к переменной или параметру внутри библиотечного класса, если он является закрытым и не имеет никакого геттера или сеттера?

  • Как я могу передать параметр FloatControl объекту JSlider, чтобы контролировать громкость строки, созданной классом JavaSoundManager?

  • И, наконец, есть ли способ изменить класс внутри библиотеки? Имея в виду, что библиотека представляет собой файл .jar.

Это код класса JavaSoundManager:

public class JavaSoundManager {

    private AudioFormat audioFormat;
    private TargetDataLine targetDataLine;
    private SourceDataLine sourceDataLine;
    private Object sourceDataLineMute;
    private DataLine.Info targetInfo;
    private DataLine.Info sourceInfo;
    private FileOutputStream microphoneOutput;
    private FileOutputStream speakerInput;
    private boolean mediaDebug;
    private Logger logger;

    public JavaSoundManager(boolean mediaDebug, Logger logger) 
        extends AbstractManager{
        this.mediaDebug = mediaDebug;
        this.logger = logger;

        audioFormat = new AudioFormat(8000, 16, 1, true, false);
        targetInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
        sourceInfo = new DataLine.Info(SourceDataLine.class, audioFormat);
        sourceDataLineMute = new Object();
    }

    @Override
    public void init() {
        logger.debug("openAndStartLines");
        if (mediaDebug) {
            SimpleDateFormat simpleDateFormat
                    = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
            String date = simpleDateFormat.format(new Date());
            StringBuffer buf = new StringBuffer();
            buf.append(MEDIA_DIR).append(File.separator);
            buf.append(date).append("_");
            buf.append(audioFormat.getEncoding()).append("_");
            buf.append(audioFormat.getSampleRate()).append("_");
            buf.append(audioFormat.getSampleSizeInBits()).append("_");
            buf.append(audioFormat.getChannels()).append("_");
            buf.append(audioFormat.isBigEndian() ? "be" : "le");
            try {
                microphoneOutput = new FileOutputStream(buf.toString()
                        + "-microphone-output");
                speakerInput = new FileOutputStream(buf.toString()
                        + "-speaker-input");
            } catch (FileNotFoundException e) {
                logger.error("cannot-create-file", e);
                return;
            }
        }

        AccessController.doPrivileged(
                new PrivilegedAction<Void>() {

            @Override
            public Void run() {
                try {
                    targetDataLine = (TargetDataLine) AudioSystem.getLine(targetInfo);
                    targetDataLine.open(audioFormat);
                } catch (LineUnavailableException e) {
                    logger.error("target-line-unavailable", e);
                    return null;
                } catch (SecurityException e) {
                    logger.error("security-exception", e);
                    return null;
                } catch (Throwable t) {
                    logger.error("throwable " + t.getMessage());
                    return null;
                }
                targetDataLine.start();
                synchronized (sourceDataLineMute) {
                    try {
                        sourceDataLine = (SourceDataLine) AudioSystem.getLine(sourceInfo);
                        sourceDataLine.open(audioFormat);
                    } catch (LineUnavailableException e) {
                        logger.error("source line unavailable", e);
                        return null;
                    }
                    sourceDataLine.start();
                }
                return null;
            }
        });

    }

    @Override
    public synchronized void close() {
        logger.debug("closeLines");
        if (microphoneOutput != null) {
            try {
                microphoneOutput.close();
            } catch (IOException e) {
                logger.error("cannot-close-file", e);
            }
            microphoneOutput = null;
        }
        if (speakerInput != null) {
            try {
                speakerInput.close();
            } catch (IOException e) {
                logger.error("cannot-close-file", e);
            }
            speakerInput = null;
        }

        AccessController.doPrivileged(new PrivilegedAction<Void>() {

            @Override
            public Void run() {
                if (targetDataLine != null) {
                    targetDataLine.close();
                    targetDataLine = null;
                }
                synchronized (sourceDataLineMute) {
                    if (sourceDataLine != null) {
                        sourceDataLine.drain();
                        sourceDataLine.stop();
                        sourceDataLine.close();
                        sourceDataLine = null;
                    }
                }
                return null;
            }
        });
    }

    @Override
    public synchronized byte[] readData() {
        if (targetDataLine == null) {
            return null;
        }
        int ready = targetDataLine.available();
        while (ready == 0) {
            try {
                Thread.sleep(2);
                ready = targetDataLine.available();
            } catch (InterruptedException e) {
                return null;
            }
        }
        if (ready <= 0) {
            return null;
        }
        byte[] buffer = new byte[ready];
        targetDataLine.read(buffer, 0, buffer.length);
        if (mediaDebug) {
            try {
                microphoneOutput.write(buffer, 0, buffer.length);
            } catch (IOException e) {
                logger.error("cannot-write-to-file", e);
                return null;
            }
        }
        return buffer;
    }

    @Override
    public int writeData(byte[] buffer, int offset, int length) {
        int numberOfBytesWritten;
        synchronized (sourceDataLineMute) {
            if (sourceDataLine == null) {
                return 0;
            }
            numberOfBytesWritten = sourceDataLine.write(buffer, offset, length);
        }
        if (mediaDebug) {
            try {
                speakerInput.write(buffer, offset, numberOfBytesWritten);
            } catch (IOException e) {
                logger.error("cannot-write-to-file", e);
                return -1;
            }
        }
        return numberOfBytesWritten;
    }

}

Дайте мне знать, если вам нужно что-то еще, чтобы быть более ясным, и спасибо всем заранее.


person Jair R    schedule 08.04.2021    source источник
comment
FloatControl и прочее — это забавная вещь, если вы можете заставить ее работать. Если у вас есть банка, вы просто открываете ее! Если это в вашей компании, то это не должно быть проблемой - если вы купили это у другой компании, то это ваша проблема.   -  person gpasch    schedule 08.04.2021
comment
Спасибо @gpasch, я думаю, мне следует сделать кое-что из этого (заголовок stackoverflow.com/questions/14069082/), верно?   -  person Jair R    schedule 09.04.2021