I am a student who has been trying to make FreeTTS working on its Ubuntu for one week. And finally I found the answer here : thank you so much hakvroot !
Your answer was perfect but you did not put your implementation and this took me quite one hour to understand what was going on in the JavaStreamingAudioPlayer class. To help the other people like me who are not used in "diving" in a completely unknown Java code (I am still a student), I will put here my code and hope it will help other people :) .
First, a more detailed explanation : around line 152, the JavaStreamingAudioPlayer opens a Line. However this operation can require some time so before using it, it wants to check it is opened. In the current implementation, the solution used is to create a LineListener listening to this line and then to sleep (using the wait() method of the threads).
The LineListener will "wake up" the main Thread using a notifyAll() and will do this only when it receives a LineEvent of type "OPEN" which will guarantee that the line has been opened.
However as explained by hakvroot here the problem is that the notification is never sent because of the specific behavior of the DataLine used by Ubuntu.
So I removed the synchronized, wait() and notifyAll() parts of the code but as hakvroot, then your JavaStreamingAudioPlayer might try to use your Line before it is opened : you need to wait for the confirmation with a new mechanism to stop the JavaStreamingAudioPlayer and to wake it up later, when the confirmation arrived.
So I used the Semaphore which havkroot used (see Javadoc for explanations on this lock system) initiated with 1 stack :
when the line is opened it acquires one stack (so 0 remains)
when it wants to use the line it tries to acquire another (so it is stopped)
when the listener gets the event we are looking for, it releases the semaphore
this frees the JavaStreamingAudioPlayer who can go for the next part
do not forget to release again the semaphore so it has again 1 stack for the next line to open
And here is my code :
Declare a Semaphore variable :
private Semaphore hackSemaphore;
Initiate it in the constructor :
hackSemaphore = new Semaphore(1);
Then the first part to replace (see hakvroot to see where to put it) :
line = (SourceDataLine) AudioSystem.getLine(info);
line.addLineListener(new JavaStreamLineListener());
line.open(format, AUDIO_BUFFER_SIZE);
hackSemaphore.acquire();
hackSemaphore.acquire();
opened = true;
hackSemaphore.release();
And the second part :
public void update(LineEvent event) {
if (event.getType().equals(LineEvent.Type.OPEN)) {
hackSemaphore.release();
}
}