Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Knobs are erratic on macOS (and other systems) #5194

Closed
tresf opened this issue Sep 16, 2019 · 40 comments
Closed

Knobs are erratic on macOS (and other systems) #5194

tresf opened this issue Sep 16, 2019 · 40 comments
Assignees
Milestone

Comments

@tresf
Copy link
Member

tresf commented Sep 16, 2019

As the title suggests, all knobs behave "wonky" on macOS.

Originally posted on Reddit, the OP (u/Coelacanth2) was kind enough to share a screen record. Holding Shift helps, but they're still way off.
A9tKsji

I can reproduce this on my machine, macOS Mojave 10.14.6 using the latest tip of stable-1.2 and all dependencies updated. Note, the change in behavior from older versions may be Qt5 related.

@tresf tresf added the bug label Sep 16, 2019
@tresf tresf added this to the 1.2.1 milestone Sep 16, 2019
@michaelgregorius
Copy link
Contributor

Is this about the behavior that if you move the mouse faster then the values will increase in greater steps? Because if it is then it's not only a problem on macOS.

@tresf
Copy link
Member Author

tresf commented Sep 23, 2019

Is this about the behavior that if you move the mouse faster then the values will increase in greater steps? Because if it is then it's not only a problem on macOS.

@michaelgregorius it may be the same underlying issue, but on macOS, it's so sensitive that it makes the knobs practically unusable, similar to trying to draw 1 pixel at a time with Gimp zoomed all the way out gives almost no room for control. Worse, it continues goes in the wrong direction when switching.

@michaelgregorius
Copy link
Contributor

Thanks for the clarification @tresf. I notice two things in the screen recording which might indicate differences in Qt's implementation on macOS compared to for example Linux:

  1. The mouse cursor stays visible on macOS when changing the values. According to the implementation it should be hidden as can be seen in Knob::mousePressEvent where the method QApplication::setOverrideCursor( Qt::BlankCursor ) is called.
  2. The mouse cursor changes its position when the value is changed on macOS. Normally the method Knob::mouseMoveEvent tries to suppress this cursor movement by calling QCursor::setPos( mapToGlobal( m_origMousePos ) ). I guess this is done so that the changing of the value is restricted by reaching a screen boundary.

So it seems that macOS restricts the capability for manipulation of the mouse cursor and perhaps this somehow breaks the implementation of the knob on macOS.

@PhysSong
Copy link
Member

So it seems that macOS restricts the capability for manipulation of the mouse cursor and perhaps this somehow breaks the implementation of the knob on macOS.

It seems like macOS 10.14 requires the user to grant the "control the computer" permission to an app in order to use QCursor::setPos(). See a comment on QTBUG-75786 for details.

@tresf
Copy link
Member Author

tresf commented Sep 24, 2019

@PhysSong (as usual) good find. That fixes it.

Unfortunately, it's simply not going to be a long-term solution for macOS 10.14+. Can we compromise on a solution that doesn't require bumping up against accessibility options?

Here's some example of knob UIs that are what I would consider to be more standard. http://anthonyterrien.com/demo/knob/.

Although rewriting the knobs is too large of a task for our 1.2. branch, we need a way to make the UI usable on 10.14 without hidden settings, even if that means the mouse moves around when it's used.

@tresf
Copy link
Member Author

tresf commented Sep 24, 2019

So I've removed the calls to QCursor::setPos and QApplication::setOverrideCursor/restoreOverrideCursor but the bug still happens. Is there other code that interacts with the processing of drag events that's not obvious or not in Knob.cpp?

@tresf
Copy link
Member Author

tresf commented Sep 24, 2019

Ok, I see what's going on. The relative position is 100% reliant on the fact that the mouse keeps getting moved back.

Somewhat working example is to change this code:

- QCursor::setPos( mapToGlobal( m_origMousePos ) );
+ m_origMousePos = _me->pos();

The downside is the cursor eventually hits the edges of the screen requiring subsequent click/release.

This code also severely exposes @michaelgregorius' point about the small drags having nearly no effect on the knob.

It's arguably worse than driving into accessibility settings.

@PhysSong
Copy link
Member

Here's some example of knob UIs that are what I would consider to be more standard. http://anthonyterrien.com/demo/knob/.

IIRC @gi0e5b06 made his fork use that kind of behavior, but I don't think that was better than the LMMS/lmms implementation(just a personal preference).

FYI, QCursor::setPos( mapToGlobal( m_origMousePos ) ); is also known to cause issues with Wacom tablets(see #4376).

@Spekular
Copy link
Member

Spekular commented Sep 24, 2019 via email

@michaelgregorius
Copy link
Contributor

I agree with @Spekular. I have tried some VSTs in the past that implemented that "you have to move the mouse pointer in a circle exactly along the knob" behavior and they were very tedious to use, i.e. I did not use these plugins. 😄

If I remember correctly I even checked in the past whether it is possible to get "raw" mouse input, e.g. only relative movements a la "the mouse moved a delta of x upwards" but I did not find anything. Having such raw data would do away with the need to move the mouse pointer back during each event.

@tresf
Copy link
Member Author

tresf commented Sep 25, 2019

I'm testing out garageband and it's just up/down as we do now, not left/right.

Carla is up/down AND left/right.

@falkTX can we use your knob code? It feels fine to me and Carla works just fine with Mojave, Catalina, etc.

@PhysSong
Copy link
Member

This is how LMMS' knobs calculate the value change:

value = ( ( _p.y() + _p.y() * qMin( qAbs( _p.y() / 2.5f ), 6.0f ) ) ) / 12.0f;
// if shift pressed we want slower movement
if( gui->mainWindow()->isShiftPressed() )
{
value /= 4.0f;
value = qBound( -4.0f, value, 4.0f );
}
return value * pageSize();

Here _p is the coordinate difference between two mouse move events, and +/-100 corresponds to the difference between the minimum value and the maximum value. I think the intention is to change the value depend on the speed of the mouse movement as well as the distance of the mouse movement. In contrast, Carla doesn't have such a feature.
Here's the graph of the function:
knobdiff
Also, I can't even change the value of a knob with the shift key pressed. I'm on Ubuntu 18.04 and using the builtin Synaptics touchpad.

@Spekular
Copy link
Member

Not being able to move the knob when shift is pressed is probably not our bug. In my experience, laptops won't allow trackpad input while a key is held. If you can test with a USB mouse you'll likely find that shift + drag works.

@tresf
Copy link
Member Author

tresf commented Sep 26, 2019

In my experience, laptops won't allow trackpad input while a key is held. If you can test with a USB mouse you'll likely find that shift + drag works.

You have it backward. The "Palm Detect" feature of trackpads will temporarily disable the trackpad from moving the cursor when the keys are being pressed, not the other way around. I agree that @PhysSong's issues are probably environmental, but I strongly disagree that Shift modifier is expected to malfunction when using a trackpad.

@PhysSong
Copy link
Member

Strangely, sliders work fine with the same modifier key. 🤔

@PhysSong PhysSong modified the milestones: 1.2.1, 1.2.2 Oct 10, 2019
@soundconjurer
Copy link

soundconjurer commented Dec 23, 2019

I am having this issue with Fedora 31 64-bit, with flatpak.

LMMS 1.2.1 from the Flatpak, the knobs just go all the way with one or the other with the tiniest move of the mouse.

LMMS 1.2.1 from the AppImage does not do this.

@JohannesLorenz
Copy link
Contributor

JohannesLorenz commented Dec 27, 2019

Summary

By now, LMMS resets the cursor, which is relevant for the increasement speed formula. Tres suggested a patch where the cursor is moved and the formula is valid, but the disadvantage is that reaching the screen borders will limit you, so you need multiple drags to use a knob. This screen border limitation seems the main problem.

Proposal

Make one mouse direction invert the movement when a knob is close to the the top right or down left screen edges. E.g. if the knob is too much down left, a movement up to the top left corner could translate to "down", and a movement to the bottom right corner could translate to "up".

Proposed because I did not know how LMMS knobs worked until now and I never made any assumptions which direction does increase and which does decrease. I always moved the knob a bit, and if it worked, I moved the mouse on. So learning how to use a knob is individual for some users. It's similar to window context menus opening top left to the window if the window is almost completeley down right.

There may be other solutions like using some grain control (using keys 0-9 or arrow keys), but I'm against making control too grain, because many knobs control volume and you don't want to blow up your speakers. So if we want to stick to fine control, in the worst case, the described two long mouse directions is all we have.

@Spekular
Copy link
Member

If we really are limited to screen bounds (which sounds strange to me, never had this issue in any software on windows nor linux), couldn't we also make the knob movement proportional to screen size?

I'm thinking

  • Dragging the mouse up by one screen height moves the knob one full rotation
  • Dragging the mouse right by one screen width moves the knob one half rotation

In this way, vertical movement serves as a fast adjustment (shorter distance* maps to big range) and horizontal serves as a fine adjust (wider distance* maps to smaller range).

A knob perfectly centered on the screen could be adjusted 75% in either direction in one go. This range gets skewed the further you get towards the top right/bottom left, but if this is unacceptable perhaps the ranges could be tweaked. If a vertical movement of one screen height translates to two knob rotations, and the knob isn't in the top or bottom 25% of the screen, you'd never need more than two adjustments to reach any point.

*Assuming wide monitor. Perhaps instead of the vertical/horizontal distinction, it should be based on the screens dimension. So, perpendicular to the long edge is fast adjust, parallel to the long edge is fine adjust.

@tresf
Copy link
Member Author

tresf commented Dec 27, 2019

Here's how GarageBand does it. Works fine.

The edges of the screen are annoying, but it's fine. People can click twice for those (metaphorical and literal) edge-cases.

ezgif-7-9b0b2b7164bb

ezgif-7-476c867b3ded

@tresf
Copy link
Member Author

tresf commented Dec 27, 2019

Dragging the mouse up by one screen height moves the knob one full rotation
Dragging the mouse right by one screen width moves the knob one half rotation

I'd advocate that it's exactly consistent. Changing sensitivity on direction is clever, but not intuitive. GarageBand only allows up/down for knobs and it feels natural, I've never had an issue with it.

In regards to screen size, I'd vote against any screen magic. It should feel identically sensitive across all screens. If a screen is too small to move the knob a full rotation, the interface is suffering in many other ways already. 😄

@JohannesLorenz
Copy link
Contributor

Zyn also only uses up/down. But if we offer additional left/right, that's no disadvantage.

I conclude if we take your suggested patch, tres, then the issue would be solved "well enough"? If a user still has too many "edge cases" they can simply move the window...

@tresf
Copy link
Member Author

tresf commented Dec 29, 2019

I conclude if we take your suggested patch, tres, then the issue would be solved "well enough"? If a user still has too many "edge cases" they can simply move the window...

Agreed although to be clear, I have provided no patch. I attempted to fix this using code, but was unable to, so I need help implementing this assuming it's to be expedited.

If the code changes are too large to introduce to stable-1.2, we can milestone it for master instead. In its current state, the knobs are unusable and macOS fails to raise the security dialog for the workaround, so if master is targeted, I'd still like to treat it as priority (as well as nightly downloads) so end-users have a quick fix which makes the software usable again.

@JohannesLorenz JohannesLorenz changed the title Knobs are erratic on macOS Knobs are erratic on macOS (and other systems) Dec 29, 2019
@JohannesLorenz
Copy link
Contributor

@tresf Can you please checkout branch #5194-setpos from my github (git@github.com:JohannesLorenz/lmms.git) and check

  1. What the command line outputs?
  2. If the behavior of setPos/hide looks right to you?

@tresf
Copy link
Member Author

tresf commented Feb 3, 2020

  1. What the command line outputs?
setPos working? false
setPos working? false
setPos working? false
... (message shows exactly once per new knob turn)
  1. If the behavior of setPos/hide looks right to you?
  1. Well, when I added build/lmms to my list of trusted applications that can control the computer, the message didn't change, so I'm not sure if the testing technique is correct.
  2. I wouldn't expect each knob to need it's own detection algorithm. It seems like one time would be sufficient.

@JohannesLorenz
Copy link
Contributor

when I added build/lmms to my list of trusted applications that can control the computer, the message didn't change

Was the cursor back on the knob when you released the key?

I wouldn't expect each knob to need it's own detection algorithm.

Good point. I forgot to make the variable static.

@tresf
Copy link
Member Author

tresf commented Feb 3, 2020

Was the cursor back on the knob when you released the key?

No, it was working as intended, but when I enabled the option to control the cursor, it still detected as being off, so that's a bit concerning to me that your detection technique is not working.

@JohannesLorenz
Copy link
Contributor

Sorry, I don't get what you say 😄 After you enabled the option to control the cursor, was the cursor back on the knob right after releasing?

@tresf
Copy link
Member Author

tresf commented Feb 3, 2020

After you enabled the option to control the cursor, was the cursor back on the knob right after releasing?

No, after enabling the option to control the cursor the behavior did not change.

@JohannesLorenz
Copy link
Contributor

In the same LMMS process? On the same knobs?

@tresf
Copy link
Member Author

tresf commented Feb 3, 2020

I restarted LMMS and it made no difference.

@JohannesLorenz
Copy link
Contributor

OK that would mean that you can tell MacOS to allow to set the cursor, but QCursor::setPos() does not change the position, at least not immediatelly. In this case, I think I must ask on SO.

@jcelerier
Copy link

I have the exact same problem on OSSIA/score - I'll try to reduce and make a bug report. The impression I get is that setPos is asynchronous on macOS and synchronous (or at least much less laggy) on other platforms.

@jcelerier
Copy link

looks a lot like this issue actually : https://bugreports.qt.io/browse/QTBUG-67639

@tresf
Copy link
Member Author

tresf commented Mar 4, 2020

looks a lot like this issue actually : https://bugreports.qt.io/browse/QTBUG-67639

Interesting, thanks for sharing. If that's the case, that would suggest that setPos() will work as a unit test so as long as we don't send it a float, no?

@jcelerier
Copy link

jcelerier commented Mar 4, 2020

Can indeed fix my issue by calling the CG functions manually with floating point values - I do in the mousePressEvent

// m_viewport is a QGraphicsView, m_startPos a QPointF, ev a QGraphicsSceneMouseEvent*
m_startPos = m_viewport->mapToGlobal(QPoint{0,0}) + ev->pos();

and in the mouseMoveEvent

#if defined(__APPLE__)
    CGPoint ppos;
    ppos.x = m_startPos.x();
    ppos.y = m_startPos.y();

    CGEventRef e = CGEventCreateMouseEvent(nullptr, kCGEventMouseMoved, ppos, kCGMouseButtonLeft);
    CGEventPost(kCGHIDEventTap, e);
    CFRelease(e);
#else
    QCursor::setPos(m_startPos);
#endif

and things finally look less crazy - hopefully that can be useful to you !

@JohannesLorenz
Copy link
Contributor

There is already an open PR #5360 . Unless anyone vetos in the next days, I'll close this issue to avoid confusion/redundancy.

@Spekular
Copy link
Member

Aren't issues typically left open until their fixes are merged? If the fix PR fails to solve the issue, or gets closed without merging, you want the original issue open so the bug isn't incorrectly marked as fixed.

@JohannesLorenz
Copy link
Contributor

Also true. I'll leave it open.

IIRC @tresf did that in the past a couple of times, so I thought it was common 😄

@tresf
Copy link
Member Author

tresf commented Apr 12, 2020

If I prematurely closed any bug reports because of active PRs, it was years ago -- and in hindsight -- premature. 😁

JohannesLorenz added a commit to JohannesLorenz/lmms that referenced this issue Apr 26, 2020
For systems where QCursor::setPos() has no effect, this fix adds a
workaround for the situation where a knob value is changed via mouse
click and move. The fix simulates that the cursor is moved back to the
original click position.

Before this commit, the cursor was always reset over the knob. Now, it
runs over the screen and tries to flip on the opposite screen side if it
hits the screen border.

This changes the meaning of `Knob::m_origMousePos` from "always being
the position where the user clicked" to "the last position in
mouseMoveEvent". And it renames it to `m_lastMousePos`.

On Apple, `setPos` and cursor hiding are now completely disabled.
JohannesLorenz added a commit to JohannesLorenz/lmms that referenced this issue May 10, 2020
This PR does

* Remove all `setPos()` from Knob.cpp on all OS
* Therefore use the previous position, not the original position to
  compute the cursor delta
* Use the cursor delta now linearly
* Use the cursor delta in relation to the screen height
JohannesLorenz added a commit to JohannesLorenz/lmms that referenced this issue May 14, 2020
JohannesLorenz added a commit to JohannesLorenz/lmms that referenced this issue May 15, 2020
For systems where QCursor::setPos() has no effect, this fix adds a
workaround for the situation where a knob value is changed via mouse
click and move. The fix simulates that the cursor is moved back to the
original click position.

Before this commit, the cursor was always reset over the knob. Now, it
runs over the screen and tries to flip on the opposite screen side if it
hits the screen border.

This changes the meaning of `Knob::m_origMousePos` from "always being
the position where the user clicked" to "the last position in
mouseMoveEvent". And it renames it to `m_lastMousePos`.

On Apple, `setPos` and cursor hiding are now completely disabled.
JohannesLorenz added a commit to JohannesLorenz/lmms that referenced this issue May 15, 2020
JohannesLorenz added a commit to JohannesLorenz/lmms that referenced this issue May 18, 2020
For systems where QCursor::setPos() has no effect, this fix adds a
workaround for the situation where a knob value is changed via mouse
click and move. The fix simulates that the cursor is moved back to the
original click position.

Before this commit, the cursor was always reset over the knob. Now, it
runs over the screen and tries to flip on the opposite screen side if it
hits the screen border.

This changes the meaning of `Knob::m_origMousePos` from "always being
the position where the user clicked" to "the last position in
mouseMoveEvent". And it renames it to `m_lastMousePos`.

On Apple, `setPos` and cursor hiding are now completely disabled.
JohannesLorenz added a commit to JohannesLorenz/lmms that referenced this issue May 18, 2020
@lukas-w lukas-w closed this as completed in c6a1abe Jun 1, 2020
mgee044 added a commit to POZAlabs/lmms that referenced this issue Oct 18, 2021
* Issue templates improvements

* Ask users to search the tracker first
* Ask for the LMMS version in bug reports

* GitHub: Add Discord contact link to template chooser

* more depricated qt functions

* setPath rather than operator= for qDir

* lambdas instead of QSignalMapper

* Remove remaining usages of QSignalMapper

* CMake: Require Qt 5.6+

* Remove Travis MinGW builds

We already run them on CircleCI with a newer Qt version.

* Change the docker tag for CircleCI Linux builds

In response to https://github.com/LMMS/lmms-ci-docker/pull/7

* CircleCI: support Qt from a PPA on /opt

* Use "bar" instead of "tact"

Closes #4865

* New BARS_PER_GROUP constant

* Fix crash due to calling QWidget::move from a non-GUI thread while exporting tracks.

Calling via QMetaObject::invokeMethod should be thread safe.

Crash callstack:

QWidget::move
SongEditor::updatePosition
Song::stop
Song::stopExport
ProjectRenderer::run
QThreadPrivate::start

* C++11 inheritance updates

Add `override` and remove `virtual` where applicable

* appimage: move launcher code into launch_lmms.sh.

* appimage: Use command -v instead of which (sc2230)

* appimage: Escape $DIR to avoid word-splitting

* Fix vertical piano mouse click unresponsiveness

`PianoRoll::mouseDoubleClickEvent` wasn't forwarding the event to the base class when not acting on the event. The base class calls `mousePressEvent`.

Fixes #3005

* Fix vertical piano mouse click unresponsiveness

`PianoRoll::mouseDoubleClickEvent` wasn't forwarding the event to the base class when not acting on the event. The base class calls `mousePressEvent`.

Fixes #3005

* CricleCI: Test merged pull request

* Sampletrack activity indicator

* Do not include unused headers

* Support NetBSD's OSS audio/midi implementation (#5277)

* Moved the activity indicator mute code to parent class

* Added to sampletrackview the code needed for the activity indicator mute behaviour

* Debian packaging improvements (#5264)

* d/control: http -> https
* d/control: rearrange lists (one item per line + alphabetically ordered)
* d/copyright: http -> https
* Delete contributors.patch (integrated now)
* d/series: removes contributors.patch

* Add some missing includes

* Fix incorrect m_lastSoloed after moving/deleting an FX channel

Original code by @gi0e5b06.

* Fix remote plugin crash reading parameters from Grooove plugin (#5300)

* Fixed triggering of stop animation when not playing

* Xpressive plugin updates (#5217)

* Updated plugin artwork.

* Update the formula in the presets to use integrate(f) instead of
  t*f, as integrate operation is more robust to frequency changes.

* rename X-Pressive to Xpressive in help window title.

* Xpressive.cpp, spaces to tabs and remove commented code.

* Fix triggering of stop animation when playing no samples after stopping song playing samples

* Spectrum analyzer update (#5160)

* advanced config: expose hidden constants to user screen
* advanced config: add support for FFT window overlapping
* waterfall: display at native resolution on high-DPI screens
* waterfall: add cursor and improve label density
* FFT: fix normalization so that 0 dBFS matches full-scale sinewave
* FFT: decouple data acquisition from processing and display
* FFT: separate lock for reallocation (to avoid some needless waiting)
* moved ranges and other constants to a separate file
* debug: better performance measurements
* minor fixes
* build the ringbuffer library as part of LMMS core

* Fix crash on deleting instrument with controller connections on knobs (#5306)

Knob::friendlyUpdate() can be called after the model is deleted
due to signal-slot connections.
Adding a check for the model fixes a crash due to null pointer dereference.

* Fix invalid read in RemotePlugin::RemotePlugin() on opening the ZynAddSubFx GUI. (#5299)

Calling .toUtf8().constData() returns a pointer which is invalid at the end of the statement.

* SpectrumAnalyzer: Fix typo

* filebrowser: making the string more flexible for i18n

* Return EXIT_SUCCESS instead of 0 in main

* MIDI import: fix putting notes before the beginning of a pattern (#5343)

* Only filter out <>:"/\|?* while exporting tracks.

* Fix scrolling direction in SongEditor due to stuck Ctrl/Shift.

* Debian: add libx11-xcb-dev as an explicit build dependency

* Comment-out deprecated attribute

It may be valid, but fails our CI

* fix locking of the useless_lock in LocklessRingBuffer.h

* Fix stuck notes with Helm VSTi

* Simplify FadeButton update (#5311)

* Switch to Xenial build environment  (#4813)

* Switch to Xenial build environment
* Add Carla submodule/weak linking support, related #3963 
* Fix Carla detection in AppImage, closes #5369

* FileBrowser: Add helpful comments

* Fixes #3183: Fix file factory delimeter position

* Fix a muted demo project "Greippi - Krem Kaakkuja (Second Flight Remix)"

* fix spelling errors (#5385)

* Add the vectorscope plugin (#5328)

The credit for the `ColorChooser` class goes to CYBERDEViLNL.

* macOS CI: fix package conflicts due to Homebrew's Python 2

* Travis/macOS: rename qt5 to qt in the installation script

Travis-CI started installs Qt 5 to their macOS images.
To exclude qt properly, it should not be written as its alias 'qt5'.

* Fix handling of plugin_export.h
Fixes error: definition is marked ‘dllimport’
Per #4813

* Linked model groups (#4964)

Add labeled controls for different types with a common base class

Implement a container for multiple equal groups of linked models and
suiting views. Such groups are suited for representing mono effects where each
Model occurs twice. A group provides Models for one mono processor and is
visually represented with a group box.

This concept is common for LADSPA and Lv2, and useful for any mono effect.

* Bias dropped clip position backwards

* Fix doxygen comment

* Fix knobs not updating vals on link (#4904)

* Update UI after linking models (#4904)

* Document strange bug

* Elaborate on desired version information

Closes #5368

* RemoteVstPlugin: fix issues with FXP/FXB files on Windows (#5411)

* Fix issue #5409. (#5413)

Fix multiple uninitialized reads.

* Cherry-pick from master commit 4dc26d1 (#5413)

* Fix previous commit

* Fix SDL2 detection

Per #5389 (Comment)
Recommended by @PhysSong 
Adopted from upstream SDL1 patch https://github.com/Kitware/CMake/commit/c5c217c6b53b035303747a2971b1b80be5391566

* Refactor FFT helpers (#5309)

* Do not check if unsigned int is negative

* Reduce scope of some local variables

* Use right types for iterators

* Check conditional returns first

* Remove unused functions

* Utilize a range-based for loop opportunity

* Fix crashes and hangs on importing some Hydrogen drum kit songs (#5420)

* Use proper synchronization methods on some instrument track operations

* STK Mallets: don't silence active notes when switching instruments

This also fixes the underlying noise on instrument switches.

* Fix bug made in #5336

This removes a duplicate dataChanged() emit. Thanks to @PhysSong for the
hint.

* Fix the linking method for the dummy Carla library

* Fix some issues in shell scripts spotted by shellcheck

* Fix wine detection

* Fix linking issues with the dummy Carla library(especially with MSVC)

* Carla: fix MSVC compatibility

* Fix submodule fetching from non-default branches with old Git

* Ensure plugin dependencies are deployed correctly

* Use shimmed std::as_const instead of qAsConst

* Add "Open containing folder" (#5453)

Add functionality to open the containing folder of a file that's selected
in LMMS' file browser.

Technical details
------------------
Add a new private method openContainingFolder to FileBrowser. Add a new
action to the context menu of a selected file. This action in turn calls
the added method.

The current implementation of openContainingFolder delegates to
QDesktopServices::openUrl with the directory of the selected file. Please
note that this will only open the directory but not select the file as
this is much more complicated due to different implementations that are
needed for the different platforms (Linux/Windows/MacOS).

Using QDesktopServices::openUrl seems to be the most simple cross
platform way which uses functionality that's already available in Qt.

* Code review changes

Move openContainingFolder to the end of the method block.

Adjust FileBrowserTreeWidget::contextMenuEvent to the coding conventions
and also make the code more readable by splitting up some conditions.

Add comments to clarify as to why the member m_contextMenuItem is set to
nullptr at the end of the execution of contextMenuEvent. Please note
that this implementation is not exception safe and should be changed in
the future, e.g. by passing the FileItem as a parameter of the slot.

* Code review changes (comment added)

Add a comment which describes that only the folder is opened without
selecting any file. Also explain why it is only done like this for now.

* Remove plugins/LadspaEffect/swh/ladspa-util.c (#5451)

This file contains no used code and it caused build problems, so we
remove it. Thanks to @plater for the issue report.

* disable drag after drawing line (#5315)

* Note selection: Editing values works in dialog (#5438)

* DrumSynth: ensure correct envelope length in any sample rate (#5467)

* If AutomationPattern has a single tick at 0, set it's length to 1 bar.

* Add comments and reduce unnecessary code

* Fix crash on drawing line on the end of a graph (#5471)

This bug was introduced in dff76b2e83d4cfe140a8554f590cfd3780b61204.
The function changes [sample_end, sample_begin), but emits the signal
as if [sample_end, sample_begin] has been changed. That bug made
Multitap Echo crash when tweaking the cutoff of the 32nd stage.

This commit fixes the issue by emitting sampleChanged with sample_end - 1.

* AFP: fix loading start and loop points if the loop point is automated (#5472)

* refactor

* Fix indicator in BB editor

* Piano roll vertical zoom (#5442)

* Use nullptr instead of NULL

Requested by Veratil <veratil@gmail.com>

* Formatting chananges

* Nicer spacing in activity indicator's setGeometry call

Co-authored-by: Kevin Zander <veratil@gmail.com>

* Refactor palette update on un/mute

* Select the correct piano key for marking semitones (#5478)

When selecting a Piano Key to mark semitones in the Piano Roll we
select key from the y position of the pop-up menu and not the mouse.
Incidentally these two are most often the same as the menu builds
from the mouse y positon and down. If there is room for it. If there
is no room downward it will create the menu so the lower part of the
frame aligns with the mouse y position.
Fixed by creating a variable to hold the pressed key before creating
the menu.

* 3rdparty/cmake: Do not reset CMAKE_C(XX)_FLAGS (#4080)

CMake 3rdparty: Do not overwrite CMAKE_C(XX)_FLAGS

Co-authored-by: tresf <tres.finocchiaro@gmail.com>

* Use local cursor instead of global one in PianoRoll (#5200)

Fixes stuck vertical cursor as well.

* Remove unwarranted CXX flag
Per https://github.com/LMMS/lmms/pull/4080#issuecomment-623058847

* Add option to move SideBar to right side of window (#5114)

* Fix #5461 and ensure consistent use of check gate (#5475)

* Multiple effects: Calculation of `outSum` should be after D/W mixing
* CrossoverEQ.cpp: `outSum` must be divided by frames in the end 
* CrossoverEQ.cpp: don't overwrite `outSum` in for loop, but increment it

* Fix #4098 (#5449)

Fixes piano roll crashing when window is scaled too large.

* VST preset preview (#5441)

* Enable vestige presets preview.

* Don't destroy vestige instrument on every preset change.

* Don't reload VST dll plugin when it's not necessary. Always hide plugin UI in preview mode.

* Don't remove other instruments in preview mode, don't send instrument change signal.

* Minor changes

* Add a change I missed

Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>

* Decrease Bitcrusher bit depth reduction step size (#5407)

* Refactor the oscilloscope (#5488)

* Rename files

* Update code

* Remove unused code

* Make background a member variable

* Forward search paths correctly in INSTALL_TARGET_DEPENDENCIES

Also fixes a typo in cmake/install/CMakeLists.txt.

* addStretch() before adding the oscilloscope

* Fix Windows compilation with no gzip available

* Fix Windows rpmalloc compile flags

* Audio/MidiJack: Fix invalid read: (1) of #5408

This fixes reading from jack MIDI events in case where
there are no jack MIDI events.

* Audio/MidiJack: Fix invalid read: (2) of #5408

This patch
* makes `m_stopped` atomic
* initializes `m_stopped` correctly to `true`
* moves the initialization of `m_stopped` to the point where jack ports
  are already connected

* Audio/MidiJack: Fix invalid read: (3) of #5408

This atomically unsets the MidiJack reference in AudioJack right before
MidiJack is destroyed. This avoids AudioJack using a destroyed MidiJack
object.

* JackMidi: Remove confusing warning at shutdown

Warning is:

```
jack_port_unregister called with an incorrect port 0
Failed to unregister jack midi output
```

* Song Editor - Delete selected objects with backspace key (#5497)

* Show VST parameter string (#5321)

* ControlLayout: Allow removing search bar's focus

* Fix Qt 5.15 build issues (#5498)

Add missing QPainterPath includes

* Implement fade in to prevent Triple Osc from clicking (#5199)

* Fix wrong lengths of exported tracks, when tracks have different lengths. (#5348)

* Fix wrong lengths of exported tracks, when tracks have different lengths.

Song::updateLength() was called in ProjectRenderer::run() after Song::startExport(),
updating m_length too late, resulting in it being used as the length of the wrong track.

* Fix "Export as loop" resetting after rendering the first track

Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>

* Divide knob step size by 1000 for LADSPA effects (#4574)

* Implement compress action for commandline use (#5341)

* Fix #5483: sf2_player: No crash when file is no soundfont (#5487)

* LinkedModelGroupView: Un-focus filter edit...

... whenever the user clicks other widgets

* Fix #5504: invalid warning

* Lv2 core implementation

Implementation of the Lv2 core, except for CV ports. No features or
extensions are supported yet.

You can now generate sound using Lv2 instruments (restricted to non-piano)
or effects.

For an explenation about the new classes, see Lv2Manager.h

* Fix #4201: BB editor: adjust cursor position (#5489)

This fixes an offset for cursors whose pointer position varies between
different themes.

* Fix #5194: Fix knobs moving too fast (#5360)

This PR fixes issues on systems where `QCursor::setPos()` has no effect
or is not reliable. These issues included knobs moving to fast on some
operating systems. Affected widgets are `Knob` and `LcdSpinBox`.

With this PR, on all operating systems, the `setPos` calls are removed and
the cursor is not hidden anymore, so the mouse keeps moving normally
when changing values of one of the widgets.

As now the previous pointer position keeps moving (instead of being reset
to the original position using `QCursor::setPos`), the mathematics that
translate pointer pixel distance to `Knob`/`LcdSpinBox` value increase
have to be changed:

* The `Knob` transition function is now linear and uses a new factor.
* `LcdSpinBox` now uses float values and saves the current float remainder
  (this is actually a separate issue revealed by this fix), leading to a fluent,
  non hanging movement.

* Compensate beat note length when stretching (#5515)

* Compensate beat note length when stretching

We allow stretching beat notes to normal notes but the length starts
from -192 so there is a lag for one whole note before any change is
seen. Compensate by setting the oldNote value to 1 when stretching
if the note is 0 or below in length.

Co-authored-by: Spekular <Spekular@users.noreply.github.com>

* Remove stopPlaying connection

Missed this in #5477

* 24 bit FLAC export. Clip negative side of wave (#5501)

24 bit FLAC export. Clip negative side of wave to counteract a bug in libsndfile < 1.0.29

Co-authored-by: Spekular <Spekular@users.noreply.github.com>
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>

* Allows instruments to keep the MIDI channel information when forwarding (#5470)

Now it's possible to forward received MIDI events with their original channel, either to another track or to the instrument plugin itself. To do that, the user must select the channel "--" on the MIDI output widget. In that case, all MIDI events will be forwarded with their original channel, and the MIDI events produced by the track itself will be sent with the default channel.

* Consolidate error messages while loading project (#5269)

* Remove macros likely() and unlikely() (#5530)

* Remove macros likely() and unlikely(): https://github.com/LMMS/lmms/pull/5530/#issue-431515330

* Remove only use of macro Q_UNLIKELY(): https://github.com/LMMS/lmms/pull/5530/#issuecomment-641634577

* Adds a button to clone the BB track pattern

Adds a button on the BBEditor that clones the current BB track pattern, but without also cloning the song editor TCOs. That can be useful when an user is editing drumlines and wants to make a section with a slight variation for example.

* Changes the clone pattern method name

- Changes method name from cloneBBTrackPattern to clonePattern
- Small fix on the comments
- Adds a TODO comment regarding reusing the code from TrackOperationsWidget as a reference, so we can later figure out a way to not repeat the code

* Make better use of getSelectedNotes() in PianoRoll.cpp (#5526)

* Make better use of getSelectedNotes() in PianoRoll.cpp

* Save and reuse selected note vector more often

* Apply review suggestions

Thanks to @Veratil

* Comment, style, consistency

* Fix some TCOs not saving properly (#5537)

* Automatically assign a midi input device to the selected track (#5499)

* Travis: stop auto-uploading binary releases

* Update CONTRIBUTORS

* Adding a trail (gradient) behind the position bar (#5543)

* src/gui/editors/SongEditor.cpp

* Gradient can be toggled and color can be changed.

* Made playback line (and tail) transparent to mouse clicks

* Gradient disappears when paused/stopped; tail length depends on zoom

* Fixes bug where gradient appears when a pattern is played; style corrections

* Cleaned up code

* Rename m_zoomLevels to s_zoomLevels

* Finalising code

* Make positionLine class independent of parent zooming model

* Edit a bug fix to make it more efficient

* Rename m_x and finalise positionLine code

* Rename m_x and finalise positionLine changes

* Rename X to playHeadPos

* Add a CMake option for deploying Qt translations

* Update PROJECT_YEAR

* Bump version to 1.2.2

* Update LcdSpinBox.cpp (#5555)

* Make Pause hotkey Shift+Space (#5554)

* Fix a bug on the "Remove unused channels" command (#5559)

On the FX mixer, the "Remove unused channels" action only checked for InstrumentTracks on every channel but ignored SampleTracks that could be linked to the particular FX channel. Because of that, if there was a channel where only SampleTracks are forwarded to and we clicked on "Remove unused channels", it was going to be removed. This commit fixes it.

* Refactor deleteUnusedChannels in FxMixerView (#5564)

* Refactor deleteUnusedChannels in FxMixerView

* Comments + style fix

Co-authored-by: Veratil <veratil@gmail.com>, formatting, suggestions on which lines to comment.

Co-authored-by: Kevin Zander <veratil@gmail.com>

* Update weird deleteChannel loop

* Use vector instead of array

Co-authored-by: Dominic Clark <mrdomclark@gmail.com>

Co-authored-by: Kevin Zander <veratil@gmail.com>
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>

* Better minimum length when resizing notes (#5512)

* Limit note length to quantization value

Draging a note to it's minimum value of 1 will add this new length to
the note if you later choose to stretch it which will not be clearly
visible in the Piano Roll unless you zoom in a bit. Limit the note
length to the quantization value and use <Alt> key to override and set
a smaller value.

* Update src/gui/editors/PianoRoll.cpp

Co-authored-by: Spekular <Spekular@users.noreply.github.com>

* Remember min note length if shorter than quantization()

* Find note length modulo quantization, pick smallest from selected notes

* Comment on and improve m_minResizeLen calculation

Co-authored-by: Oskar Wallgren <oskar.wallgren13@gmail.com>

* Removed the excessive margin in instruments' GUI (#5129) (#5171)

* Removed the excessive margin in instruments' GUI (#5129)

* Reduced the font size for "master pitch" label.
* Reduced the layout spacing for MIDI Input and MIDI Output groups
* Shortened labels, so that the LcdSpinBoxes are spaced evenly

* Added translator's comments

* Whitespace fix

* Fix garbage in exported audio caused by resampling (#5552)

This makes AudioDevice::resample return the actual number of generated samples.

* Enable LMMS fullscreen and... (long title, read first line of description) (#5563)

* Enable fullscreen with hotkey & hotkey to toggle maximise in internal window

* Fix an obvious blunder

* Add fullscreen menu entry

* Change Alt+F11 to Shift+F11 (fix Windows bug)

* Move F5-F10 to Ctrl+F*, fullscreen by F11 and fix Linux bug

* Remove wrongly placed "fullscreen" attribute

* Remove temporary fixes for redundant bug

* Rename maximise to maximize

* Rename maximise to maximize

* Use fullscreen icon instead of maximise icon

* Actually include the icon in the commit

* Replace .svg icon with .png 16x16 icon

* Migrate editor hotkeys to Ctrl+1-7

* Remove warning color from oscilloscope (#5492)

* Small refactor on FxMixerView.cpp and FxMixer.cpp

The code on FxMixerView.cpp and FxMixer.cpp were using the types TrackContainer::TrackList and QVector<Track *> unconsistently. TrackContainer::TrackList is just a typedef for QVector<Track *> so it makes sense that we use it, specially in terms of readability.

Places where QVector<Track *> were used are now replaced with TrackContainer::TrackList.

Also, we were not including "TrackContainer.h" directly (the typedef was likely being included indirectly through one of the other include files), so we also include this header on both source codes.

* Fixes small conflict on a new commit

On the PR #5470 (Allows intruments to keep the midi channel information when forwarding), merged on Jun 1st 2020 commit 97680e0, there's a line removed on the src/gui/widgets/InstrumentMidiIOView.cpp file ( m_outputChannelSpinBox->setEnabled( false ); ), because since the output channel is now relevant even when MIDI forwarding is disabled, we need that spinbox always enabled. It was also disconnected from the LedButton to keep it from disabling/enabling it.

On the PR #5171 (Removed the excessive margin in instruments' GUI (#5129)), merged on Jul 9th 2020 commit 9895472, the line was reintroduced, possibly because it was an older PR that wasn't rebased to the latest changes. This broke the output channel spinbox because now it was disabled on the constructor, but it was still disconnected from the LedButton, as a result always disabled.

This hotfix removes the line again to fix the issue.

* Fix bug from issue 5562 (#5565)

Fixes a small bug where projects that are saved with a soloed track can't restore the muted state of other tracks, because it doesn't store the m_mutedBeforeSolo variable on the project file.

With this fix, a new attribute is added to the Track DOM element, containing the muted state of tracks before the solo. When loading older projects that don't contain this attribute m_mutedBeforeSolo will be set to false.

* Fix crash on CLI rendering (#5579)

This is a temporary workaround. To make all export options available in CLI,
some properties of TimeLineWidget should be moved to a core class.

* Implement portable mode (#5561)

Adds portable mode by creating a file named portable_mode.txt next to lmms
and fixed a typo in the name of the function

* Remove Xpressive help maximise button (#5570) (#5586)

* Remove Xpressive maximise button

* Fix grammar errors

* Fix the outer border for the instrument track (#5594)

* Add missing ¹⁄₉₆ quantization (#5304)

* Avoid leaking the track grip QPixmap at each paintEvent (#5590)

* Set default behaviour of playhead to << instead of |<< (#5591)

* Set default behaviour, correct spelling

* Set default behaviour, correct spelling

* Store stop behaviour in project

* Change how state is saved & loaded

* Change to use enum

* Minor icon updates (#5588)

* Delete clear_ghost_note.png

* Delete ghost_note.png

* Delete loop_points_off.png

* Delete loop_points_on.png

* Updated and recreated icons

* Delete trackop.png

* New track gear icon

* Improved relative paths (#5117)

* Create PathUtils

* Replace old SampleBuffer calls

* Fix automatic track names

* Fix things

* Remove accidental duplicate file

* Add includes

* More incldues

* PhysSong's code review + style

* Fix vestige loading?

Seems more reasonable to convert from relative on load and to relative on save than vice versa.

* Typo fix

* More Bases

* Enable more bases

* Add missing semicolons in prefixes

* Nicer sample track tooltip

* Use correct directories

"userXDir" gives the default dir for ladspa, sf2, and gig. "xDir" gives the user dir.

* Make relative to both default and custom locations

Part 1

* Make relative to both default and custom locations

Part 2

* Typofix

* Typofix

* Fix upgrade function after base renaming

* Fix Tests

* Update tests/src/core/RelativePathsTest.cpp

Co-Authored-By: Hyunjin Song <tteu.ingog@gmail.com>

* Choose UserXBase over DefaultXBase if identical

toShortestRelative sticks with the first base found if two bases give the same path length. By placing UserXBase Bases before DefaultXBase Bases in the relativeBases vector, toShortestRelative will prioritize them.

* Ensure baseLocation always has trailing slash

Otherwise, a user configuring a path without one will break things.

* Move loc declaration out of switch

* Semicolon

* Apply suggestions from code review...

* Include PathUtil and sort includes

* More granular includes

* Apply suggestions from code review

Co-Authored-By: Hyunjin Song <tteu.ingog@gmail.com>

* Update include/PathUtil.h

* Leave empty paths alone

* Fix stupid merge

* Really fix merge. Hopefully

* Switch Base from enum to class enum

* Don't pass Base by reference

* Use QStringLiteral for static QString allocation in basePrefix method

* Make VST loading more similar to previous implementation

* Fix tests after enum change

* Attempt to fix VST loading, nicer name for sample clips

* Fix last review comment

Don't append a "/" that will be removed by cleanPath later

* Apply suggestions from code review

Co-authored-by: Dominic Clark <mrdomclark@gmail.com>

Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>

* Removes unused variable on SongEditor.cpp (#5600)

There was a variable declared but unused on the SongEditor.cpp file (method SongEditor::keyPressEvent), called QVector<TrackContentObjectView *> tcoViews. The variable was removed.

* Fix validPattern to check if hasAutomation as well (#5124)

* Changes the behavior of "solo" so it doesn't mute Automation Tracks (#5547)

* Changes the toggleSolo method

- Changes the toggleSolo method so it doesn't mute automation tracks (keeps their original state)

* Stop restoring Automation Track's mute values

- Since Automation Tracks are not affected by enabling solo on other tracks, there's no need (and it's even counter intuitive) to restore their previous mute value.
- Reduces a line by using "else if".

* Saves two lines merging 2 conditionals in 1

* Adds the new solo behavior as a new LED button

To allow the user choosing between the old solo behavior and the new one, a new LED button was added which will be used to enable the solo keeping the automation tracks states, while the red LED will enable the solo with the current behavior.

Changes to the code:
	- Added a purple LED image that will be used on the new button.
	- Increased the default width of the widget that holds the mute and solo buttons so the third one fits.
	- Changed the positioning of the LEDs on both the standard and compact track modes to accomodate them.
	- Added a new model called m_soloAutomationsModel, which is connected to the new LED button (m_soloAutomationsBtn). This will dictate the behavior of the toggleSolo method.
	- The red LED calls the toggleSolo method as before. The purple LED will change the m_soloAutomationsModel value and toggle the red LED, which will then call toggleSolo. But since the value of m_soloAutomationsModel will be different, the new behavior will be used on the method.

* Revert "Adds the new solo behavior as a new LED button"

This reverts commit fdbc8b2712d85cb7cafaf0298531557135cf9968.

After consulting fellow users and devs about this change to the PR, it was decided that adding a third button for the new solo behavior was not the best approach. This reverts the commit so we go back to just changing the solo behavior. Later an option can be added on LMMS settings to choose between the old and new behaviors.

* Adds an option to use the legacy solo behavior

This commit adds an option on LMMS settings (saved to the config file) to go back to the legacy behavior of the track solo button. The option can be found on Settings>General>"Use solo legacy behavior"

Changes to the code:
	- Since there's a change to the configuration file, an upgrade method was created (upgrade_1_3_0) to add the value to the config XML if it isn't already present (safety check).
	- An attribute is added to the DOM structure of the app configuration under the "app" tag, called "sololegacybehavior", which can be either 0 or 1.
	- Changes were made to include/SetupDialog.h, include/ConfigManager.h and src/core/ConfigManager.cpp to implement this new configuration option.
	- The toggleSolo method was changed to behave according to the value of the "sololegacybehavior" configuration.

* Changes the description of the solo setting

Changes the description of the solo setting on the Setup Dialog from "Use solo legacy behavior" to "Mute automation tracks during solo" since the latter is more descriptive and new users wouldn't be confused about what the legacy behavior was.

* Merges "if"s and "if-else"s where possible

A conditional could be merged by using the "||" logical operator and there was a "if" nested inside an "else" that could be merged into a single "if-else".

Very small code format change (keeping code block curly braces in separate lines).

* Uses default value instead of upgrading ConfigFile

Instead of using an upgrade method on the ConfigManager class to set a value to the sololegacybehavior parameter, we now use a default value on every call to ConfigManager::value that requests it.

* Removes repetitive method call

To make the loop more efficient, a local variable was created to hold the behavior of the solo selected in the setup dialog, instead of calling the ConfigManager::value method repeated times.

Observation:

Since no code was added/removed from ConfigManager.cpp, it was restored to its original state. There's however a TAB character in a blank line on line 145, which was there at the beginning of this PR but removed during it. It was written again in this commit to remove ConfigManager.cpp from the "Files changed" list.

* Saves one line of code and adds a comment

* RemoteVstPlugin32: Fix Qt version check with MSVC 2019 + Qt 5.15 (#5607)

* Fix metronome playing when song is paused. (#5612)

* Implement Lv2 Urid feature (#5517)

This includes implementing general feature handling, since this is the first supported feature.

* Refactor PianoRoll (#5253)

* Rework PianoRoll paintEvent + some extras
* Split out PositionLine class to own file
* Refactor PianoRoll Q_PROPERTYs
* Reduce code by using Q_PROPERTY's MEMBER function and removing getter/setter functions
  After looking at the getters and setters, they did nothing different than what direct
  access would allow. Nothing outside of PianoRoll used the public functions as well.
  Considering these factors we can reduce the number of functions by 2x the number of
  Q_PROPERTIES, and go with direct access instead.
* Remove need for keyboard pixmaps
  With the recent change to allow zooming vertically, aligning pixmaps is a PITA. Since
  we have themes which can take brushes and colors, it would be simpler to take a solid
  color or a gradient with some extra style properties to resize the keys and text colors.
  While it will slightly be a downgrade from pixmaps since they can be anything really,
  this will allow us to customize the piano roll further moving forward.
* Added the ability to update margins for TimeLineWidget and StepRecorderWidget
  These take a X coordinate, which was hardcoded to WHITE_KEY_WIDTH, and never looked
  back. Now we can adjust on the fly if we need to. Currently this just allows us to
  shift the left margin to the style-defined white key width.
* Fix phantom pixmaps when PianoRoll not focused
* Update PositionLine class changes related to #5543

* Improve the context menu actions when multiple TCOs are selected (#5601)

* Starts implementing the feature

The idea of this branch is to allow actions triggered through the context menu of a TCO on the song editor to affect all the selected TCOs. With this commit, only the "Mute/unmute" action affects all selected TCOs, while the others retain their old behavior (only affect the TCO that owns the context menu).

For that, a method was created that processes all actions (the triggered action is parsed as a parameter to the method). In the case of the "Mute" action, it checks if the song editor has selected TCOs, and if it does it mutes/unmutes all of them.

* Allows selected TCOs to be removed too

Now the "Remove" action from the context menu will remove all selected TCOs if there are any.

* Starts implementing selected TCO cut and copy

Now, when multiple TCOs are selected, the context menu actions Cut and Copy will write a DataFile to the clipboard containing the TCO information, so it can later be used to paste it.

The Paste action now checks if there's data in the QApplication clipboard. If there is, it will later paste the TCOs (for now it just prints the data with qWarning). If there's not, it uses the regular TCO paste method that uses the internal LMMS clipboard. Because it now have to decide between the QApplication clipboard and the LMMS internal clipboard, the Clipboard::copy() method now clears anything in the QApplication clipboard, making it empty so LMMS can know it should use the internal clipboard instead in that situation.

Adds safety checks for the selected TCO views.

* Overloads TCW paste selection methods

This commit is a step towards implementing the paste feature of the TCO context menu. It overloads the TrackContentWidget::canPasteSelection and TrackContentWidget::pasteSelection methods so they can be called without having a QDropEvent (only the QMimeData with the copied TCOs information). The overloaded canPasteSelection(MidiTime, QMimeData, bool) method required a third argument which says whether pasting over the same bar should be allowed or not, because it shouldn't when the QDropEvent comes from the same application but should when it doesn't. That is defined in the canPasteSelection(MidiTime, QDropEvent) method.

Also, the pasteSelection(MidiTime, QDropEvent) isn't optimal, since it calls canPasteSelection twice (more details in the comments, but it's basically because the two canPasteSelection methods can return different values depending on the origin of QDropEvent). This could later be fixed by calling canPasteSelection before pasteSelection and removing it from inside the method altogether.

Next step is to add the "tco_" key to the mimeData on the Copy/Cut operations and implementing the paste operation using those methods.

* Adds the TCO type to the clipboard

Adds the key with the TCO type ("tco_" + type number + ":" + TCO Data XML) to the clipboard, so it can be later used by the canPasteSelection and pasteSelection methods.

* Apply changes to "src/tracks/SampleTrack.cpp"

Change the SampleTCOView::contextMenuEvent() method so it behaves the same way as the TrackContentObjectView::contextMenuEvent() method. For that, I had to change the ContextMenuAction enum and the contextMenuAction methods to be protected instead of private, so SampleTCOView can access it.

* Implement the paste action

Now that the canPasteSelection and pasteSelection methods were overloaded, it was possible to implement the paste action using the same logic as the Drag&Drop copy/paste.

Other small changes:
	- Removes the TCO views AFTER creating the TCO data file, instead of before (which probably resulted in an empty data file).
	- Uses the StringPairDrag::mimeType() instead of Clipboard::mimeType() since that's the one the methods from StringPairDrag.cpp recognizes.

* Removes QDebug header

Forgot to remove the QDebug header on the last commit.

* Creates a Context Menu on the TCW for "paste"

Now it's possible to paste a selection of copied TCOs anywhere in the TCW, as long as the rules to paste are met (same rules as Drag&Drop copy/paste). If the rules are not met the "Paste" menu action shows but is disabled.

* Small code refactoring

Saving a few lines of code.

* Avoids double call to canPasteSelection

This commit adds a third parameter to the pasteSelection overloaded method, which will define whether we whould skip the canPasteSelection check. The only situation where we will want to skip it is if we are calling pasteSelection from inside the other pasteSelection method, which will already have checked it. Because of that the default value is false.

Organizes comments as well.

* Separates methods for the actions on selections

Now the remove, copy, cut, paste and toggle mute actions have a separate method for applying them to selections, which are then called from the contextMenuAction method. That made the code more organized and the contextMenuAction method smaller.

Also, the mouse shortcuts for muting and removing (CTRL+middle button, middle button, CTRL+right button) now apply the action on selections as well.

* Fixes small bug and reorganize code

Fixes a small bug where using a mouse shortcut or choosing an action on a TCO that is not selected while other TCOs were selected would result in the selection being affected.

Also reorganizes the code so the conditional for choosing between the selection action and the individual action stays inside the method.

* Move logic to the action methods

Since the methods that called the action+Selection() methods didn't need the list of selectableObjects, I moved it to the inside of the action+Selection() methods and removed the parameter from them.

* Changes logic structure and labels

As suggested by Spekular, the logic structure was changed. Now, the mousePressEvent and contextMenuAction methods determine whether the action should happen to a selection of TCOs or an individual TCO. The list of TCOs to be affected populate a QVector list called "active", which is parsed to the action method that will apply the action to each object in the list.

I changed the method names to removeActive, cutActive, copyActive and toggleMuteActive, since I believe that better describe the behavior. The paste method is still called pasteSelection for now, because the paste behavior isn't related to the active TCOs but to the content of the clipboard.

The contextMenuEvent method on both src/core/Track.cpp and src/tracks/SampleTrack.cpp were changed so they also check if the right-clicked TCO is part of a selection or an individual TCO, and the labels for the actions are changed to better describe the behavior (i.e.: "Delete" for individual TCO and "Delete selection" for multiple TCOs).

* Make removeActive and toggleMuteActive static

removeActive and toggleMuteActive methods are now static so they can be called from anywhere in the code since they don't require a TCO view instance to work. That makes it possible for them to be used in the future if any feature requires this type of action to be called from out of a TCO view instance.

The same couldn't be done for the copyActive and cutActive methods because those require an instance of the TCO view to call them, since when copying to the clipboard some metadata is written using information from the object instance.

* Renamed TCO View paste method

I renamed the TCO View paste method from pasteSelection to just paste, since the TCO view doesn't currently have a paste method (only the TCO class). It's also a name that accurately describes the action: it will paste either a group of TCOVs or a single TCOV on the current TCOV.

I also moved the logic for deciding between the multiple TCOV paste and single TCOV paste inside the paste method.

* Moves repeated code to a new method

This commit adds another method to TrackContentObjectView called getClickedTCOs, which will return a QVector with the TCO views that are supposed to be affected by a context menu action (either the individual right-clicked TCO or the selection of TCOs). Code was updated on the other methods to make use of this new method.

Method names for actions that affect multiple TCOs were changed. Instead of calling them copyActive, cutActive, toggleMuteActive and removeActive, they are just called copy, cut, toggleMute and remove, hence they are overloaded methods for those actions that affect multiple TCOs (their differenciation is the arguments list, which is a QVector list for those).

* Avoid unnecessary calls to getClickedTCOs()

We use a ternary operator inside TrackContentObjectView::mousePressEvent to avoid unnecessary calls to getClickedTCOs when the list is not going to be used.

The contextMenuEvent method on both Track.cpp and SampleTrack.cpp was reformated to use a more appropriate indentation and spacing between method calls.

* Fix indenting in a ternary operator assignment

* Enable mixer color-coding (#5589)

* Enable mixer color-coding

* Cleanup

* Fix warnings

* Improvements

* Improvements

* Use ColorChooser instead of QColorDialog

* Fix default palette being out of range

* Remove a redundant function

* Rename and make stuff efficient

* Comment on the code

* Make things more efficient

* Fix breaking builds

* Improvements

* Improvements pt. 2

* Improvements pt. 3

* Improvements pt. 4

* Improvements pt. 5

* Apply suggestions from code review

Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>

Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>

* Replace iterator where possible

* Revert "Replace iterator where possible"

This reverts commit 2fe06c8f3c849a0d8ce56910e66a1c9b85d3a460.

* Center vertical scroll position when opening the Automation Editor (#5123)

* Center vertical scroll position when opening the Automation Editor

* Change the background color of the selected text in a text box. (#5628)

* Change the background color of the selected text in a text box.
The new background color matches the green background of selected items in a tree view.

* Add selection-background-color for QLineEdit widgets in the classic theme, but keep the color as it was.

* Fix for Icons and comboboxes mismatch in arpeggiator in Instrument Editor #5494 (#5623)

* Fix for Icons and comboboxes mismatch in arpeggiator in Instrument Editor #5494
(https://github.com/LMMS/lmms/issues/5494)

Introduce a static const int variable for the default height of a ComboBox.
Set this height already in the constructor of the ComboBox object.
Update all modules setting the height of a ComboBox object to make use of the new constant.

* Replace 'const int' by 'constexpr int' after review.

* Don't use dialogs and message boxes on CLI import

Fix crash on CLI import if any error occurs.

* VST: improve usability on headless mode

* Plugin: add loadPluginPresetFile() to allow loading .fxp file easily
* VstPlugin: decouple file selection from openPreset and savePreset

TODO: add savePluginPresetFile() as well?

* Replace -e flag for CLI import with new --save-as

* Add JsonDataFile class for JSON data file support

* Make ImportFilter::tryImport() accept JSON-based setting object

* Allow passing import configuraion via command line

* Support MIDI CC events inside LMMS (cherry-picked from 5581)

* [WIP] MIDI import: implement various settings

* TEMPORARY: allow importing multiple files at once

* Allow rendering right after importing

* RemoteVstPlugin: fix failing message window creation without X server

* RemotePlugin::init(): retry on poll() failures

I don't know why, but poll() sometimes fails on the first attempt
and then success on the second attempt.

This commit handle such cases by blindly retrying.

* VstEffect: expose interfaces for loading plugin files and VST presets

* Add scripting plugin type

* main12

* Add MixSetup scripting plugin

* Fix render after import when a template project is given

* Add a plugin for audio mixing/mastering

* Allow rendering right after running script plugins

* Test: change the condition to route channels to master

* SampleTrack: Fix TCO not being played on the first tick (if it starts on
tick 0)

* Improve MidiImport

* Support separation by track
* Don't ignore tracks with port >= 16
* Fix ignoring track names in type 1 MIDI files

* MidiImport: support default mapping

* AudioMixMaster: support MIDI files as well

* Use rounded value for BPM instead of trunctaed one

* Refactor AudioMixMaster and support patch for master(incomplete)

* ConfigManager: use "tmp" for temporary data stroage

* MidiImport: add a way to override the target FX channel

* AudioMixMaster: use the right FX channel for MIDI files

* AudioMixMaster: Allow passing channel gain/panning

* PathUtil: fix using the working directory misleadingly

* AudioMixMaster: improve handling empty patches

* AudioMixMaster: wait for user-specified delay time to complete loading

* MidiImport: Fix note length with mixed note on/off events

* Refactor IPC and support per-instance VST sync

* AudioMixMaster: fix waiting time

* Fix negative offsets of MIDI note off events with sustain pedal

* Use rounding for volume-velocity conversion

* Use the default quality settings for GUI as the default for CLI as well

* Change audio quality before loading anything

* Fix POSIX IPC

* MidiImport: implement track caching(WIP)

* Export RenderManager for plugins

* AudioMixMaster: implement batch jobs

* MidiImport: set the song tempo with the value at t=0

* Don't split automations in MIDI import

* EffectChain: Start running when it is enabled

* AudioMixMaster: work around some broken Kontakt libraies

* Let MIDI instruments handle sustain pedal

* PR 템플릿 추가 (#1)

* [Plugin] 피치 오토메이션 수정 #2

* etc)컴파일 에러 수정

형변환으로 인한 컴파일 에러 수정
(형변환이 엄격한 컴파일러에서 에러가 발생)

* fea)midi 파일을 불러올때 미디파일 데이터 갱신하도록 수정

미디 파일 정보를 읽은 후 모든 Model 정보의 signal 함수(dataChanged)을 호출 하도록 수정

Co-authored-by: Lukas W <lukaswhl@gmail.com>
Co-authored-by: Noah Brecht <noahb2713@gmail.com>
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
Co-authored-by: Alexandre Almeida <wilsalx@gmail.com>
Co-authored-by: Cyp <cyp@wz2100.net>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: Shmuel H <shmuelhazan0@gmail.com>
Co-authored-by: Kevin Zander <veratil@gmail.com>
Co-authored-by: Andres <andresbb@gmail.com>
Co-authored-by: Hussam al-Homsi <sawuare@gmail.com>
Co-authored-by: nia <29542929+niacat@users.noreply.github.com>
Co-authored-by: Olivier Humbert <trebmuh@users.noreply.github.com>
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
Co-authored-by: Kapandaria <gnudles@users.noreply.github.com>
Co-authored-by: Martin Pavelek <he29.HS@gmail.com>
Co-authored-by: Cyp <48363+Cyp@users.noreply.github.com>
Co-authored-by: liushuyu <liushuyu011@gmail.com>
Co-authored-by: Johannes Lorenz <j.git@lorenz-ho.me>
Co-authored-by: Javier Serrano Polo <javier--IfwAyVwL9S8xJKrdU2QtlAdbjyPl9T@jasp.net>
Co-authored-by: Hye Sung Jung <hjung524@gmail.com>
Co-authored-by: tresf <tres.finocchiaro@gmail.com>
Co-authored-by: Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com>
Co-authored-by: Spekular <Spekularr@gmail.com>
Co-authored-by: Spekular <Spekular@users.noreply.github.com>
Co-authored-by: Muhammed Furkan USLU <mfurkanuslu@yandex.com>
Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>
Co-authored-by: tecknixia <50790262+tecknixia@users.noreply.github.com>
Co-authored-by: Oskar Wallgren <oskar.wallgren13@gmail.com>
Co-authored-by: akimaze <63190361+akimaze@users.noreply.github.com>
Co-authored-by: Andreas Müller <schnitzeltony@gmail.com>
Co-authored-by: thmueller64 <64359888+thmueller64@users.noreply.github.com>
Co-authored-by: Lost Robot <34612565+DouglasDGI@users.noreply.github.com>
Co-authored-by: Ibuki <main@fuwa.dev>
Co-authored-by: necrashter <iiilker99@gmail.com>
Co-authored-by: bahaokten <bahaokten@hotmail.com>
Co-authored-by: IanCaio <iancaio_dev@hotmail.com>
Co-authored-by: Raine M. Ekman <raine@iki.fi>
Co-authored-by: Luna Nooteboom <l.nooteboom@gmail.com>
Co-authored-by: Kumar <adityakumar4644@gmail.com>
Co-authored-by: Artur Twardowski <32247490+artur-twardowski@users.noreply.github.com>
Co-authored-by: LAMCILAK Theo <lamcilaktheo@gmail.com>
Co-authored-by: Claudius Ellsel <claudius.ellsel@live.de>
Co-authored-by: Stefano Bonicatti <smjert@gmail.com>
Co-authored-by: Rebecca DeField <rebeccadefield@gmail.com>
Co-authored-by: pmerry96 <60325403+pmerry96@users.noreply.github.com>
Co-authored-by: DigArtRoks <69391149+DigArtRoks@users.noreply.github.com>
Co-authored-by: SunWoong KIM <35526032+novdov@users.noreply.github.com>
sdasda7777 pushed a commit to sdasda7777/lmms that referenced this issue Jun 28, 2022
This PR fixes issues on systems where `QCursor::setPos()` has no effect
or is not reliable. These issues included knobs moving to fast on some
operating systems. Affected widgets are `Knob` and `LcdSpinBox`.

With this PR, on all operating systems, the `setPos` calls are removed and
the cursor is not hidden anymore, so the mouse keeps moving normally
when changing values of one of the widgets.

As now the previous pointer position keeps moving (instead of being reset
to the original position using `QCursor::setPos`), the mathematics that
translate pointer pixel distance to `Knob`/`LcdSpinBox` value increase
have to be changed:

* The `Knob` transition function is now linear and uses a new factor.
* `LcdSpinBox` now uses float values and saves the current float remainder
  (this is actually a separate issue revealed by this fix), leading to a fluent,
  non hanging movement.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants