1

Well, in order to start with the question, first I want to clarify that I am a newbie in Java programming, so, excuse me if I ask something unconsciously.

Recently I have been working on a project that consists mainly on managing SIP VoIP calls with the help of a library that does all the laborious business related to structuring and managing SIP protocol, in few words, just a kind of a basic softphone. This library also is in charge of capturing, sending and transmitting the audio to the respective sources and targets.

My problem is that I want to control the system volume using a slider within a graphical interface I created, but what I do not know is how to pass the FloatControl parameter to the slider due to the following circumstances:

  • If the slider needs to be created and shown from the time I start the program, What FloatControl parameter I should give to the JSlider object?, because the audio ports are open by the library methods or in other words, the instance of the JavaSoundManager object is created only when I make o receive a call. As far as I know, to get an audio line, it is needed to get a System Mixer, then LineInfos, later SourceLine and finally open this line, just at this point, I am able to create de FloatControl parameter of the SourceLine and pass it to the JSlider object, or, is there another way to do it?

  • Just for you to have a bigger picture of the situation, I am still not clear hundred percent how the library works in general, but checking its classes, I notice the JavaSoundManager class uses doPrivileged and Synchronized methods which I am not acquaintance with, these are used to open an close the audio lines when the calls are stablished.

In resume, these are my doubts:

  • How can I have access to a variable or parameter inside a library class if this is privated and does not have any getter o setter?

  • How can I pass the FloatControl parameter to the JSlider object in order to control de volume of the line created by the JavaSoundManager class?

  • And finally, is there a way to modify a class inside a library? Keeping in mind the library is a .jar file.

This is the code of the JavaSoundManager class:

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;
    }

}

Let me know if you need somthing else to be clearer, and thank you all in advance.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Jair R
  • 11
  • 3
  • FloatControl and stuff is a dinky-dinky thing - if you can get it to work. If you have a jar you just unjar it! If it is in your compamy then that should not be a problem - if you bought this from another company then that's your Problem. – gpasch Apr 08 '21 at 20:20
  • Thanks @gpasch , I think I should do some of this stuff (https://stackoverflow.com/questions/14069082/how-to-change-already-compiled-class-file-without-decompile), Right? – Jair R Apr 08 '21 at 21:14

0 Answers0