13
0

Compare commits

...

5 Commits

Author SHA1 Message Date
0d160926c7
Merge branch 'ardour' 2024-07-17 17:47:19 +02:00
e175410f54 midi surfaces fixes (partially for PR #898)
1. do more to ensure that we do not call MidiSurface::begin_using_device()
multiple times without ::stop_using_device() in between. This reduces the risk
of duplicate signal handler connections being made (it might even eliminate it).

2. Notify all control surfaces when MIDI connectivity is established AND
disestablished. This gives them a chance to update their notion of their
current connection state. This can be important with JACK across zombification,
but also likely across backend stop&start.

These changes currntly only impact classes derived from MidiSurface but
something equivalent is required for all control surfaces
2024-07-16 11:12:41 -06:00
f8f6c89136 fix a likely logic error in GtkMenu handling of enter events
On macOS popping up a menu with a position function that leads the menu to be
under the mouse pointer generates the same initial set of enter events as on
linux, but this is then followed  by some leave events and then a repeat of the
same set of enter events.

this exposes what appears to be a logic error in gtk_menu_enter_notify().

Nonlinear enter events (i.e. where the menu pops up under the mouse, so the
mouse was never actually moved into the menu's window) should not cause a reset
of priv->seen_item_enter. This value, when true, is used to force the next
received button release event to be handle as an menu activation event. This
should only happen when the mouse has actually been moved by the user into the
menu (as already indicated in existing comments). The value has this effect by,
on the next enter event for a menu item, if already set, forcing
menu->activate_time to zero, which in turn will cause menu activation on button
up/release.

This bug doesn't appear on Linux (or Windows) because the event sequence
associated with a menu popup is different. The lack of another set of enter
events means that menu->activate_time is never reset, and so the behavior is as
expected.

This change makes the setting of priv->seen_item_enter be idempotent with
respect to non-linear enter events, which I believe is the intended behavior.
2024-07-15 11:09:59 -06:00
bd5e85780a
Hide region peak cursor when mouse leaves regions or canvas
Previously the cursor remained visible when moving the mouse
out of the canvas area.
2024-07-15 15:34:26 +02:00
b50477e608
Exclude monitor gain from mixer scenes 2024-07-15 00:43:51 +02:00
7 changed files with 43 additions and 17 deletions

View File

@ -72,7 +72,7 @@ class LIBARDOUR_API ControlProtocolManager : public PBD::Stateful, public ARDOUR
void set_session (Session*);
void discover_control_protocols ();
void foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)>);
void midi_connectivity_established ();
void midi_connectivity_established (bool);
void drop_protocols ();
void probe_midi_control_protocols ();
void probe_usb_control_protocols (bool, uint16_t, uint16_t);

View File

@ -619,12 +619,12 @@ ControlProtocolManager::instance ()
}
void
ControlProtocolManager::midi_connectivity_established ()
ControlProtocolManager::midi_connectivity_established (bool yn)
{
Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
(*p)->midi_connectivity_established ();
(*p)->midi_connectivity_established (yn);
}
}

View File

@ -357,7 +357,7 @@ Session::post_engine_init ()
* could start talking to surfaces if they want to.
*/
ControlProtocolManager::instance().midi_connectivity_established ();
ControlProtocolManager::instance().midi_connectivity_established (true);
if (_is_new && !no_auto_connect()) {
Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());

View File

@ -52,6 +52,7 @@
#include "ardour/automation_watch.h"
#include "ardour/butler.h"
#include "ardour/click.h"
#include "ardour/control_protocol_manager.h"
#include "ardour/debug.h"
#include "ardour/disk_reader.h"
#include "ardour/io_tasklist.h"
@ -1868,6 +1869,8 @@ Session::engine_halted ()
*/
realtime_stop (false, true);
ControlProtocolManager::instance().midi_connectivity_established (false);
}
void

View File

@ -57,7 +57,7 @@ public:
virtual int set_feedback (bool /*yn*/) { return 0; }
virtual bool get_feedback () const { return false; }
virtual void midi_connectivity_established () {}
virtual void midi_connectivity_established (bool) {}
virtual void stripable_selection_changed () = 0;

View File

@ -256,6 +256,8 @@ MIDISurface::connection_handler (std::weak_ptr<ARDOUR::Port>, std::string name1,
std::string ni = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (std::shared_ptr<ARDOUR::Port>(_async_in)->name());
std::string no = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (std::shared_ptr<ARDOUR::Port>(_async_out)->name());
int old_connection_state = _connection_state;
if (ni == name1 || ni == name2) {
if (yn) {
_connection_state |= InputConnected;
@ -277,23 +279,34 @@ MIDISurface::connection_handler (std::weak_ptr<ARDOUR::Port>, std::string name1,
DEBUG_TRACE (DEBUG::MIDISurface, string_compose ("our ports changed connection state: %1 -> %2 connected ? %3, connection state now %4\n",
name1, name2, yn, _connection_state));
if ((_connection_state & (InputConnected|OutputConnected)) == (InputConnected|OutputConnected)) {
/* it ought o be impossible for the connection state of our ports to
* change without a corresponding change in _connection_state. But
* since the consequences of calling device_acquire() and
* begin_using_device() are substantial, include it as a test to catch
* any weird corner cases.
*/
/* XXX this is a horrible hack. Without a short sleep here,
something prevents the device wakeup messages from being
sent and/or the responses from being received.
*/
if ((_connection_state != old_connection_state) && (_connection_state & (InputConnected|OutputConnected)) == (InputConnected|OutputConnected)) {
DEBUG_TRACE (DEBUG::MIDISurface, "device now connected for both input and output\n");
g_usleep (100000);
/* may not have the device open if it was just plugged
in. Really need USB device detection rather than MIDI port
detection for this to work well.
*/
if (!_in_use) {
device_acquire ();
begin_using_device ();
/* XXX this is a horrible hack. Without a short sleep here,
something prevents the device wakeup messages from being
sent and/or the responses from being received.
*/
g_usleep (100000);
/* may not have the device open if it was just plugged
in. Really need USB device detection rather than MIDI port
detection for this to work well.
*/
device_acquire ();
begin_using_device ();
}
} else {
DEBUG_TRACE (DEBUG::MIDISurface, "Device disconnected (input or output or both) or not yet fully connected\n");
@ -332,6 +345,15 @@ MIDISurface::write (MIDI::byte const * data, size_t size)
_output_port->write (data, size, 0);
}
void
MIDISurface::midi_connectivity_established (bool yn)
{
if (!yn) {
_connection_state = ConnectionState (0);
stop_using_device ();
}
}
bool
MIDISurface::midi_input_handler (IOCondition ioc, MIDI::Port* port)
{

View File

@ -85,6 +85,7 @@ class MIDISurface : public ARDOUR::ControlProtocol
CONTROL_PROTOCOL_THREADS_NEED_TEMPO_MAP_DECL();
virtual bool midi_input_handler (Glib::IOCondition ioc, MIDI::Port* port);
void midi_connectivity_established (bool);
protected:
bool with_pad_filter;