When QAudioDecoder is given the pathname of an audio file to read, it appears to open it and leave it open until the pathname is changed, rather than open it only while actually reading it. This prevents other programs from modifying or replacing the file, even when the Qt app is finished with it. The "solution" is to set a null pathname after processing the file, but this also means setting the real pathname just before calling start(). This doesn't work because the file format is determined by a separate thread, so the call to start() locks in the current (initially invalid) format, preventing the other thread from changing the format when it discovers what it actually is.
I tried moving the call to start() into a handler for the formatChanged signal, but that only gets called if the format actually changes. To ensure a change, I tried setting a default-constructed (invalid) QAudioFormat after setting the null pathname, but it seems to ignore that if there is no real file to read the format from.
It seems to me that the file should only be opened when needed, once briefly when the pathname is set, to determine its file format, and then between the calls to start() and stop(), so that other programs could manipulate the file. To deal with the timing race, start() should wait until the other thread has determined the file format before locking it in. Furthermore, if the previous audioFormat was an invalid QAudioFormat, it should restore that in stop(), so that the next use of the decoder will auto-discover the format, instead of re-using the format of the last file.
If there's a workaround I haven't thought of, I'd like to hear it.