Conversation
|
Additional context: This PR is a recreation of an old merge request on PortAudio's previous Assembla-hosted repository. readers can find that Merge Request here... |
|
I have a PR that overlaps somewhat with this, so we should probably coordinate that (#473). |
Merge from upstream RC
|
I still need to review this properly, but two obvious things:
|
|
I notice this was tagged for inclusion in the next release of PortAudio. I'm currently working on ASIO functionality in my company's application and expect I will have an opportunity to revisit this Pull Request in the coming weeks. |
|
If I understand correctly, this PR would prevent PortAudio apps from using JackRouter (routing audio through JACK) on Windows, is this correct? If so, such change would affect SuperCollider Windows users, if they use JACK. I understand that one can't make everyone happy, but I think this would be an unfortunate regression. To clarify, the issue only occurs with older versions of JACK (pre-2021); it does not occur with the current version. EDIT: maybe blocking JackRouter could be enabled/disabled at compile time with a CMake option? That way those building PortAudio themselves could make the appropriate decision as they see fit. |
This PR blocks interfacing with JACK through its ASIO adaptor, "JackRouter", in order to avoid a problem that historically rendered the JACK ASIO adaptor nonfunctional for 64-bit apps. PortAudio also supports interfacing directly with the JACK API on Windows (ie, natively rather than through ASIO/JackRouter) which will understandably be the better approach to making Windows applications with Jack support. If the bug in JackRouter has been fixed, and that fix has propagated widely, the guard could be removed -- perhaps with a CMake option as you suggest. But be advised that the JackRouter problem causes applications to crash when initializing PortAudio on any system with the faulty ASIO driver; this usually means an app without this guard will be unopenable on affected systems, regardless of whether the user intends to interface with JACK. The nature of the crash also makes inspection of the debug trace rather difficult. |
|
I'm aware of the bug, and that it prevents the application from starting. Is building PortAudio with the JACK backend on Windows actually operational? I don't think that was the case in the past. Also, would the application be then linked against the Jack library? IMO it's quite important to allow the same binary to run both on systems that do and don't have JACK installed. If PA's JACK backend works on Windows, AND if the JACK library would be dynamically loaded, then indeed it is a viable workaround. As I wrote, the fixed JackRouter has been around for over two years now. I don't have the data on how well it is propagated. Since SuperCollider uses PortAudio on Windows, this has come up in SuperCollider's issue tracker, so it is likely that there are users who use PortAudio + Jack (with fixed JackRouter) on Windows. |
|
Pardon my two year (minus one day) delay.
Note that the latter change will break compatibility with any existing applications that use my branch (the message callback will not be used because the flag is not set). I considered checking for this in |
|
Phil and I discussed the struct version check. Phil raised the point that the check will fail if a newer version of the struct is passed even if it does not use new features. Something to think about. Given that I don't think we have a clear and stable global policy on struct version management I think the way that the version check is being handled in this PR is fine to merge as-is even if it's not perfect. |
I noticed this. I was copying the behavior of the previous code (the current library will fail any version other than 1). At your discretion I'd be happy to modify the validation check to facilitate forward compatibility. |
|
I went ahead and implemented the forward-compatibility as it seems unlikely to cause problems compared to the alternative. Implementors may need a fallback to deal with the possibility of an older portaudio DLL that rejects non-1 versions though. 0308b1e |
|
The CI is still finding some trailing white space. |
|
At Ross' suggestion I've split off #885 which fixes a bug in stream info validation. 885 should be merged before this PR; otherwise it won't be possible to use ASIO messages without also specifying a channel mapping. |
|
#885 is merged now |
|
|
||
| if (!theAsioStream) | ||
| { | ||
| /* Some ASIO drivers will fire messages during OpenStream. We ignore them. */ |
There was a problem hiding this comment.
This seems like incomplete code (same in the sampleRateChanged handler). Is there a rationale for dropping these messages?
To me, it seems that if we're going to pass through driver messages, we should pass through all of them. All it would take would be to stash the required callback data for use here even before the stream is fully created.
There was a problem hiding this comment.
It has been quite a while since I visited this code. My faint recollection is that some ASIO drivers were generating spurious ResetRequest messages while opening the stream, but I'd need to look into it.
|
According to Gemini, this cryptic command might trigger a CI test. $ bors r+ |
|
My command did not trigger a CI test. I think this PR needs to be rebased on master. |
|
Discussion invited: This PR has stalled because there is a policy decision to resolve about what to do with ASIO driver callbacks while the stream is being opened. I don't like the idea of suppressing messages in a low-level pass-through API -- thatshould be a decision for higher layers to make. The current PR code suppresses ASIO message callbacks "while the stream is being opened," in-fact only up to the sequence point in If I understand correctly, the purpose of suppressing callbacks is to avoid issues with the client getting stuck in a loop of infinite resets while the stream is being opened. On the other hand, if a legitimate reset happens after Baseline proposal: Don't suppress any callbacks. The client will have to do the work to ignore callbacks up to some sequence point after Pa_OpenStream has returned, either using a flag or a timer. This has effectively the same behavior as I described in the previous paragraph but gives the client full control over exactly when the stop-ignoring sequence point happens. Document that the notification callback can occur prior to Enhancement: add a flags parameter to the message notification callback. Define at least two flag fields: [1] NB assignment should be atomic/have release memory barrier if this mechanism is used |
|
I think the flags parameter would probably be the best way to do it. Or adding a couple new event codes corresponding to the transitions between those stages of initialization. Apologies for leaving this untouched for so long; I was in poor health throughout 2023-2024. |
|
@EvanBalster sorry to hear about your health issues. Phil and I are discussing moving this PR off the 19.8 release milestone. I think there's still time to ship it if you (or someone else) would like to work on it now, but there's no pressure, we can just take care of it later. |
|
Those health issues (post-COVID syndrome) made an unexpected comeback so I can't commit to anything short term. |
|
@EvanBalster no problems. I wish you the best for your recovery. Unless someone else is interested in working on this PR we will move it to v19.9 |
This PR addresses PortAudio's bad habit of ignoring certain highly actionable messages from ASIO drivers by providing a callback mechanism to the application. Applications may receive the following events:
In particular, Reset Request is commonly used to notify the ASIO client when the stream should be reset in order to put configuration changes into effect or resume the interrupted flow of audio. Implementing automatic reset allows the user to interactively re-configure the ASIO stream by way of a driver-specific UI without superfluous manual steps in the client application.
The patch works by extending the ASIO configuration structure and, therefore, does not change PortAudio's ABI. I have been using this functionality in production for over four years in an application with an integrated crash forensics system and haven't identified any faults.