RG works very well with JACK and is very stable, in my case at least. There is one feature which is expected to be there, but is missing and likely a notification bug. I will use Ardour as the other JACK enabled application, but this probably applies to any such application. Note, it's not the latest version, but I will assume the below still occurs because I'm using RG master [16c5bf], and I think the problem is there.
Steps to reproduce:
Why isn't RG responding? However, even though it did not respond, if you hit play in Ardour, RG jumps into action at the correct location i.e. responds to that notification. But with xruns always lurking, I would prefer RG to be down at the start line ready to go. Maybe it only responds to the play/stop part or maybe I missed a configuration setting in RG? But I saw nothing obvious in preferences. So, bug?
I would go after this bug (assuming it is one) first, because I think it may be the cause of a behavior which appears to be some confusion between the two applications:
You'll have to try it, but the playhead will not move when toggled to play/stop i.e. Ardour appears to be not responding. After a moment or two, the playhead also seems to jump back and forth as though moving to the position RG is rolling to and back to the location chosen by the user. I usually head back to RG and hit stop there, although that does not always get a stable state by itself...then back to Ardour and hit the space bar there (meaning stop, even though it's not moving). Sooner or later strange behavior does stop doing whatever...but it's obviously confusion concerning JACK's transport instructions. My guess is maybe the original bug above?
Anyway, I would guess that changes in this area are tricky, so note that both issues can be avoided and worked around, and are preferable to an unstable RG-JACK relationship, after the fact :-) If you need more info let me know.
I was in that area recently and our implementation of JACK transport seemed limited. Shouldn't be too hard to finish it up and add better support for receiving and responding to position information. We fully support the user jumping to any spot in the composition. We should be able to do the same for JACK.
I am able to reproduce this issue with qjackctl. It seems like rg only pays attention to position when transitioning to playback.
I should have mentioned that one likely side-effect of fixing the current bug (or missing feature), is that looping will work in RG via JACK, assuming it's not based on start/stop alone. Currently, both RG and Ardour (as a JACK enabled example) both loop perfectly when JACK is not involved. It also works with JACK if looping is started from RG, but not if started from Ardour, where nothing happens at all. I may have missed some preference in Ardour, since I would have thought it would start the loop, and then RG would fail to loop back due to ignoring the positional information. However, it might also be related to the current bug.
In any case, once the bug is fixed, then positional information at the loop start and end could be sent via JACK, so testing will be needed to make sure no other RG bugs are revealed in that scenario.
Found a very serious bug in the code which should help with some/most of this. Hoping to push the change tonight. It will be interesting to see if it fixes the looping issue.
Just pushed a fix for this as [dc2062]. Please test latest git.
Moving around in an external app (e.g. Ardour) while rolling should work now. Moving around while stopped still doesn't work. That's a more difficult problem to fix, unfortunately.
Related
Commit: [dc2062]
The scenarios mentioned in the last post work exactly as stated. Placing the cursor at some location while Ardour is playing is now picked up by RG. You fixed this part in short order too, which is amazing. The only thing now is for that to happen when Ardour is not playing. And as far as I can tell at this point, that is all the needed functionality I can think of. But if you really want to hear amazing read on.
First, and noteworthy, is to remember that from RG, play/stop was picked up by Ardour just fine even before this fix. In addition, even looping also worked when the loop is in RG and started from RG i.e. Ardour's playhead moved with the RG loop, because it was picking up the play positions from JACK. There was never a problem that way around.
However, as mentioned above, when I hit loop (not play) in Ardour nothing happens and I thought it might be a missed preference setting or related to the current bug. But it is neither. It doesn't even feel like the dynamic vs static issue because it's not a case of RG not following...absolutely nothing happens in Ardour at all.
What I failed to notice before is that RG could never have been involved in the failed loop start from Ardour because nothing appeared in JACK for the Ardour loop scenario. Suspicions start to fall on Ardour alone? Even though Ardour's problems are not RG's problems, I thought I would check further.
I installed Ardour from the Debian repository (bookworm) on a different box, along with RG master. Still nothing for looping when JACK is enabled in Adour. What's going on? Well, I did a quick simple search involving "Ardour", "JACK" and "looping" and here are the links which came back, and I simply don't understand the "discourse":
https://discourse.ardour.org/t/no-looping-playback-with-jack/86800/6
https://discourse.ardour.org/t/loop-with-jack-transport/111684
It looks to me like Ardour simply turned off the functionality when JACK is enabled! And as per those links above, they appear to be blaming the need to do that on JACK audio?
What amazes me is that looping appears to be working fine in RG with JACK, and on top of that even with Ardour itself as a client application? Sure they mention something about "reliably" in one of the links, but I've had RG using the JACK transport for years. Sure I wasn't using looping across to Ardour, but I didn't see any issues with RG looping even though it was in communication with JACK all along. And now with the new RG master, I have tried looping from RG while watching Ardour and still see no issues, reliability or otherwise? It just works.
Still mystified, I took the next logical step. If they intentionally turned off looping simply because I enabled JACK in Ardour, that does not stop me setting up the loop in RG, ignoring hitting their loop button and just hitting play in Ardour. RG would obviously jump to its loop start because it received a play command and that always worked. And sure enough, looping now works from Ardour but by simply hitting play, not loop. And as far as I can tell it's works just fine, just like when I hit play in RG :-)
Anyway, with Ardour's looping turned off by design, I don't have to worry about what happens if loop ranges exist in both applications...who wants the headache from competing loops!
I'll continue using the new code, and if any regression issues show up, I'll know soon enough...but I doubt there will be any. Anyway, with the above information, you can adapt any test scenarios you currently have.
Since I only needed another JACK-enabled application with looping for the test, I installed MusE...and no, I have no idea how to use it :-) Fortunately, the looping button was in plain sight, and what looked like a loop range (same color) was right there. Better still, just hitting play indicated that JACK transport was all ready to go since RG's transport started moving too. I didn't bother adding segments or any other setup to MusE for this test, but I'd advise matching tempos to prevent visual confusion of the transport's location.
Without the [dc2062] fix
Non looping: This is manually moving the cursor in another JACK-enable application either during its play or while it is stopped
Looping:
The cursor is already at the start of the loop range on lauching MusE, so I selected the loop button in MusE and play in MusE.
RG looped back at the end of the MusE range, but MusE itself did not. It just continued...until what looked like RG hitting the range end a second time and then MusE did loop back. Strangely enough RG didn't loopback this time around...it just continued. From that point, I believe we were already in what I called the transport confusion area mentioned in the last post just like for Ardour.
With the [dc2062] fix
Non looping:
Looping:
Conclusion:
Finally, and this is only an opinion: It seems perfectly fine for RG (like MusE) to at least ensure that they are sending the required transport position notifications for JACK regardless of whether looping is active or not. If there really is a problem with looping and JACK, which is questionable at this point, it may be addressed in JACK in the future assuming that it has not already been addressed. Then no changes (like a whole new version) would be required in RG and the fix would be immediately available to all previous versions.
So, if the static cursor change is fixable, and there is no urgency, then RG is good to go with respect to the basics of JACK transport.
Related
Commit: [dc2062]
I admit this is going to sound strange, and I hope I haven't missed something obvious. But here is a subtle bug appropriate for this thread since it involves JACK. Nothing to do with looping though...just simple play. It does somehow involve tempo changes, but has nothing to do with recent changes to the tempo editor on master. I found the problem even in the released stable. I'm surprised I didn't notice it before, but it's tricky to reproduce and does involve using another JACK-enabled application to see it. Either MusE or Ardour will do. In fact, since it's not about looping, qjackctl was mentioned in this thread, so it should probably work too. Just play silence in whatever application you decide to use.
At first, it looks like a playback pointer position error. But if the segment is played from its start, using play in the other JACK client, then any notes in the segment play normally at their correct locations. I thought it might be because the default length of a note can reach the end of the segment and starting there becomes a problem in this scenario...but the notes aren't past end? And if I shorten the note enough manually using the Matrix Editor, then the note does not play. But how the tempo is involved or triggered this scenario will be revealed once reproduced.
See if you can reproduce it, while in this area, since it probably needs to be taken into account.
I can't reproduce this with qjackctl.
Rg does some work figuring out which notes are in progress at start time. There might be a bug in that someplace, or the time from JACK is being misinterpreted. The computations are pretty complicated. Some questions:
There is one very serious problem in rg's JACK support that really needs to be fixed before we dig into anything else. Right now rg sends redundant JACK events out for transport changes that are caused by JACK. E.g. if JACK says "play", rg sends out another "play". This has made it impossible to fix the "following when stopped" problem. It might be contributing to other problems as well.
Yes, I agree that you should tackle one problem at a time...the one you mentioned. For all we know, while fixing that, it might result in killing two bugs with one keystroke.
I will detail below far simpler steps to reproduce the bug, since I know the exact scenario now. In addition, I can reproduce it with qjackctl. It will work with any JACK enabled application which starts play, but only under a specific scenario in RG. Unfortunately, I didn't see any evidence, or differences, in the JACK logs. The following is for when you are ready.
In answer to the specific questions:
Just to be precise, here are the detailed steps to reproduce the bug, but they are just what I happened to use for this test:
Scenario where problem does not occur
Now cause the problem based on the above
To prove it has nothing to do with the segment end itself
On the surface, the problem seems simple and involves:
Just for completeness, here are the JACK logs, which claim the same starting frame of 1603636 in both cases. So, it doesn't look like a positional error caused by JACK or its clients.
Start pressed in RG
Start pressed in JACK client (in this case Ardour)
So starting play at the end of a note is what this boils down to. I definitely was able to reproduce that when I was testing. I just wasn't sure how big the note was from the original description. If you can post a simple .rg file with the single problematic note, that would be a big help.
This is probably due to the fact that JACK's transport position is in seconds and rg keeps things in PPQ. The conversion is not simple and depends on past tempos. I can definitely see a simple round off error leading to this. At a tempo of 120 , things work out pretty well since everything is easily divisible. But at other tempos, the math is going to be problematic and round-off errors are guaranteed. What's likely happening is JACK provides a time and rg converts it to a tick which is just prior to the start of the bar JACK is asking for. That causes rg to send out the note since it thinks we are in the middle of it and it doesn't want to pretend it wasn't there.
Anyway, just a theory. We should probably figure out whether this is what's going on and see if it makes sense to do anything about it. With MIDI, starting playback in the middle of the composition is always going to be troublesome. Unless nothing is going on near the starting point.
I believe the theory is correct. In an earlier post, I mentioned that all of this "does somehow involve tempo changes". And sure enough your information about the PPQ points straight to that too. In fact, it's not worth uploading the rg-file since there is nothing special about it...when I change its tempo to 120 BPM, even the same MIDI note wasn't sent out. So, just for the record I'll update my last post here:
On the surface, the problem seems simple and involves:
It seems to be boiling down to time resolution issues (whether ticks or milliseconds) and can't be "programmed away" in all cases. Handling rounding errors may help to some extent. I've always been aware the problem exists...theory is theory...I just didn't expect to actually hear it :-)
It's still possible that some calculation has been missed though, but then that should be a different bug? I can start checking the calculations. But while doing a rough check, I discovered another simpler bug. When changing the tempo, the transport window location is not updated. This is true whether it's open during that change or opened after the change, with the latter being a bit more worrying. However, if you hit PgUp/PgDown i.e. return to the same location, then the transport at least has a different location indicating it got the message.
Obviously with the problem I mentioned above, I don't know the consequences of not notifying all observers of the tempo change. Or whether there is a price for hitting play in that case,, but one has to be concerned. Besides, if JACK sends out a tempo change, who knows what the effect might be.
At present, it's still seems a different bug, so:
In the meantime, I think have enough information to check the location calculations which led to that note sounding in my particular case.
My last post is still valid, but I changed my mind about the test rg file not being needed. The original file was just some composition with lots of segments to confuse the issue. So I went back to set up a clean test with just one segment and I noticed something odd. It doesn't change the results of the test, but is curious. In my steps to reproduce, I clearly stated that when the floor tom was placed using the drawing tool, it defaulted to 3/16 long. I had to stretch it to the end of the bar myself. That was what it was in the old session, and I generally never bother to edit percussion note lengths. I just accept the the diamond icon which appears in the drawing tool.
So, why when I create any percussion note now, it appears to fill the entire measure wherever I place it? Obviously, that affects this test...well in a positive way since the bug shows up regardless... a note is guaranteed to end at the end of the bar. And if I place another note ahead of it, the first shortens enough to allow that, but then both fill all of the measure?
I have plenty of sessions created previously where the percussion notes are separated by silence. I never followed notes lengths in the past, so I don't know when this occurred, but it even happens when placing percussion notes in the stable release and that is the earliest I have now. This doesn't appear to cause any harm, and I never knew why or how a particular default length was decided previously. Was this an intentional change, and if so why?
In any case, the attached rg-file has the setup you need. All you have to do is ensure your RG has "Use JACK transport", and you are listening for MIDI notes when play is hit in a JACK-enabled client. RG will send the one tom note out on instrument 12, which has been changed to a percussion track for the test, even though the playback cursor has been positioned at bar 11 and the note is in bar 10.
Another long post, but I think it's conclusive. I checked, not the calculations, but the numbers involved in the JACK transport positions. The following can be tested using the uploaded rg-file in the last post. It all takes place when the cursor is placed at bar 11.
At bar 11
The RG transport window indicates 00:00:36 3636 and when double-clicked shows:
RG logs:
JACK logs:
Jack: transport stopped ==> stopped (locating) frame = 1603636Ardour's time clocks:
Everything matches up.
On play in RG, where no MIDI note is sent
RG logs:
JACK logs:
On play in Ardour, MIDI note is sent
RG logs:
JACK logs:
It would be helpful if RG indicated something about the JACK position in the JACK client case, but there is nothing about the JACK transport frames or positions in its logs. It only shows them in a play in RG. I think that can be fixed for future debugging?
In any case, the JACK logs are identical to when play was initiated in RG and MIDI was sent. On stop, the frames and positions then show up in both RG and JACK logs and have identical positions, but immaterial to the problem at hand, so I have not included them here.
The decision to send or not send the MIDI is down to RG, which treats its internal play differently from that when initiated by JACK. It's still possible for the problem to be caused by the conversion from JACK's 1603636 to PPQ. The RG transport window does round 00:00:36 3636 to 36s 364ms, but I don't think that is the problem.
Even when played in RG, the note is sounded on matter how small an amount prior to the end of bar. In RG the resolution of that move can be as small as 1 ms using the transport window i.e. 36s 363ms. And then RG does play the note in that case. But the point to note is that in all of the tests, the note itself actually ends at bar 11 bar i.e. where the playback pointer has always been played from...yet RG does not send that note in that particular case when it initiates the play. I think that is an inconsistency, and yet it is the correct and expected thing to do. Whatever logic determined that, should be applied to playback initiated via JACK and then this issue simply disappears, and the behavior is consistent in both cases and no note is sent for the silence after bar 11.
If you haven't noticed already, there is more bad news worth bringing to your attention now rather than later. You can reproduce this in the same rg-file uploaded earlier.
If you actually place another tom note at the start of bar 11, and hit play in another JACK enabled client at bar 11, both the note in bar 10 and the one in bar 11 are sent out as MIDI at the same time and can be clearly heard as a double tom hit. Non-percussion instruments suffer the same problem, but depending on their attack and sustain the bar 10 note, a double note may be harder to hear. However, I believe an unwanted higher than normal audio spike does appear. Fortunately, during a normal transport roll over the two notes, I don't think there is an issue regardless of which application play is initiated from, which is why this problem may not have been noticed before.
Just pushed [4c4d9d] which fixes transport time not updating on the transport dialog after adding a tempo change (and several other use cases). Please test latest git.
Related
Commit: [4c4d9d]
Summary of Remaining Issues
Remember the annoying click when repeating with a synth plugin - it was mentioned in the lv2 feature request. That had something to do with jack transport too.
To me it seems that the correct way to do things is:
if jack transport is configured false:
Everything pretty much as now
if jack transport is configured true:
All the rosegarden menu actions (stat, stop reposition) do nothing with the sequencer but just call the appropriate jack transport functions.
Start, stop, reposition are all triggered purely from the jack status obtained from
jack_transport_queryThat should eliminate any feedback loop.
The sync callback is only necessary if rosegarden requires time to setup the start - this may be unnecessary.
The transport window location is now correctly updated whenever a tempo change is made prior to the playback cursor, regardless of whether it is open or not. I also tried inserting and deleting multiple tempos per composition prior to the playback pointer. So, that is fixed now.
Unfortunately, the transport window update fix broke notation and matrix note previews. I have removed the fix in [563583]. I've opened a new bug report to track this: [#1723].
Related
Bugs:
#1723Commit: [563583]
Before we do anything further, I think we need to take a look at how Ardour handles JACK transport sync. In particular, we need to pay attention to how Ardour avoids a feedback loop. How does it handle the difference between JACK sync on and JACK sync off? With JACK sync on, does it rely on JACK transport messages even when dealing with a local transport change? How does it handle incoming stop/sync updates? Is there a concept of leader/follower?
Once that review is complete, we need to take lessons learned and apply them to rg.
I'm looking at this as more of a cleanup effort. Our JACK transport support is good enough for real work. It's just lacking in some details. I'm guessing that the amount of work required to get it fully functional is going to be pretty significant. Some non-trivial redesign will be required.
I had a look at ardour and qtractor. Always difficult looking at other people's code (Difficult enough looking at my own code). I believe they both have the same principle:
The jack transport changes cause the sequencer changes.
I think this is the correct approach. I think the "add on" approach that Rosegarden uses at the moment is a fundamentally flawed design.
So - a suggestion:
Add a new class (TransportControl ?) with play, stop, jumpTo etc. commands
SequenceManagerandRosegardenSequencerJackDriverTransportRequestcode can be removed.Ideas? Improvements? Discussion?
This sounds like a solid plan. Splitting this off into a new class should help get the size of JackDriver down.
TransportControlis fine for a working name. We can rename later as it becomes more clear what the new class needs to do. The other name that comes to my mind isJackTransport. Not sure if that is too narrow, though. Probably make it a singleton likeRosegardenSequenceror just a namespace likeLV2PluginDatabase.Also, I would keep the
jackSyncCallback()approach. While rg might not really need time to get started, I don't think there is any harm in pretending like we do. One day we might need some extra time, and having the support in there already will be helpful. What do Ardour and qtractor do about this? Do they provide a sync callback (jack_set_sync_callback())?Feels like this will be a significant improvement in terms of design, and of course, doing JACK transport the way everyone else does it. I would say go for it. Don't worry about keeping any of the old code. Untangle the mess and do what needs to be done. I'll follow closely with review and testing as it moves along. We'll get @musewhirl testing on your branch as well before we merge into master.