Compare commits

...

84 Commits

Author SHA1 Message Date
Paul Davis 5b5b67029d remove debug output 2024-04-13 16:03:01 -06:00
Paul Davis 1fd73ac184 display MIDI scene markers
Note: this commit is valid for Ardour as well as LiveTrax
2024-04-13 16:03:01 -06:00
Paul Davis c1b99b6521 some libardour support for MIDI scene support 2024-04-13 16:03:01 -06:00
Paul Davis 4f9ac9ed01 basics of the livetrax TC widget 2024-04-13 16:03:01 -06:00
Paul Davis 613ad32038 some basic but incomplete logic for track autoconnect in livetrax 2024-04-13 16:03:01 -06:00
Paul Davis 06295cbd51 fix reordering of newly added tracks in livetrax scenario 2024-04-13 16:03:01 -06:00
Paul Davis 8cdd4765d0 add and use simplified livetrax add tracks dialog 2024-04-13 16:03:01 -06:00
Paul Davis 28a6cf1649 add a channel mask to AudioBackend
This can be used to identify channels not to be used during
auto-connect, particularly for livetrax
2024-04-13 16:03:01 -06:00
Paul Davis 0892cd9c6e some tweaks to get initial state of gain controls for virtual soundccheck correct 2024-04-13 16:03:01 -06:00
Paul Davis 08576d45b4 for livetrax, use a knob for panning
While we're here, cleanup PannerUI initialization and some whitespace/brace issues.

Note: the knob does not yet actually control panning at all yet (not clear why)
2024-04-13 16:03:01 -06:00
Paul Davis 789da93b10 better GUI handling of virtual soundcheck 2024-04-13 16:03:01 -06:00
Paul Davis 93dc771edf better libardour infrastructure for virtual soundcheck 2024-04-13 16:03:01 -06:00
Paul Davis 902c87da48 GUI steps for virtual soundcheck 2024-04-13 16:03:01 -06:00
Paul Davis faafdfef2c libardour infrastructure for virtual soundcheck 2024-04-13 16:03:01 -06:00
Paul Davis 4b3fee8f02 fix restore of master send from XML 2024-04-13 16:03:01 -06:00
Paul Davis 2d01f72dd3 fix missing conditions in Route:is_internal_processor() to cover master send 2024-04-13 16:03:01 -06:00
Paul Davis 8020115693 most of the mechanism for livetrax signal routing via as master send 2024-04-13 16:03:01 -06:00
Paul Davis fcda89f458 MasterSend IS-A send for Delivery purposes 2024-04-13 16:03:01 -06:00
Paul Davis 29a0f62594 don't set monitor_out for livetrax 2024-04-13 16:03:01 -06:00
Paul Davis 3fc51fa85a for livetrax, Route::panner{._panner_shell}() should not use the Route's own 2024-04-13 16:03:01 -06:00
Paul Davis a7fd69e1ec NO-OP: move Route::remove_monitor_send() to be near ::enable_monitor_send() 2024-04-13 16:03:01 -06:00
Paul Davis 5e61f58bb8 when positioning master send in processor list, use cheaper conditional than is_track() 2024-04-13 16:03:01 -06:00
Paul Davis 294b0af5fa don't bother asking for a monitor section if livetrax 2024-04-13 16:03:01 -06:00
Paul Davis 75246407d2 master send uses _role == MasterSend, not _role == Aux 2024-04-13 16:03:01 -06:00
Paul Davis 9c60ad18a3 MasterSend is a type of (aux) send 2024-04-13 16:03:01 -06:00
Paul Davis e0b8f583fc make send return a sensible name if it is a MasterSend 2024-04-13 16:03:01 -06:00
Paul Davis 2b21898ac7 auto-fication of a loop in InternalReturn 2024-04-13 16:03:01 -06:00
Paul Davis 6217f8d338 internal sends in livetrax are never linked to the Route panner
Note: this could discriminate based on _role == MasterSend, but
livetrax doesn't allow any other type of internal send anyway.
2024-04-13 16:03:01 -06:00
Paul Davis e272e3b360 NO-OP: add space before bracket 2024-04-13 16:03:01 -06:00
Paul Davis 7cb3b04115 NO-OP: linebeeak removed 2024-04-13 16:03:01 -06:00
Paul Davis fe5491ef5a no monitor section for livetrax plus minor code rearrangement 2024-04-13 16:03:01 -06:00
Paul Davis bacd33db07 more crash avoidance in sfdb UI if there's no auditioner 2024-04-13 16:03:01 -06:00
Paul Davis b918933a1e sfdb UI should not crash if there's no auditioner 2024-04-13 16:03:01 -06:00
Paul Davis eedf806734 NO-OP: fix space near braces/brackets 2024-04-13 16:03:01 -06:00
Paul Davis 108f30b0c6 sfdb_ui should be smart if there's no auditioner 2024-04-13 16:03:01 -06:00
Paul Davis 0b76039174 port group display should not crash if there's no auditioner 2024-04-13 16:03:01 -06:00
Paul Davis 8014d3f794 panner UI in mixer should leave choice of panner shell & panner to Route 2024-04-13 16:03:01 -06:00
Paul Davis 0ac7c4614c no plugins in MixerUI for livetrax 2024-04-13 16:03:01 -06:00
Paul Davis c2f8f3606f no crash if instrument selector has no _instrument_list 2024-04-13 16:03:01 -06:00
Paul Davis 0b844b2220 do not save or restore tabbable state for livetrax 2024-04-13 16:03:01 -06:00
Paul Davis 86e5a9a38f add some enums and rc vars related to master send/return design 2024-04-13 16:03:01 -06:00
Paul Davis 2b8a4b885e no context menus for solo, mute, rec-enable with livetrax 2024-04-13 16:03:01 -06:00
Paul Davis 5489e83c14 remove debug output 2024-04-13 16:03:01 -06:00
Paul Davis 2e5f7f65a1 functional file format dropdown UI 2024-04-13 16:03:01 -06:00
Paul Davis 42c4b572d6 change design for doing "both" file format changes at once 2024-04-13 16:03:01 -06:00
Paul Davis 8ee0626fc4 library infrastructure for changing both aspects of audio file format at once 2024-04-13 16:03:01 -06:00
Paul Davis 8a9909c9c9 no region gain line for livetrax 2024-04-13 16:03:01 -06:00
Paul Davis 01e3887eb9 no plugin-related GUI elements (and no editor notebook) for livetrax 2024-04-13 16:03:01 -06:00
Paul Davis c1f2007351 no fleshed out plugin manager for livetrax 2024-04-13 16:03:01 -06:00
Paul Davis 77338aaace no auditioner for livetrax 2024-04-13 16:03:01 -06:00
Paul Davis e82b6e6b98 NO-OP indentation fix 2024-04-13 16:03:01 -06:00
Paul Davis b029eacb19 remove fade handles for livetrax 2024-04-13 16:03:01 -06:00
Paul Davis f0eb3ba7c8 define actions to control livetrax section visibility 2024-04-13 16:03:01 -06:00
Paul Davis a97e646fcb attach bindings to boxes in livetrax view, and steal focus appropriately 2024-04-13 16:03:01 -06:00
Paul Davis b1da985fbe initial work on livetrax all-mono, direct outs and send-to-(master/monitor?) GUI edition 2024-04-13 16:03:01 -06:00
Paul Davis 309e277525 initial work on livetrax all-mono, direct outs and send-to-(master/monitor?) 2024-04-13 16:03:00 -06:00
Paul Davis b8952c771d continuing tweaks for livetrax 2024-04-13 16:03:00 -06:00
Paul Davis c1cc3f613c working input meters, among other improvements for livetrax 2024-04-13 16:03:00 -06:00
Paul Davis b28a202a2b don't compute scope info for livetrax (never displayed) 2024-04-13 16:03:00 -06:00
Paul Davis 974d1eca5a work on livetrax continues 2024-04-13 16:03:00 -06:00
Paul Davis 5bd50b87bd remove over-wide meter hack 2024-04-13 16:03:00 -06:00
Paul Davis 3b23c0b238 more work on livetrax layout 2024-04-13 16:03:00 -06:00
Paul Davis b1ce56088b NOOP: reformat and reflow 2024-04-13 16:03:00 -06:00
Paul Davis fba1381e2e initial work on livetrax 2024-04-13 16:03:00 -06:00
Paul Davis 6c1e66bb70 add a new Profile flag for livetrax 2024-04-13 16:03:00 -06:00
Paul Davis cfa80f2c6d allow true boxy buttons for ArdourButtons
Also add a default tweaks static member to force all buttons to a given tweak state
2024-04-13 16:03:00 -06:00
Paul Davis 042cb79e79 add unrounded rectangle methods to Gtkmm2ext for use in truly boxy buttons 2024-04-13 16:03:00 -06:00
Paul Davis dde59c8e4c temporary fix for X Window and Windows bad canvas drawing with no single expose 2024-04-12 18:55:27 -06:00
Paul Davis 1eb2a345df prevent flickering of snapped cursor during drags when it should be invisible 2024-04-12 18:54:52 -06:00
Paul Davis e7b3b61dbc fix bad redraws caused by TrackingText on canvas
Probably Item::set_position() should call Item::set_bbox_dirty() but
this will do as a first pass at that
2024-04-12 18:50:03 -06:00
Robin Gareus ab1299da87
We're behind the times 2024-04-13 00:54:52 +02:00
Robin Gareus 44610c7877
Fix RCU race condition (see source for details) 2024-04-12 00:26:51 +02:00
Robin Gareus 96e83f4101
Semicolon to the rescue 2024-04-11 23:42:13 +02:00
Robin Gareus b8c474ff32
Add support for splash screen image transparency 2024-04-11 19:42:14 +02:00
Robin Gareus a69ca86944
Fix inline controls allow for inverted range
Some controls (notably pan azimuth) have reversed range 1..0.
Support for this was added years ago in 647103c825
but inline controls were not updated.
2024-04-11 19:41:14 +02:00
Robin Gareus fe7fd146aa macOS: fix crash when trying to enter fullscreen while already in fullscreen
YDK2 uses SetSystemUIMode() for fullscreen. This also uses space
otherwise reserved for the menu bar at the top, and is apparently
preferable for Ardour's UI.

However when a user manually enters fullscreen using the window
title-bar's green button (NSWindow toggleFullScreen). YDK will crash
when the user then also tries to use YDK's fullscreen mode:

```
NSWindowStyleMaskFullScreen cleared on a window outside of a full screen transition.
called from
  [NSWindow setStyleMask:]
  gdk_window_set_decorations
  gdk_window_fullscreen
```

Ideally we'd set NSApp presentation flags so that the toplevel window
would allow one to zoom (maximize), but not to enter fullscreen. Like it
used to be on OSX. It is unclear how to achieve this on macOS for
resizable windows, short of marking the top-level window a dialog or
utility window.
2024-04-10 20:41:49 +02:00
Robin Gareus 6b3fbefd26
Revert "Debug AVX512f crashes"
This reverts commit 0eed49b48e.
2024-04-10 15:44:40 +02:00
Robin Gareus 0eed49b48e
Debug AVX512f crashes 2024-04-10 03:22:05 +02:00
Robin Gareus 3d375f12ed
NOOP: whitespace 2024-04-10 03:10:43 +02:00
Robin Gareus d023ea0d77
Fix potential memory corruption in AVX512f DSP 2024-04-10 03:09:27 +02:00
Robin Gareus 8a7d92f196
Fix MonotorProc's channel_solo_control
Previously only ::set_solo() worked. Directly using the
controllable did not update `solo_cnt` and other channels
were not muted.
2024-04-09 22:02:31 +02:00
Robin Gareus cde26c5205
Set default time domain to Audiotime to sidestep various MusicTime issues 2024-04-09 18:36:43 +02:00
Robin Gareus ecd22e9aa8 Remove call to deprecated userSpaceScaleFactor
userSpaceScaleFactor is a missing symbol on some recent versions of macOS.
2024-04-09 06:06:58 +02:00
Robin Gareus 826103f08c
Pitch bend is not unreasonable 2024-04-09 02:10:19 +02:00
85 changed files with 2426 additions and 605 deletions

View File

@ -641,7 +641,7 @@ About::About ()
#endif
set_translator_credits (t);
set_copyright (_("Copyright (C) 1999-2023 Paul Davis\n"));
set_copyright (_("Copyright (C) 1999-2024 Paul Davis\n"));
set_license (gpl);
set_name (X_("Ardour"));
set_website (X_("https://ardour.org/"));

View File

@ -627,7 +627,11 @@ AddRouteDialog::maybe_update_name_template_entry ()
switch (type_wanted()) {
case AudioTrack:
name_template_entry.set_text (_("Audio"));
if (Profile->get_livetrax()) {
name_template_entry.set_text (_("Track"));
} else {
name_template_entry.set_text (_("Audio"));
}
break;
case MidiTrack:
/* set name of instrument or _("MIDI") */

View File

@ -553,6 +553,7 @@
<menuitem action="toggle-arrangement-ruler"/>
<menuitem action="toggle-marker-ruler"/>
<menuitem action="toggle-cue-marker-ruler"/>
<menuitem action="toggle-scene-marker-ruler"/>
<separator/>
<menuitem action="toggle-video-ruler"/>
</menu>
@ -805,6 +806,7 @@
<menuitem action="toggle-cd-marker-ruler"/>
<menuitem action="toggle-marker-ruler"/>
<menuitem action="toggle-cue-marker-ruler"/>
<menuitem action="toggle-scene-marker-ruler"/>
<separator/>
<menuitem action="toggle-video-ruler"/>
</popup>

View File

@ -151,6 +151,7 @@
#include "keyboard.h"
#include "keyeditor.h"
#include "library_download_dialog.h"
#include "livetrax_add_track_dialog.h"
#include "location_ui.h"
#include "lua_script_manager.h"
#include "luawindow.h"
@ -339,6 +340,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
, plugin_dsp_load_window (X_("plugin-dsp-load"), _("Plugin DSP Load"))
, dsp_statistics_window (X_("dsp-statistics"), _("Performance Meters"))
, transport_masters_window (X_("transport-masters"), _("Transport Masters"))
, livetrax_track_dialog (nullptr)
, session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this))
, add_video_dialog (X_("add-video"), _("Add Video"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this))
, bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
@ -1254,13 +1256,22 @@ ARDOUR_UI::set_fps_timeout_connection ()
void
ARDOUR_UI::update_sample_rate ()
{
std::string label = string_compose (X_("<span weight=\"ultralight\">%1</span>:"), _("Audio"));
std::string label;
if (!Profile->get_livetrax()) {
label = string_compose (X_("<span weight=\"ultralight\">%1</span>:"), _("Audio"));
}
ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
if (!AudioEngine::instance()->running()) {
sample_rate_label.set_markup (label + _("none"));
if (Profile->get_livetrax()) {
livetrax_sr_button->set_text (_("Stopped"), true);
} else {
const std::string str (label + _("none"));
sample_rate_label.set_markup (str);
}
} else {
@ -1269,14 +1280,23 @@ ARDOUR_UI::update_sample_rate ()
if (rate == 0) {
/* no sample rate available */
sample_rate_label.set_markup (label + _("none"));
if (Profile->get_livetrax()) {
livetrax_sr_button->set_text (_("Unknown"), true);
} else {
sample_rate_label.set_markup (label + _("none"));
}
} else {
char buf[64];
snprintf (buf, sizeof (buf), "%4.1f", (AudioEngine::instance()->usecs_per_cycle() / 1000.0f));
const char* const bg = (_session && _session->nominal_sample_rate () != rate) ? " background=\"red\" foreground=\"white\"" : "";
sample_rate_label.set_markup (string_compose ("%1 <span%2>%3</span> %4 %5", label, bg, ARDOUR_UI_UTILS::rate_as_string (rate), buf, _("ms")));
const std::string str (string_compose ("%1 <span%2>%3</span> %4 %5", label, bg, ARDOUR_UI_UTILS::rate_as_string (rate), buf, _("ms")));
sample_rate_label.set_markup (str);
if (Profile->get_livetrax()) {
livetrax_sr_button->set_text (str, true);
}
}
}
@ -1341,6 +1361,42 @@ ARDOUR_UI::update_format ()
}
format_label.set_markup (s.str ());
if (Profile->get_livetrax()) {
s.str ("");
s.clear ();
/* LiveTrax only allows a very limited set of options */
/* This looks like we could just unconditionally add "24bit" to
* the string, but this logic allows us to potentially detect
* logic glitches where somehow we end up with a different
* format.
*/
switch (_session->config.get_native_file_data_format ()) {
case FormatInt24:
s << _("24 bit");
break;
default:
break;
}
s << ' ';
switch (_session->config.get_native_file_header_format ()) {
case RF64_WAV:
s << _("WAV/RF64");
break;
case FLAC:
s << _("FLAC");
default:
break;
}
livetrax_ff_dropdown->set_active (s.str());
}
}
void
@ -2809,6 +2865,16 @@ ARDOUR_UI::add_route ()
return;
}
if (Profile->get_livetrax()) {
if (!livetrax_track_dialog) {
livetrax_track_dialog = new LiveTraxAddTrackDialog;
livetrax_track_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_response));
}
livetrax_track_dialog->set_position (WIN_POS_MOUSE);
livetrax_track_dialog->present ();
return;
}
if (!add_route_dialog.get (false)) {
add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_response));
}
@ -2830,6 +2896,15 @@ ARDOUR_UI::add_route_dialog_response (int r)
return;
}
if (Profile->get_livetrax()) {
if (r == RESPONSE_OK) {
int nchan = livetrax_track_dialog->stereo() ? 2 : 1;
session_add_audio_route (true, nchan, nchan, ARDOUR::Normal, nullptr, livetrax_track_dialog->num_tracks(), string(), false, PresentationInfo::max_order, false);
}
livetrax_track_dialog->hide ();
return;
}
if (!AudioEngine::instance()->running ()) {
switch (r) {
case AddRouteDialog::Add:
@ -2916,7 +2991,7 @@ ARDOUR_UI::add_route_dialog_response (int r)
}
}
if (oac & AutoConnectMaster) {
if (!Profile->get_livetrax() && (oac & AutoConnectMaster)) {
output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
output_chan.set (DataType::MIDI, 0);
} else {
@ -3197,3 +3272,13 @@ ARDOUR_UI::stop_cues (int col, bool immediately)
_basic_ui->trigger_stop_col (col, immediately);
}
void
ARDOUR_UI::open_media_folder ()
{
if (!_session) {
return;
}
PBD::open_folder (_session->session_directory().sound_path());
}

View File

@ -176,6 +176,8 @@ class NSM_Client;
class LevelMeterHBox;
class GUIObjectState;
class BasicUI;
class LiveTraxMeters;
class LiveTraxAddTrackDialog;
namespace ARDOUR {
class ControlProtocolInfo;
@ -220,6 +222,7 @@ public:
void launch_howto_report ();
void show_about ();
void hide_about ();
void open_media_folder ();
void load_from_application_api (const std::string& path);
void finish();
@ -403,6 +406,14 @@ public:
void gui_idle_handler ();
enum LiveTraxVisibility {
LiveTraxEditorVisible = 0x1,
LiveTraxMixerVisible = 0x2,
LiveTraxMeterVisible = 0x4,
};
void livetrax_toggle_visibility (LiveTraxVisibility);
protected:
friend class PublicEditor;
@ -460,6 +471,7 @@ private:
int setup_windows ();
void apply_window_settings (bool);
void connect_transport_elements ();
void setup_transport ();
void setup_clock ();
@ -486,6 +498,7 @@ private:
void update_autosave();
sigc::connection _autosave_connection;
void virtual_soundcheck_changed (bool);
void session_dirty_changed ();
void update_title ();
@ -620,6 +633,29 @@ private:
void primary_clock_value_changed ();
void secondary_clock_value_changed ();
/* LiveTrax */
Gtk::HBox livetrax_top_bar;
Gtk::HBox livetrax_transport_bar;
Gtk::HBox livetrax_meter_bar;
Gtk::HBox livetrax_editor_bar;
Gtk::HBox livetrax_mixer_bar;
TimeInfoBox* livetrax_time_info_box;
ArdourWidgets::ArdourButton* livetrax_multi_out_button;
ArdourWidgets::ArdourButton* livetrax_stereo_out_button;
ArdourWidgets::ArdourButton* livetrax_meter_view_button;
ArdourWidgets::ArdourButton* livetrax_editor_view_button;
ArdourWidgets::ArdourButton* livetrax_mixer_view_button;
ArdourWidgets::ArdourButton* livetrax_lock_button;
ArdourWidgets::ArdourButton* livetrax_view_in_folder_button;
ArdourWidgets::ArdourDropdown* livetrax_ff_dropdown;
ArdourWidgets::ArdourButton* livetrax_sr_button;
Gtk::HScrollbar* livetrax_edit_hscrollbar;
Gtk::VScrollbar* livetrax_edit_vscrollbar;
Gtk::HScrollbar* livetrax_mix_hscrollbar;
LiveTraxMeters* livetrax_meters;
int livetrax_setup_windows ();
/* menu bar and associated stuff */
Gtk::MenuBar* menu_bar;
@ -759,6 +795,8 @@ private:
WM::Proxy<DspStatisticsWindow> dsp_statistics_window;
WM::Proxy<TransportMastersWindow> transport_masters_window;
LiveTraxAddTrackDialog* livetrax_track_dialog;
/* Windows/Dialogs that require a creator method */
WM::ProxyWithConstructor<SessionOptionEditor> session_option_editor;
@ -846,6 +884,8 @@ private:
void toggle_send_mmc ();
void toggle_send_mtc ();
void toggle_send_midi_clock ();
void disable_virtual_soundcheck ();
void enable_virtual_soundcheck ();
void toggle_use_osc ();
@ -954,6 +994,11 @@ private:
bool nsm_first_session_opened;
PBD::ScopedConnectionList clock_state_connection;
LiveTraxVisibility _livetrax_visibility;
void livetrax_visibility_change ();
void livetrax_set_file_format (ARDOUR::LiveTraxFileFormat const &);
};
#endif /* __ardour_gui_h__ */

View File

@ -317,7 +317,7 @@ ARDOUR_UI::update_clock_visibility ()
}
void
ARDOUR_UI::setup_transport ()
ARDOUR_UI::connect_transport_elements ()
{
RefPtr<Action> act;
/* setup actions */
@ -360,6 +360,11 @@ ARDOUR_UI::setup_transport ()
act = ActionManager::get_action (X_("Monitor Section"), X_("monitor-cut-all"));
monitor_mute_button.set_related_action (act);
if (Profile->get_livetrax()) {
act = ActionManager::get_action (X_("Common"), X_("open-media-folder"));
livetrax_view_in_folder_button->set_related_action (act);
}
act = ActionManager::get_action ("Main", "ToggleLatencyCompensation");
latency_disable_button.set_related_action (act);
@ -375,6 +380,12 @@ ARDOUR_UI::setup_transport ()
secondary_clock->ValueChanged.connect (sigc::mem_fun(*this, &ARDOUR_UI::secondary_clock_value_changed));
secondary_clock->change_display_delta_mode_signal.connect (sigc::mem_fun(UIConfiguration::instance(), &UIConfiguration::set_secondary_clock_delta_mode));
big_clock->ValueChanged.connect (sigc::mem_fun(*this, &ARDOUR_UI::big_clock_value_changed));
}
void
ARDOUR_UI::setup_transport ()
{
connect_transport_elements ();
editor_visibility_button.signal_drag_failed().connect (sigc::bind (sigc::ptr_fun (drag_failed), editor));
mixer_visibility_button.signal_drag_failed().connect (sigc::bind (sigc::ptr_fun (drag_failed), mixer));
@ -1060,4 +1071,3 @@ ARDOUR_UI::update_title ()
}
snapshot_name_label.set_markup (snap_label.str());
}

View File

@ -36,9 +36,12 @@
#include "ardour/session.h"
#include "ardour/lv2_plugin.h"
#include "ardour/profile.h"
#include "gtkmm2ext/bindings.h"
#include "widgets/ardour_button.h"
#include "actions.h"
#include "ardour_message.h"
#include "ardour_ui.h"
@ -47,6 +50,10 @@
#include "meterbridge.h"
#include "luainstance.h"
#include "luawindow.h"
#include "livetrax_meters.h"
#include "livetrax_tc_widget.h"
#include "main_clock.h"
#include "meterbridge.h"
#include "mixer_ui.h"
#include "recorder_ui.h"
#include "trigger_page.h"
@ -54,6 +61,7 @@
#include "keyeditor.h"
#include "rc_option_editor.h"
#include "route_params_ui.h"
#include "selection_properties_box.h"
#include "time_info_box.h"
#include "trigger_ui.h"
#include "step_entry.h"
@ -67,6 +75,7 @@
using namespace Gtk;
using namespace PBD;
using namespace ArdourWidgets;
namespace ARDOUR {
class Session;
@ -130,9 +139,14 @@ ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
editor->set_session (s);
BootMessage (_("Setup Mixer"));
mixer->set_session (s);
recorder->set_session (s);
trigger_page->set_session (s);
meterbridge->set_session (s);
if (!Profile->get_livetrax()) {
recorder->set_session (s);
trigger_page->set_session (s);
meterbridge->set_session (s);
} else {
livetrax_time_info_box->set_session (s);
}
/* its safe to do this now */
@ -249,11 +263,16 @@ tab_window_root_drop (GtkNotebook* src,
int
ARDOUR_UI::setup_windows ()
{
if (ARDOUR::Profile->get_livetrax()) {
return livetrax_setup_windows ();
}
_tabs.set_show_border(false);
_tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch));
_tabs.signal_page_added().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_added));
_tabs.signal_page_removed().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_removed));
rc_option_editor = new RCOptionEditor;
rc_option_editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
@ -360,6 +379,182 @@ ARDOUR_UI::setup_windows ()
return 0;
}
int
ARDOUR_UI::livetrax_setup_windows ()
{
using namespace Menu_Helpers;
using namespace Gtk;
ArdourButton::set_default_tweaks (ArdourButton::Tweaks (ArdourButton::ForceBoxy|ArdourButton::ForceFlat));
if (create_editor()) {
error << _("UI: cannot setup editor") << endmsg;
return -1;
}
if (create_mixer()) {
error << _("UI: cannot setup mixer") << endmsg;
return -1;
}
livetrax_time_info_box = new TimeInfoBox ("LiveTraxTimeInfo", false);
Image* icon = manage (new Image (ARDOUR_UI_UTILS::get_icon ("allenheath")));
VBox* vb;
HBox* hb;
ArdourButton::Element elements (ArdourButton::Element (ArdourButton::Text|ArdourButton::VectorIcon));
Gtkmm2ext::Bindings* bindings;
Glib::RefPtr<Action> act;
livetrax_top_bar.set_spacing (12);
livetrax_top_bar.set_border_width (12);
livetrax_top_bar.pack_start (*icon, false, false);
livetrax_top_bar.pack_start (*livetrax_time_info_box, false, false);
livetrax_top_bar.pack_start (*primary_clock, false, false);
EventBox* ev_dsp = manage (new EventBox);
EventBox* ev_timecode = manage (new EventBox);
ev_dsp->set_name ("MainMenuBar");
ev_timecode->set_name ("MainMenuBar");
ev_dsp->add (dsp_load_label);
ev_timecode->add (timecode_format_label);
livetrax_ff_dropdown = manage (new ArdourDropdown ());
Menu_Helpers::MenuList& items (livetrax_ff_dropdown->items());
items.push_back (MenuElem (_("24 bit WAV/RF64"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::livetrax_set_file_format), LiveTraxFileFormat (ARDOUR::FormatInt24, ARDOUR::RF64_WAV))));
items.push_back (MenuElem (_("24 bit FLAC"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::livetrax_set_file_format), LiveTraxFileFormat (ARDOUR::FormatInt24, ARDOUR::FLAC))));
livetrax_sr_button = manage (new ArdourButton (""));
vb = manage (new VBox);
vb->pack_start (*livetrax_ff_dropdown, false, false);
vb->pack_start (*livetrax_sr_button, false, false);
livetrax_top_bar.pack_start (*vb, false, false);
CairoWidget* cw = new LiveTraxTCWidget;
cw->show ();
livetrax_top_bar.pack_start (*cw, false, false);
vb = manage (new VBox);
vb->pack_start (*ev_dsp, true, true);
vb->pack_start (disk_space_label, true, true);
vb->show_all ();
livetrax_top_bar.pack_end (*vb, false, false);
livetrax_multi_out_button = manage (new ArdourButton (_("Multi Out")));
livetrax_stereo_out_button = manage (new ArdourButton (_("Stereo Out")));
act = ActionManager::get_action (X_("Common"), X_("disable-virtual-soundcheck"));
livetrax_stereo_out_button->set_related_action (act);
act = ActionManager::get_action (X_("Common"), X_("enable-virtual-soundcheck"));
livetrax_multi_out_button->set_related_action (act);
vb = manage (new VBox);
vb->pack_start (*livetrax_stereo_out_button, true, true);
vb->pack_start (*livetrax_multi_out_button, true, true);
vb->show_all ();
livetrax_top_bar.pack_end (*vb, false, false);
/* transport bar */
livetrax_meter_view_button = manage (new ArdourButton (_("METERS"), ArdourButton::Element (ArdourButton::Text|ArdourButton::Edge|ArdourButton::Body), true));;
act = ActionManager::get_action (X_("Common"), X_("livetrax-toggle-meter"));
livetrax_meter_view_button->set_related_action (act);
livetrax_mixer_view_button = manage (new ArdourButton (_("MIXER"), ArdourButton::Element (ArdourButton::Text|ArdourButton::Edge|ArdourButton::Body), true));
act = ActionManager::get_action (X_("Common"), X_("livetrax-toggle-mixer"));
livetrax_mixer_view_button->set_related_action (act);
livetrax_editor_view_button = manage (new ArdourButton (_("TRACKS"), ArdourButton::Element (ArdourButton::Text|ArdourButton::Edge|ArdourButton::Body), true));
act = ActionManager::get_action (X_("Common"), X_("livetrax-toggle-editor"));
livetrax_editor_view_button->set_related_action (act);
livetrax_transport_bar.pack_start (*livetrax_editor_view_button, false, false);
livetrax_transport_bar.pack_start (*livetrax_mixer_view_button, false, false);
livetrax_transport_bar.pack_start (*livetrax_meter_view_button, false, false);
hb = manage (new HBox);
hb->pack_start (transport_ctrl, false, false);
livetrax_lock_button = manage (new ArdourButton (_("Lock Icon"), elements));
editor->mouse_mode_hbox->pack_start (*livetrax_lock_button, false, false, 12);
livetrax_transport_bar.pack_start (*hb, true, false);
livetrax_transport_bar.pack_start (*editor->mouse_mode_hbox, true, false);
livetrax_view_in_folder_button = manage (new ArdourButton (_("MEDIA"), elements));
editor->_zoom_box.pack_start (*livetrax_view_in_folder_button, false, false, 12);
livetrax_transport_bar.pack_end (editor->_zoom_box, false, false);
livetrax_transport_bar.show_all ();
/* meter display */
livetrax_meters = manage (new LiveTraxMeters (48));
livetrax_meters->show_all ();
livetrax_meter_bar.set_border_width (12);
livetrax_meter_bar.pack_start (*livetrax_meters, true, true, 12);
hb = manage (new HBox);
livetrax_edit_vscrollbar = manage (new VScrollbar (editor->vertical_adjustment));
livetrax_edit_vscrollbar->show ();
hb->pack_start (editor->contents(), true, true);
hb->pack_start (*livetrax_edit_vscrollbar, false, false);
vb = manage (new VBox);
livetrax_edit_hscrollbar = manage (new HScrollbar (editor->horizontal_adjustment));
livetrax_edit_hscrollbar->show ();
vb->pack_start (*hb, true, true);
vb->pack_start (*livetrax_edit_hscrollbar, false, false);
livetrax_editor_bar.pack_start (*vb, true, true);
livetrax_mixer_bar.pack_start (mixer->contents(), true, true);
we_have_dependents ();
/* order of addition affects order seen in initial window display */
main_vpacker.pack_start (menu_bar_base, false, false);
main_vpacker.pack_start (livetrax_top_bar, false, false);
main_vpacker.pack_start (livetrax_transport_bar, false, false);
main_vpacker.pack_start (livetrax_meter_bar, false, false);
main_vpacker.pack_start (livetrax_editor_bar, true, true);
main_vpacker.pack_start (livetrax_mixer_bar, true, true);
connect_transport_elements ();
setup_tooltips ();
build_menu_bar ();
bindings = Bindings::get_bindings (X_("Editor"));
livetrax_editor_bar.set_data ("ardour-bindings", bindings);
bindings = Bindings::get_bindings (X_("Mixer"));
livetrax_mixer_bar.set_data ("ardour-bindings", bindings);
_livetrax_visibility = LiveTraxVisibility (LiveTraxMeterVisible|LiveTraxMixerVisible|LiveTraxEditorVisible);
livetrax_visibility_change ();
// setup_tooltips ();
_main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
/* pack the main vpacker into the main window and show everything
*/
_main_window.add (main_vpacker);
apply_window_settings (true);
setup_toplevel_window (_main_window, "", this);
_main_window.show_all ();
#ifdef GDK_WINDOWING_X11
/* allow externalUIs to be transient, on top of the main window */
LV2Plugin::set_main_window_id (GDK_DRAWABLE_XID(_main_window.get_window()->gobj()));
#endif
return 0;
}
void
ARDOUR_UI::apply_window_settings (bool with_size)
{
@ -482,3 +677,78 @@ ARDOUR_UI::action_script_changed (int i, const std::string& n)
}
KeyEditor::UpdateBindings ();
}
void
ARDOUR_UI::livetrax_visibility_change ()
{
if (_livetrax_visibility & LiveTraxMeterVisible) {
livetrax_meter_bar.show ();
livetrax_meter_view_button->set_active_state (Gtkmm2ext::ExplicitActive);
} else {
livetrax_meter_bar.hide ();
livetrax_meter_view_button->set_active_state (Gtkmm2ext::Off);
}
if (_livetrax_visibility & LiveTraxEditorVisible) {
livetrax_editor_bar.show ();
livetrax_editor_view_button->set_active_state (Gtkmm2ext::ExplicitActive);
} else {
livetrax_editor_bar.hide ();
livetrax_editor_view_button->set_active_state (Gtkmm2ext::Off);
}
if (_livetrax_visibility & LiveTraxMixerVisible) {
livetrax_mixer_bar.show ();
livetrax_mixer_view_button->set_active_state (Gtkmm2ext::ExplicitActive);
} else {
livetrax_mixer_bar.hide ();
livetrax_mixer_view_button->set_active_state (Gtkmm2ext::Off);
}
}
void
ARDOUR_UI::livetrax_toggle_visibility (LiveTraxVisibility v)
{
if (_livetrax_visibility & v) {
_livetrax_visibility = LiveTraxVisibility (_livetrax_visibility & ~v);
} else {
_livetrax_visibility = LiveTraxVisibility (_livetrax_visibility | v);
}
livetrax_visibility_change ();
}
void
ARDOUR_UI::livetrax_set_file_format (LiveTraxFileFormat const & ff)
{
if (!_session) {
return;
}
/* Don't reset write sources on header format change */
_session->disable_file_format_reset ();
_session->config.set_native_file_header_format (ff.hf);
_session->config.set_native_file_data_format (ff.sf);
_session->enable_file_format_reset ();
_session->reset_native_file_format ();
}
void
ARDOUR_UI::virtual_soundcheck_changed (bool onoff)
{
if (!Profile->get_livetrax()) {
return;
}
if (onoff) {
livetrax_stereo_out_button->set_active_state (Gtkmm2ext::Off);
livetrax_multi_out_button->set_active_state (Gtkmm2ext::ExplicitActive);
} else {
livetrax_stereo_out_button->set_active_state (Gtkmm2ext::ExplicitActive);
livetrax_multi_out_button->set_active_state (Gtkmm2ext::Off);
}
}

View File

@ -156,15 +156,18 @@ ARDOUR_UI::set_session (Session *s)
AutomationWatch::instance().set_session (s);
shuttle_box.set_session (s);
mini_timeline.set_session (s);
time_info_box->set_session (s);
primary_clock->set_session (s);
secondary_clock->set_session (s);
big_clock->set_session (s);
video_timeline->set_session (s);
rc_option_editor->set_session (s);
if (!Profile->get_livetrax()) {
shuttle_box.set_session (s);
mini_timeline.set_session (s);
time_info_box->set_session (s);
secondary_clock->set_session (s);
big_clock->set_session (s);
video_timeline->set_session (s);
rc_option_editor->set_session (s);
}
roll_controllable->set_session (s);
stop_controllable->set_session (s);
@ -206,6 +209,11 @@ ARDOUR_UI::set_session (Session *s)
_session->TransportStateChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::map_transport_state, this), gui_context());
_session->DirtyChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_dirty_changed, this), gui_context());
if (Profile->get_livetrax()) {
_session->VirtualSoundCheckChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::virtual_soundcheck_changed, this, _1), gui_context());
virtual_soundcheck_changed (_session->virtual_soundcheck());
}
_session->PunchLoopConstraintChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::set_punch_sensitivity, this), gui_context());
_session->auto_punch_location_changed.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::set_punch_sensitivity, this), gui_context ());

View File

@ -99,7 +99,9 @@ ARDOUR_UI::create_editor ()
{
try {
editor = new Editor ();
editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
if (!ARDOUR::Profile->get_livetrax()) {
editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
}
}
catch (failed_constructor& err) {
@ -116,7 +118,9 @@ ARDOUR_UI::create_recorder ()
{
try {
recorder = new RecorderUI ();
recorder->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
if (!ARDOUR::Profile->get_livetrax()) {
recorder->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
}
} catch (failed_constructor& err) {
return -1;
}
@ -128,7 +132,9 @@ ARDOUR_UI::create_trigger_page ()
{
try {
trigger_page = new TriggerPage ();
trigger_page->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
if (!ARDOUR::Profile->get_livetrax()) {
trigger_page->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
}
} catch (failed_constructor& err) {
return -1;
}
@ -280,6 +286,13 @@ ARDOUR_UI::install_actions ()
ActionManager::register_action (common_actions, X_("show-ui-prefs"), _("Show more UI preferences"), sigc::mem_fun (*this, &ARDOUR_UI::show_ui_prefs));
}
if (Profile->get_livetrax()) {
/* XXX should these be toggles? */
ActionManager::register_action (common_actions, X_("livetrax-toggle-meter"), _("Hide/Show Meters"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::livetrax_toggle_visibility), LiveTraxMeterVisible));
ActionManager::register_action (common_actions, X_("livetrax-toggle-mixer"), _("Hide/Show Mixer"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::livetrax_toggle_visibility), LiveTraxMixerVisible));
ActionManager::register_action (common_actions, X_("livetrax-toggle-editor"), _("Hide/Show Editor"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::livetrax_toggle_visibility), LiveTraxEditorVisible));
}
ActionManager::register_action (common_actions, X_("toggle-meterbridge"), S_("Window|Meterbridge"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_meterbridge));
act = ActionManager::register_action (common_actions, X_("NewMIDITracer"), _("MIDI Tracer"), sigc::mem_fun(*this, &ARDOUR_UI::new_midi_tracer_window));
@ -293,6 +306,7 @@ ARDOUR_UI::install_actions ()
ActionManager::register_action (common_actions, X_("website-dev"), _("Development"), mem_fun(*this, &ARDOUR_UI::launch_website_dev));
ActionManager::register_action (common_actions, X_("forums"), _("User Forums"), mem_fun(*this, &ARDOUR_UI::launch_forums));
ActionManager::register_action (common_actions, X_("howto-report"), _("How to Report a Bug"), mem_fun(*this, &ARDOUR_UI::launch_howto_report));
ActionManager::register_action (common_actions, X_("open-media-folder"), _("Open Media Folder"), mem_fun(*this, &ARDOUR_UI::open_media_folder));
act = ActionManager::register_action (common_actions, X_("Save"), _("Save"), sigc::hide_return (sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::save_state), string(""), false)));
ActionManager::session_sensitive_actions.push_back (act);
@ -539,6 +553,11 @@ ARDOUR_UI::install_actions ()
act = ActionManager::register_action (midi_actions, X_("panic"), _("Panic (Send MIDI all-notes-off)"), sigc::mem_fun(*this, &ARDOUR_UI::midi_panic));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::transport_sensitive_actions.push_back (act);
if (Profile->get_livetrax()) {
act = ActionManager::register_action (common_actions, X_("disable-virtual-soundcheck"), _("Disable Virtual Soundcheck"), sigc::mem_fun (*this, &ARDOUR_UI::disable_virtual_soundcheck));
act = ActionManager::register_action (common_actions, X_("enable-virtual-soundcheck"), _("Enable Virtual Soundcheck"), sigc::mem_fun (*this, &ARDOUR_UI::enable_virtual_soundcheck));
}
}
void
@ -762,19 +781,25 @@ ARDOUR_UI::build_menu_bar ()
ev->set_name ("MainMenuBar");
ev->show ();
EventBox* ev_dsp = manage (new EventBox);
EventBox* ev_dsp;
EventBox* ev_timecode;
EventBox* ev_path = manage (new EventBox);
EventBox* ev_name = manage (new EventBox);
EventBox* ev_audio = manage (new EventBox);
EventBox* ev_format = manage (new EventBox);
EventBox* ev_timecode = manage (new EventBox);
ev_dsp->set_name ("MainMenuBar");
if (!Profile->get_livetrax()) {
ev_dsp = manage (new EventBox);
ev_timecode = manage (new EventBox);
ev_dsp->set_name ("MainMenuBar");
ev_timecode->set_name ("MainMenuBar");
}
ev_path->set_name ("MainMenuBar");
ev_name->set_name ("MainMenuBar");
ev_audio->set_name ("MainMenuBar");
ev_format->set_name ("MainMenuBar");
ev_timecode->set_name ("MainMenuBar");
Gtk::HBox* hbox = manage (new Gtk::HBox);
hbox->show ();
@ -794,18 +819,23 @@ ARDOUR_UI::build_menu_bar ()
snapshot_name_label.set_name ("Name");
format_label.set_use_markup ();
ev_dsp->add (dsp_load_label);
if (!Profile->get_livetrax()) {
ev_dsp->add (dsp_load_label);
ev_timecode->add (timecode_format_label);
ev_audio->add (sample_rate_label);
}
ev_path->add (session_path_label);
ev_name->add (snapshot_name_label);
ev_audio->add (sample_rate_label);
ev_format->add (format_label);
ev_timecode->add (timecode_format_label);
ev_dsp->show ();
if (!Profile->get_livetrax()) {
ev_dsp->show ();
ev_timecode->show ();
ev_audio->show ();
}
ev_path->show ();
ev_audio->show ();
ev_format->show ();
ev_timecode->show ();
#ifdef __APPLE__
use_menubar_as_top_menubar ();
@ -816,10 +846,14 @@ ARDOUR_UI::build_menu_bar ()
hbox->pack_end (error_alert_button, false, false, 2);
hbox->pack_end (wall_clock_label, false, false, 10);
hbox->pack_end (*ev_dsp, false, false, 6);
hbox->pack_end (disk_space_label, false, false, 6);
if (!Profile->get_livetrax()) {
hbox->pack_end (*ev_dsp, false, false, 6);
hbox->pack_end (disk_space_label, false, false, 6);
}
hbox->pack_end (*ev_audio, false, false, 6);
hbox->pack_end (*ev_timecode, false, false, 6);
if (!Profile->get_livetrax()) {
hbox->pack_end (*ev_timecode, false, false, 6);
}
hbox->pack_end (*ev_format, false, false, 6);
hbox->pack_end (peak_thread_work_label, false, false, 6);
hbox->pack_end (*ev_name, false, false, 6);
@ -834,10 +868,13 @@ ARDOUR_UI::build_menu_bar ()
_status_bar_visibility.add (&snapshot_name_label ,X_("Name"), _("Snapshot Name and Modified Indicator"), false);
_status_bar_visibility.add (&peak_thread_work_label,X_("Peakfile"), _("Active Peak-file Work"), false);
_status_bar_visibility.add (&format_label, X_("Format"), _("File Format"), false);
_status_bar_visibility.add (&timecode_format_label, X_("TCFormat"), _("Timecode Format"), false);
_status_bar_visibility.add (&sample_rate_label, X_("Audio"), _("Audio"), true);
_status_bar_visibility.add (&disk_space_label, X_("Disk"), _("Disk Space"), !Profile->get_small_screen());
_status_bar_visibility.add (&dsp_load_label, X_("DSP"), _("DSP"), true);
if (!Profile->get_livetrax()) {
_status_bar_visibility.add (&timecode_format_label, X_("TCFormat"), _("Timecode Format"), false);
_status_bar_visibility.add (&disk_space_label, X_("Disk"), _("Disk Space"), !Profile->get_small_screen());
_status_bar_visibility.add (&dsp_load_label, X_("DSP"), _("DSP"), true);
}
#ifndef __APPLE__
// OSX provides its own wallclock, thank you very much
_status_bar_visibility.add (&wall_clock_label, X_("WallClock"), _("Wall Clock"), false);
@ -845,13 +882,16 @@ ARDOUR_UI::build_menu_bar ()
ev->signal_button_press_event().connect (sigc::mem_fun (_status_bar_visibility, &VisibilityGroup::button_press_event));
ev_dsp->signal_button_press_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::xrun_button_press));
ev_dsp->signal_button_release_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::xrun_button_release));
if (!Profile->get_livetrax()) {
ev_dsp->signal_button_press_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::xrun_button_press));
ev_dsp->signal_button_release_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::xrun_button_release));
ev_timecode->signal_button_press_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::timecode_button_press));
}
ev_path->signal_button_press_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::path_button_press));
ev_name->signal_button_press_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::path_button_press));
ev_audio->signal_button_press_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::audio_button_press));
ev_format->signal_button_press_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::format_button_press));
ev_timecode->signal_button_press_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::timecode_button_press));
ArdourWidgets::set_tooltip (session_path_label, _("Double click to open session folder."));
ArdourWidgets::set_tooltip (format_label, _("Double click to edit audio file format."));

View File

@ -143,7 +143,7 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey
}
}
DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 [title = %9] focus = %7 (%8) Key event: code = %2 [%10] state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7 mods ? %8\n",
DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 [title = %9] focus = %7 (mods %8) Key event: code = %2 [%10] state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7 mods ? %8\n",
win,
ev->keyval,
Gtkmm2ext::show_gdk_event_state (ev->state),

View File

@ -26,6 +26,8 @@
is to cut down on the nasty compile times for these classes.
*/
#include "ardour/profile.h"
#include "gtkmm2ext/keyboard.h"
#include "actions.h"
@ -44,7 +46,9 @@ ARDOUR_UI::create_mixer ()
{
try {
mixer = Mixer_UI::instance ();
mixer->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
if (!ARDOUR::Profile->get_livetrax()) {
mixer->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
}
}
catch (failed_constructor& err) {

View File

@ -60,6 +60,26 @@ using namespace ARDOUR;
using namespace PBD;
using namespace ArdourWidgets;
void
ARDOUR_UI::enable_virtual_soundcheck ()
{
if (!_session) {
return;
}
_session->enable_virtual_soundcheck ();
}
void
ARDOUR_UI::disable_virtual_soundcheck ()
{
if (!_session) {
return;
}
_session->disable_virtual_soundcheck ();
}
void
ARDOUR_UI::toggle_external_sync()
{

View File

@ -117,10 +117,6 @@ ARDOUR_UI::setup_profile ()
if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
Profile->set_small_screen ();
}
if (g_getenv ("MIXBUS")) {
Profile->set_mixbus ();
}
}
int

View File

@ -196,7 +196,7 @@ AudioRegionView::init (bool wfd)
create_waves ();
if (!_recregion) {
if (!_recregion && !Profile->get_livetrax()) {
fade_in_handle = new ArdourCanvas::Rectangle (group);
CANVAS_DEBUG_NAME (fade_in_handle, string_compose ("fade in handle for %1", region()->name()));
fade_in_handle->set_outline_color (Gtkmm2ext::rgba_to_color (0, 0, 0, 1.0));
@ -232,12 +232,14 @@ AudioRegionView::init (bool wfd)
set_fade_visibility (false);
}
const string line_name = _region->name() + ":gain";
if (!Profile->get_livetrax()) {
const string line_name = _region->name() + ":gain";
gain_line.reset (new AudioRegionGainLine (line_name, *this, *group, audio_region()->envelope()));
gain_line.reset (new AudioRegionGainLine (line_name, *this, *group, audio_region()->envelope()));
update_envelope_visibility ();
gain_line->reset ();
update_envelope_visibility ();
gain_line->reset ();
}
/* streamview will call set_height() */
//set_height (trackview.current_height()); // XXX not correct for Layered mode, but set_height() will fix later.
@ -277,8 +279,10 @@ AudioRegionView::init (bool wfd)
setup_waveform_visibility ();
get_canvas_frame()->set_data ("linemerger", (LineMerger*) this);
gain_line->canvas_group().raise_to_top ();
if (gain_line) {
get_canvas_frame()->set_data ("linemerger", (LineMerger*) this);
gain_line->canvas_group().raise_to_top ();
}
/* XXX sync mark drag? */
}
@ -1665,7 +1669,7 @@ AudioRegionView::set_fade_visibility (bool yn)
if (end_xfade_curve) { end_xfade_curve->show (); }
if (start_xfade_rect) { start_xfade_rect->show (); }
if (end_xfade_rect) { end_xfade_rect->show (); }
} else {
} else {
if (start_xfade_curve) { start_xfade_curve->hide(); }
if (end_xfade_curve) { end_xfade_curve->hide(); }
if (fade_in_handle) { fade_in_handle->hide(); }

View File

@ -343,20 +343,20 @@ Editor::Editor ()
, cd_mark_label (_("CD Markers"))
, section_mark_label (_("Arrangement"))
, cue_mark_label (_("Cue Markers"))
, scene_mark_label (_("Scenes"))
, videotl_label (_("Video Timeline"))
, videotl_group (0)
, _region_boundary_cache_dirty (true)
, edit_packer (4, 4, true)
, vertical_adjustment (0.0, 0.0, 10.0, 400.0)
, horizontal_adjustment (0.0, 0.0, 1e16)
, unused_adjustment (0.0, 0.0, 10.0, 400.0)
, controls_layout (unused_adjustment, vertical_adjustment)
, _scroll_callbacks (0)
, _visible_canvas_width (0)
, _visible_canvas_height (0)
, _full_canvas_height (0)
, edit_controls_left_menu (0)
, edit_controls_right_menu (0)
, edit_controls_left_menu (nullptr)
, edit_controls_right_menu (nullptr)
, _trigger_clip_picker (nullptr)
, visual_change_queued(false)
, _tvl_no_redisplay(false)
, _tvl_redisplay_on_resume(false)
@ -576,6 +576,13 @@ Editor::Editor ()
cue_mark_label.hide();
cue_mark_label.set_no_show_all();
scene_mark_label.set_name ("EditorRulerLabel");
scene_mark_label.set_size_request (-1, (int)timebar_height);
scene_mark_label.set_alignment (1.0, 0.5);
scene_mark_label.set_padding (5,0);
scene_mark_label.hide();
scene_mark_label.set_no_show_all();
videotl_bar_height = 4;
videotl_label.set_name ("EditorRulerLabel");
videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
@ -602,7 +609,9 @@ Editor::Editor ()
CairoWidget::set_focus_handler (sigc::mem_fun (ARDOUR_UI::instance(), &ARDOUR_UI::reset_focus));
_summary = new EditorSummary (this);
if (!Profile->get_livetrax()) {
_summary = new EditorSummary (this);
}
TempoMap::MapChanged.connect (tempo_map_connection, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this), gui_context());
@ -706,20 +715,27 @@ Editor::Editor ()
add_notebook_page (_("Selection"), *_properties_box);
#warning Fix Properties Sidebar Layout to fit < 720px height
#endif
add_notebook_page (_("Tracks & Busses"), _routes->widget ());
add_notebook_page (_("Sources"), _sources->widget ());
add_notebook_page (_("Regions"), _regions->widget ());
add_notebook_page (_("Clips"), _trigger_clip_picker);
add_notebook_page (_("Arrangement"), _sections->widget ());
add_notebook_page (_("Snapshots"), _snapshots->widget ());
add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
add_notebook_page (_("Ranges & Marks"), _locations->widget ());
if (!Profile->get_livetrax()) {
_the_notebook.set_show_tabs (true);
_the_notebook.set_scrollable (true);
_the_notebook.popup_disable ();
_the_notebook.set_tab_pos (Gtk::POS_RIGHT);
_the_notebook.show_all ();
if (!Profile->get_livetrax()) {
_trigger_clip_picker = manage (new TriggerClipPicker ());
}
add_notebook_page (_("Tracks & Busses"), _routes->widget ());
add_notebook_page (_("Sources"), _sources->widget ());
add_notebook_page (_("Regions"), _regions->widget ());
add_notebook_page (_("Clips"), *_trigger_clip_picker);
add_notebook_page (_("Arrangement"), _sections->widget ());
add_notebook_page (_("Snapshots"), _snapshots->widget ());
add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
add_notebook_page (_("Ranges & Marks"), _locations->widget ());
_the_notebook.set_show_tabs (true);
_the_notebook.set_scrollable (true);
_the_notebook.popup_disable ();
_the_notebook.set_tab_pos (Gtk::POS_RIGHT);
_the_notebook.show_all ();
}
_notebook_shrunk = false;
@ -732,93 +748,104 @@ Editor::Editor ()
settings->get_property ("notebook-shrunk", _notebook_shrunk);
}
editor_summary_pane.set_check_divider_position (true);
editor_summary_pane.add (edit_packer);
if (!Profile->get_livetrax()) {
editor_summary_pane.set_check_divider_position (true);
editor_summary_pane.add (edit_packer);
Button* summary_arrow_left = manage (new Button);
summary_arrow_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
summary_arrow_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
summary_arrow_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
Button* summary_arrow_left = manage (new Button);
summary_arrow_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
summary_arrow_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
summary_arrow_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
Button* summary_arrow_right = manage (new Button);
summary_arrow_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
summary_arrow_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
summary_arrow_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
Button* summary_arrow_right = manage (new Button);
summary_arrow_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
summary_arrow_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
summary_arrow_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
VBox* summary_arrows_left = manage (new VBox);
summary_arrows_left->pack_start (*summary_arrow_left);
VBox* summary_arrows_left = manage (new VBox);
summary_arrows_left->pack_start (*summary_arrow_left);
VBox* summary_arrows_right = manage (new VBox);
summary_arrows_right->pack_start (*summary_arrow_right);
VBox* summary_arrows_right = manage (new VBox);
summary_arrows_right->pack_start (*summary_arrow_right);
Gtk::Frame* summary_frame = manage (new Gtk::Frame);
summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
Gtk::Frame* summary_frame = manage (new Gtk::Frame);
summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
summary_frame->add (*_summary);
summary_frame->show ();
summary_frame->add (*_summary);
summary_frame->show ();
_summary_hbox.pack_start (*summary_arrows_left, false, false);
_summary_hbox.pack_start (*summary_frame, true, true);
_summary_hbox.pack_start (*summary_arrows_right, false, false);
_summary_hbox.pack_start (*summary_arrows_left, false, false);
_summary_hbox.pack_start (*summary_frame, true, true);
_summary_hbox.pack_start (*summary_arrows_right, false, false);
editor_summary_pane.add (_summary_hbox);
edit_pane.set_check_divider_position (true);
edit_pane.add (editor_summary_pane);
_editor_list_vbox.pack_start (_the_notebook);
_editor_list_vbox.pack_start (*_properties_box, false, false, 0);
edit_pane.add (_editor_list_vbox);
edit_pane.set_child_minsize (_editor_list_vbox, 30); /* rough guess at width of notebook tabs */
editor_summary_pane.add (_summary_hbox);
edit_pane.set_check_divider_position (true);
edit_pane.add (editor_summary_pane);
_editor_list_vbox.pack_start (_the_notebook);
_editor_list_vbox.pack_start (*_properties_box, false, false, 0);
edit_pane.add (_editor_list_vbox);
edit_pane.set_child_minsize (_editor_list_vbox, 30); /* rough guess at width of notebook tabs */
edit_pane.set_drag_cursor (*_cursors->expand_left_right);
editor_summary_pane.set_drag_cursor (*_cursors->expand_up_down);
edit_pane.set_drag_cursor (*_cursors->expand_left_right);
editor_summary_pane.set_drag_cursor (*_cursors->expand_up_down);
float fract;
if (!settings || !settings->get_property ("edit-horizontal-pane-pos", fract) || fract > 1.0) {
/* initial allocation is 90% to canvas, 10% to notebook */
fract = 0.90;
float fract;
if (!settings || !settings->get_property ("edit-horizontal-pane-pos", fract) || fract > 1.0) {
/* initial allocation is 90% to canvas, 10% to notebook */
fract = 0.90;
}
edit_pane.set_divider (0, fract);
if (!settings || !settings->get_property ("edit-vertical-pane-pos", fract) || fract > 1.0) {
/* initial allocation is 90% to canvas, 10% to summary */
fract = 0.90;
}
editor_summary_pane.set_divider (0, fract);
}
edit_pane.set_divider (0, fract);
if (!settings || !settings->get_property ("edit-vertical-pane-pos", fract) || fract > 1.0) {
/* initial allocation is 90% to canvas, 10% to summary */
fract = 0.90;
}
editor_summary_pane.set_divider (0, fract);
global_vpacker.set_spacing (0);
global_vpacker.set_border_width (0);
/* the next three EventBoxes provide the ability for their child widgets to have a background color. That is all. */
if (!Profile->get_livetrax()) {
/* the next three EventBoxes provide the ability for their child widgets to have a background color. That is all. */
Gtk::EventBox* ebox = manage (new Gtk::EventBox); // a themeable box
ebox->set_name("EditorWindow");
ebox->add (ebox_hpacker);
Gtk::EventBox* ebox = manage (new Gtk::EventBox); // a themeable box
ebox->set_name("EditorWindow");
ebox->add (ebox_hpacker);
Gtk::EventBox* epane_box = manage (new EventBoxExt); // a themeable box
epane_box->set_name("EditorWindow");
epane_box->add (edit_pane);
Gtk::EventBox* epane_box = manage (new EventBoxExt); // a themeable box
epane_box->set_name("EditorWindow");
epane_box->add (edit_pane);
Gtk::EventBox* epane_box2 = manage (new EventBoxExt); // a themeable box
epane_box2->set_name("EditorWindow");
epane_box2->add (global_vpacker);
Gtk::EventBox* epane_box2 = manage (new EventBoxExt); // a themeable box
epane_box2->set_name("EditorWindow");
epane_box2->add (global_vpacker);
ArdourWidgets::ArdourDropShadow *toolbar_shadow = manage (new (ArdourWidgets::ArdourDropShadow));
toolbar_shadow->set_size_request (-1, 4);
toolbar_shadow->set_mode(ArdourWidgets::ArdourDropShadow::DropShadowBoth);
toolbar_shadow->set_name("EditorWindow");
toolbar_shadow->show();
ArdourWidgets::ArdourDropShadow *toolbar_shadow = manage (new (ArdourWidgets::ArdourDropShadow));
toolbar_shadow->set_size_request (-1, 4);
toolbar_shadow->set_mode(ArdourWidgets::ArdourDropShadow::DropShadowBoth);
toolbar_shadow->set_name("EditorWindow");
toolbar_shadow->show();
global_vpacker.pack_start (*toolbar_shadow, false, false);
global_vpacker.pack_start (*toolbar_shadow, false, false);
global_vpacker.pack_start (*ebox, false, false);
global_vpacker.pack_start (*epane_box, true, true);
global_hpacker.pack_start (*epane_box2, true, true);
global_vpacker.pack_start (*ebox, false, false);
/* need to show the "contents" widget so that notebook will show if tab is switched to
*/
if (!Profile->get_livetrax()) {
global_vpacker.pack_start (*epane_box, true, true);
global_hpacker.pack_start (*epane_box2, true, true);
}
/* need to show the "contents" widget so that notebook will show if tab is switched to
*/
global_hpacker.show ();
ebox_hpacker.show();
ebox->show();
global_hpacker.show ();
ebox_hpacker.show();
ebox->show();
} else {
global_vpacker.pack_start (edit_packer, true, true);
global_hpacker.pack_start (global_vpacker, true, true);
global_hpacker.show ();
}
/* register actions now so that set_state() can find them and set toggles/checks etc */
@ -1340,7 +1367,10 @@ void
Editor::set_session (Session *t)
{
SessionHandlePtr::set_session (t);
_trigger_clip_picker.set_session (_session);
if (_trigger_clip_picker) {
_trigger_clip_picker->set_session (_session);
}
section_marker_bar->clear (true);
@ -1353,16 +1383,19 @@ Editor::set_session (Session *t)
* before the visible state has been loaded from instant.xml */
_leftmost_sample = session_gui_extents().first.samples();
nudge_clock->set_session (_session);
_summary->set_session (_session);
if (!Profile->get_livetrax()) {
nudge_clock->set_session (_session);
_summary->set_session (_session);
}
_group_tabs->set_session (_session);
_route_groups->set_session (_session);
_regions->set_session (_session);
_sources->set_session (_session);
_snapshots->set_session (_session);
_sections->set_session (_session);
_routes->set_session (_session);
_locations->set_session (_session);
_sections->set_session (_session);
_properties_box->set_session (_session);
if (rhythm_ferret) {
@ -2503,7 +2536,9 @@ Editor::set_state (const XMLNode& node, int version)
PBD::Unwinder<bool> nsi (no_save_instant, true);
bool yn;
Tabbable::set_state (node, version);
if (!Profile->get_livetrax()) {
Tabbable::set_state (node, version);
}
samplepos_t ph_pos;
if (_session && node.get_property ("playhead", ph_pos)) {
@ -2721,7 +2756,9 @@ Editor::get_state () const
node->set_property ("id", id().to_s ());
node->add_child_nocopy (Tabbable::get_state());
if (!Profile->get_livetrax()) {
node->add_child_nocopy (Tabbable::get_state());
}
node->set_property("edit-horizontal-pane-pos", edit_pane.get_divider ());
node->set_property("notebook-shrunk", _notebook_shrunk);
@ -2821,7 +2858,9 @@ Editor::set_snapped_cursor_position (timepos_t const & pos)
{
if (_edit_point == EditAtMouse) {
_snapped_cursor->set_position (pos.samples());
_snapped_cursor->show ();
if (UIConfiguration::instance().get_show_snapped_cursor()) {
_snapped_cursor->show ();
}
}
}
@ -3290,7 +3329,7 @@ Editor::setup_toolbar ()
mode_box->set_spacing(2);
HBox* mouse_mode_box = manage (new HBox);
HBox* mouse_mode_hbox = manage (new HBox);
mouse_mode_hbox = manage (new HBox);
VBox* mouse_mode_vbox = manage (new VBox);
Alignment* mouse_mode_align = manage (new Alignment);
@ -3333,19 +3372,26 @@ Editor::setup_toolbar ()
mouse_mode_size_group->add_widget (nudge_backward_button);
mouse_mode_hbox->set_spacing (2);
mouse_mode_hbox->pack_start (smart_mode_button, false, false);
if (!Profile->get_livetrax()) {
mouse_mode_hbox->pack_start (smart_mode_button, false, false);
}
mouse_mode_hbox->pack_start (mouse_move_button, false, false);
mouse_mode_hbox->pack_start (mouse_select_button, false, false);
mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
mouse_mode_hbox->pack_start (mouse_grid_button, false, false);
mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
mouse_mode_hbox->pack_start (mouse_content_button, false, false);
mouse_mode_vbox->pack_start (*mouse_mode_hbox);
if (!Profile->get_livetrax()) {
mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
mouse_mode_hbox->pack_start (mouse_grid_button, false, false);
mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
mouse_mode_hbox->pack_start (mouse_content_button, false, false);
}
if (!Profile->get_livetrax()) {
mouse_mode_vbox->pack_start (*mouse_mode_hbox);
}
mouse_mode_align->add (*mouse_mode_vbox);
mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
@ -3361,7 +3407,9 @@ Editor::setup_toolbar ()
mode_box->pack_start (edit_point_selector, false, false);
mode_box->pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
mode_box->pack_start (*mouse_mode_box, false, false);
if (!Profile->get_livetrax()) {
mode_box->pack_start (*mouse_mode_box, false, false);
}
/* Zoom */
@ -3514,7 +3562,9 @@ Editor::setup_toolbar ()
toolbar_hbox.pack_start (grid_box, false, false);
toolbar_hbox.pack_start (_draw_box_spacer, false, false, 3);
toolbar_hbox.pack_start (draw_box, false, false);
toolbar_hbox.pack_end (_zoom_box, false, false, 2);
if (!Profile->get_livetrax()) {
toolbar_hbox.pack_end (_zoom_box, false, false, 2);
}
toolbar_hbox.pack_end (*(manage (new ArdourVSpacer ())), false, false, 3);
toolbar_hbox.pack_end (_track_box, false, false);
@ -5096,7 +5146,9 @@ Editor::on_samples_per_pixel_changed ()
}
refresh_location_display();
_summary->set_overlays_dirty ();
if (_summary) {
_summary->set_overlays_dirty ();
}
update_section_box ();
update_marker_labels ();
@ -5235,7 +5287,9 @@ Editor::visual_changer (const VisualChange& vc)
}
_region_peak_cursor->hide ();
_summary->set_overlays_dirty ();
if (_summary) {
_summary->set_overlays_dirty ();
}
}
struct EditorOrderTimeAxisSorter {
@ -5807,7 +5861,9 @@ Editor::region_view_added (RegionView * rv)
}
}
_summary->set_background_dirty ();
if (_summary) {
_summary->set_background_dirty ();
}
mark_region_boundary_cache_dirty ();
}
@ -5815,7 +5871,9 @@ Editor::region_view_added (RegionView * rv)
void
Editor::region_view_removed ()
{
_summary->set_background_dirty ();
if (_summary) {
_summary->set_background_dirty ();
}
mark_region_boundary_cache_dirty ();
}
@ -6214,7 +6272,9 @@ Editor::redisplay_track_views ()
vertical_adjustment.set_value (_full_canvas_height - _visible_canvas_height);
}
_summary->set_background_dirty();
if (_summary) {
_summary->set_background_dirty();
}
_group_tabs->set_dirty ();
return false;
@ -6514,12 +6574,16 @@ Editor::super_rapid_screen_update ()
timepos_t ms (selection->markers.front()->position());
snap_to (ms); // should use snap_to_with_modifier?
_snapped_cursor->set_position (ms.samples());
_snapped_cursor->show ();
if (UIConfiguration::instance().get_show_snapped_cursor()) {
_snapped_cursor->show ();
}
}
} else if (_edit_point == EditAtMouse && mouse_sample (where.sample, ignored)) {
/* cursor is in the editing canvas. show it. */
if (!_drags->active()) {
_snapped_cursor->show ();
if (UIConfiguration::instance().get_show_snapped_cursor()) {
_snapped_cursor->show ();
}
}
} else {
/* mouse is out of the editing canvas, or edit-point isn't mouse. Hide the snapped_cursor */

View File

@ -632,6 +632,8 @@ public:
void remove_region_marker (ARDOUR::CueMarker&);
void make_region_markers_global (bool as_cd_markers);
SelectionPropertiesBox& properties_box() const { return *_properties_box; }
protected:
void map_transport_state ();
void map_position_change (samplepos_t);
@ -939,6 +941,7 @@ private:
ArdourCanvas::Container* cd_marker_group;
ArdourCanvas::Container* section_marker_group;
ArdourCanvas::Container* cue_marker_group;
ArdourCanvas::Container* scene_marker_group;
/* parent for groups which themselves contain time markers */
ArdourCanvas::Container* _time_markers_group;
@ -992,6 +995,7 @@ private:
Glib::RefPtr<Gtk::ToggleAction> ruler_section_action;
Glib::RefPtr<Gtk::ToggleAction> ruler_marker_action;
Glib::RefPtr<Gtk::ToggleAction> ruler_cue_marker_action;
Glib::RefPtr<Gtk::ToggleAction> ruler_scene_marker_action;
bool no_ruler_shown_update;
Gtk::Widget* ruler_grabbed_widget;
@ -1083,6 +1087,7 @@ private:
ArdourCanvas::Rectangle* cd_marker_bar;
ArdourCanvas::Rectangle* section_marker_bar;
ArdourCanvas::Rectangle* cue_marker_bar;
ArdourCanvas::Rectangle* scene_marker_bar;
ArdourCanvas::Line* ruler_separator;
void toggle_cue_behavior ();
@ -1099,6 +1104,7 @@ private:
Gtk::Label cd_mark_label;
Gtk::Label section_mark_label;
Gtk::Label cue_mark_label;
Gtk::Label scene_mark_label;
/* videtimline related actions */
Gtk::Label videotl_label;
@ -1167,10 +1173,6 @@ private:
Gtk::Table edit_packer;
/** the adjustment that controls the overall editor vertical scroll position */
Gtk::Adjustment vertical_adjustment;
Gtk::Adjustment horizontal_adjustment;
Gtk::Adjustment unused_adjustment; // yes, really; Gtk::Layout constructor requires refs
Gtk::Layout controls_layout;
bool control_layout_scroll (GdkEventScroll* ev);
@ -1203,7 +1205,7 @@ private:
Gtk::VBox edit_controls_vbox;
Gtk::HBox edit_controls_hbox;
TriggerClipPicker _trigger_clip_picker;
TriggerClipPicker* _trigger_clip_picker;
void control_vertical_zoom_in_all ();
void control_vertical_zoom_out_all ();
@ -1318,7 +1320,7 @@ private:
void register_actions ();
void register_region_actions ();
void register_midi_actions (Gtkmm2ext::Bindings*);
void register_midi_actions ();
void load_bindings ();
@ -1593,6 +1595,7 @@ private:
void clear_xrun_markers ();
void clear_ranges ();
void clear_cues ();
void clear_scenes ();
void clear_locations ();
void unhide_markers ();
void unhide_ranges ();
@ -1996,6 +1999,7 @@ private:
void build_edit_mode_menu ();
Gtk::VBox edit_mode_box;
void set_ripple_mode (ARDOUR::RippleMode);
void set_edit_mode (ARDOUR::EditMode);
@ -2071,7 +2075,6 @@ private:
Gtk::HBox _track_box;
Gtk::HBox _zoom_box;
void zoom_adjustment_changed();
void setup_toolbar ();

View File

@ -697,6 +697,7 @@ Editor::register_actions ()
ruler_cd_marker_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-cd-marker-ruler"), _("CD Markers"), sigc::mem_fun(*this, &Editor::toggle_ruler_visibility)));
ruler_section_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-arrangement-ruler"), _("Arrangement"), sigc::mem_fun(*this, &Editor::toggle_ruler_visibility)));
ruler_marker_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-marker-ruler"), _("Location Markers"), sigc::mem_fun(*this, &Editor::toggle_ruler_visibility)));
ruler_scene_marker_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-scene-marker-ruler"), _("Scene Markers"), sigc::mem_fun(*this, &Editor::toggle_ruler_visibility)));
ruler_cue_marker_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-cue-marker-ruler"), _("Cue Markers"), sigc::mem_fun(*this, &Editor::toggle_ruler_visibility)));
ActionManager::register_action (editor_menu_actions, X_("VideoMonitorMenu"), _("Video Monitor"));
@ -727,6 +728,7 @@ Editor::register_actions ()
ruler_cd_marker_action->set_active (true);
ruler_marker_action->set_active (true);
ruler_cue_marker_action->set_active (true);
ruler_scene_marker_action->set_active (false);
ruler_video_action->set_active (false);
xjadeo_proc_action->set_active (false);
@ -790,7 +792,7 @@ Editor::register_actions ()
}
void
Editor::register_midi_actions (Bindings* midi_bindings)
Editor::register_midi_actions ()
{
_midi_actions = ActionManager::create_action_group (midi_bindings, X_("Notes"));
@ -985,7 +987,9 @@ void
Editor::load_bindings ()
{
bindings = Bindings::get_bindings (X_("Editor"));
global_hpacker.set_data ("ardour-bindings", bindings);
midi_bindings = Bindings::get_bindings (X_("MIDI"));
register_midi_actions ();
/* This set of bindings may expand in the future to include things
* other than MIDI editing, but for now this is all we've got as far as
@ -993,11 +997,11 @@ Editor::load_bindings ()
* the keys may overlap.
*/
Bindings* midi_bindings = Bindings::get_bindings (X_("MIDI"));
register_midi_actions (midi_bindings);
_track_canvas_viewport->canvas()->set_data ("ardour-bindings", midi_bindings);
if (!Profile->get_livetrax()) {
global_hpacker.set_data ("ardour-bindings", bindings);
_track_canvas_viewport->canvas()->set_data ("ardour-bindings", midi_bindings);
}
}
void

View File

@ -83,8 +83,12 @@ Editor::initialize_canvas ()
_track_canvas->set_background_color (UIConfiguration::instance().color ("arrange base"));
_track_canvas->use_nsglview (UIConfiguration::instance().get_nsgl_view_mode () == NSGLHiRes);
#ifdef __APPLE__
// as of april 12 2024 on X Window and Windows, setting this to false
// causes redraw errors, but not on macOS as far as we can tell
_track_canvas->set_single_exposure (false);
#endif
/* scroll group for items that should not automatically scroll
* (e.g verbose cursor). It shares the canvas coordinate space.
*/
@ -169,6 +173,8 @@ Editor::initialize_canvas ()
CANVAS_DEBUG_NAME (section_marker_group, "Arranger marker group");
meter_group = new ArdourCanvas::Container (_time_markers_group, ArdourCanvas::Duple (0.0, (timebar_height * 5.0) + 1.0));
CANVAS_DEBUG_NAME (meter_group, "meter group");
scene_marker_group = new ArdourCanvas::Container (_time_markers_group, ArdourCanvas::Duple (0.0, (timebar_height * 5.0) + 1.0));
CANVAS_DEBUG_NAME (scene_marker_group, "scene marker_group");
float timebar_thickness = timebar_height; //was 4
float timebar_top = (timebar_height - timebar_thickness)/2;
@ -203,6 +209,9 @@ Editor::initialize_canvas ()
cue_marker_bar = new ArdourCanvas::Rectangle (cue_marker_group, ArdourCanvas::Rect (0.0, timebar_top, ArdourCanvas::COORD_MAX, timebar_btm));
CANVAS_DEBUG_NAME (cue_marker_bar, "Cue Marker Bar");
scene_marker_bar = new ArdourCanvas::Rectangle (scene_marker_group, ArdourCanvas::Rect (0.0, timebar_top, ArdourCanvas::COORD_MAX, timebar_btm));
CANVAS_DEBUG_NAME (cue_marker_bar, "Scene Marker Bar");
ruler_separator = new ArdourCanvas::Line(_time_markers_group);
CANVAS_DEBUG_NAME (ruler_separator, "separator between ruler and main canvas");
ruler_separator->set (ArdourCanvas::Duple(0.0, 0.0), ArdourCanvas::Duple(ArdourCanvas::COORD_MAX, 0.0));
@ -252,6 +261,7 @@ Editor::initialize_canvas ()
cd_marker_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_bar_event), cd_marker_bar, CdMarkerBarItem, "cd marker bar"));
section_marker_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_bar_event), section_marker_bar, SectionMarkerBarItem, "arrangement marker bar"));
cue_marker_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_bar_event), cue_marker_bar, CueMarkerBarItem, "cd marker bar"));
scene_marker_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_bar_event), scene_marker_bar, SceneMarkerBarItem, "scene marker bar"));
videotl_group->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_videotl_bar_event), videotl_group));
range_marker_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_bar_event), range_marker_bar, RangeMarkerBarItem, "range marker bar"));
transport_marker_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_bar_event), transport_marker_bar, TransportMarkerBarItem, "transport marker bar"));
@ -363,7 +373,10 @@ Editor::track_canvas_viewport_size_allocated ()
update_tempo_based_rulers ();
redisplay_grid (false);
redisplay_track_views ();
_summary->set_overlays_dirty ();
if (_summary) {
_summary->set_overlays_dirty ();
}
}
void
@ -968,7 +981,7 @@ Editor::entered_track_canvas (GdkEventCrossing* ev)
if (!was_within) {
if (internal_editing()) {
if (internal_editing() || Profile->get_livetrax()) {
/* ensure that key events go here because there are
internal editing bindings associated only with the
canvas. if the focus is elsewhere, we cannot find them.
@ -1042,7 +1055,9 @@ Editor::tie_vertical_scrolling ()
{
if (pending_visual_change.idle_handler_id < 0) {
_region_peak_cursor->hide ();
_summary->set_overlays_dirty ();
if (_summary) {
_summary->set_overlays_dirty ();
}
}
}
@ -1087,6 +1102,9 @@ Editor::color_handler()
section_marker_bar->set_fill_color (UIConfiguration::instance().color_mod ("arrangement marker bar", "marker bar"));
section_marker_bar->set_outline_color (UIConfiguration::instance().color ("marker bar separator"));
scene_marker_bar->set_fill_color (UIConfiguration::instance().color_mod ("arrangement marker bar", "marker bar"));
scene_marker_bar->set_outline_color (UIConfiguration::instance().color ("marker bar separator"));
cue_marker_bar->set_fill_color (UIConfiguration::instance().color_mod ("cd marker bar", "marker bar"));
cue_marker_bar->set_outline_color (UIConfiguration::instance().color ("marker bar separator"));
@ -1494,6 +1512,7 @@ Editor::which_canvas_cursor(ItemType type) const
case CdMarkerBarItem:
case SectionMarkerBarItem:
case CueMarkerBarItem:
case SceneMarkerBarItem:
case VideoBarItem:
case TransportMarkerBarItem:
case DropZoneItem:

View File

@ -27,11 +27,13 @@ enum ItemType {
WaveItem,
PlayheadCursorItem,
MarkerItem,
SceneMarkerItem,
MarkerBarItem,
RangeMarkerBarItem,
CdMarkerBarItem,
SectionMarkerBarItem,
CueMarkerBarItem,
SceneMarkerBarItem,
VideoBarItem,
TransportMarkerBarItem,
SelectionItem,

View File

@ -145,6 +145,8 @@ Editor::add_new_location_internal (Location* location)
color = X_("location loop");
} else if (location->is_auto_punch()) {
color = X_("location punch");
} else if (location->is_scene()) {
color = X_("location scene");
} else {
color = X_("location range");
}
@ -161,6 +163,9 @@ Editor::add_new_location_internal (Location* location)
} else if (location->is_section()) {
lam->start = new ArdourMarker (*this, *section_marker_group, color, location->name(), marker_type (location), location->start());
group = section_marker_group;
} else if (location->is_scene()) {
lam->start = new ArdourMarker (*this, *scene_marker_group, color, location->name(), marker_type (location), location->start());
group = scene_marker_group;
} else {
lam->start = new ArdourMarker (*this, *marker_group, color, location->name(), marker_type (location), location->start());
group = marker_group;
@ -514,6 +519,8 @@ void Editor::ensure_marker_updated (LocationMarkers* lam, Location* location)
{
if (location->is_cd_marker()) {
reparent_location_markers (lam, cd_marker_group);
} else if (location->is_scene()) {
reparent_location_markers (lam, scene_marker_group);
} else if (location->is_section()) {
reparent_location_markers (lam, section_marker_group);
} else if (location->is_cue_marker()) {

View File

@ -775,6 +775,9 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
}
}
return true;
case SceneMarkerItem:
_drags->set (new MarkerDrag (this, item), event);
return true;
case TempoMarkerItem:
if (ArdourKeyboard::indicates_constraint (event->button.state)) {
@ -1731,6 +1734,10 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
marker_context_menu (&event->button, item);
break;
case SceneMarkerItem:
marker_context_menu (&event->button, item);
break;
case TempoMarkerItem:
case MeterMarkerItem:
case BBTMarkerItem:

View File

@ -2683,6 +2683,22 @@ Editor::clear_cues ()
}
}
void
Editor::clear_scenes ()
{
begin_reversible_command (_("clear locations"));
XMLNode &before = _session->locations()->get_state();
if (_session->locations()->clear_scene_markers (0, max_samplepos)) {
XMLNode &after = _session->locations()->get_state();
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
commit_reversible_command ();
} else {
abort_reversible_command ();
}
}
void
Editor::clear_locations ()
{

View File

@ -180,6 +180,7 @@ Editor::initialize_rulers ()
lab_children.push_back (Element(cd_mark_label, PACK_SHRINK, PACK_START));
lab_children.push_back (Element(mark_label, PACK_SHRINK, PACK_START));
lab_children.push_back (Element(cue_mark_label, PACK_SHRINK, PACK_START));
lab_children.push_back (Element(scene_mark_label, PACK_SHRINK, PACK_START));
lab_children.push_back (Element(section_mark_label, PACK_SHRINK, PACK_START));
lab_children.push_back (Element(videotl_label, PACK_SHRINK, PACK_START));
@ -257,6 +258,10 @@ Editor::popup_ruler_menu (timepos_t const & where, ItemType t)
}
break;
case SceneMarkerBarItem:
ruler_items.push_back (MenuElem (_("Delete all Scenes"), sigc::mem_fun (*this, &Editor::clear_scenes)));
break;
case TempoBarItem:
case TempoCurveItem:
ruler_items.push_back (MenuElem (_("Add New Tempo"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_add_new_tempo_event), where)));
@ -485,7 +490,7 @@ Editor::update_ruler_visibility ()
videotl_label.hide();
#endif
if (ruler_minsec_action->get_active()) {
if (!Profile->get_livetrax() && ruler_minsec_action->get_active()) {
old_unit_pos = minsec_ruler->position().y;
if (tbpos != old_unit_pos) {
minsec_ruler->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));
@ -501,7 +506,7 @@ Editor::update_ruler_visibility ()
minsec_label.hide();
}
if (ruler_timecode_action->get_active()) {
if (Profile->get_livetrax() || ruler_timecode_action->get_active()) {
old_unit_pos = timecode_ruler->position().y;
if (tbpos != old_unit_pos) {
timecode_ruler->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));
@ -517,7 +522,7 @@ Editor::update_ruler_visibility ()
timecode_label.hide();
}
if (ruler_samples_action->get_active()) {
if (!Profile->get_livetrax() && ruler_samples_action->get_active()) {
old_unit_pos = samples_ruler->position().y;
if (tbpos != old_unit_pos) {
samples_ruler->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));
@ -533,7 +538,7 @@ Editor::update_ruler_visibility ()
samples_label.hide();
}
if (ruler_bbt_action->get_active()) {
if (!Profile->get_livetrax() && ruler_bbt_action->get_active()) {
old_unit_pos = bbt_ruler->position().y;
if (tbpos != old_unit_pos) {
bbt_ruler->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));
@ -549,7 +554,7 @@ Editor::update_ruler_visibility ()
bbt_label.hide();
}
if (ruler_tempo_action->get_active()) {
if (!Profile->get_livetrax() && ruler_tempo_action->get_active()) {
old_unit_pos = tempo_group->position().y;
if (tbpos != old_unit_pos) {
tempo_group->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));
@ -564,7 +569,7 @@ Editor::update_ruler_visibility ()
tempo_label.hide();
}
if (ruler_meter_action->get_active()) {
if (!Profile->get_livetrax() && ruler_meter_action->get_active()) {
old_unit_pos = meter_group->position().y;
if (tbpos != old_unit_pos) {
meter_group->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));
@ -579,7 +584,7 @@ Editor::update_ruler_visibility ()
meter_label.hide();
}
if (ruler_range_action->get_active()) {
if (!Profile->get_livetrax() && ruler_range_action->get_active()) {
old_unit_pos = range_marker_group->position().y;
if (tbpos != old_unit_pos) {
range_marker_group->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));
@ -597,7 +602,7 @@ Editor::update_ruler_visibility ()
range_mark_label.hide();
}
if (ruler_loop_punch_action->get_active()) {
if (!Profile->get_livetrax() && ruler_loop_punch_action->get_active()) {
old_unit_pos = transport_marker_group->position().y;
if (tbpos != old_unit_pos) {
transport_marker_group->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));
@ -615,7 +620,7 @@ Editor::update_ruler_visibility ()
transport_mark_label.hide();
}
if (ruler_cd_marker_action->get_active()) {
if (!Profile->get_livetrax() && ruler_cd_marker_action->get_active()) {
old_unit_pos = cd_marker_group->position().y;
if (tbpos != old_unit_pos) {
cd_marker_group->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));
@ -637,7 +642,7 @@ Editor::update_ruler_visibility ()
update_marker_display();
}
if (ruler_marker_action->get_active()) {
if (Profile->get_livetrax() || ruler_marker_action->get_active()) {
old_unit_pos = marker_group->position().y;
if (tbpos != old_unit_pos) {
marker_group->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));
@ -655,7 +660,7 @@ Editor::update_ruler_visibility ()
mark_label.hide();
}
if (ruler_cue_marker_action->get_active()) {
if (!Profile->get_livetrax() && ruler_cue_marker_action->get_active()) {
old_unit_pos = cue_marker_group->position().y;
if (tbpos != old_unit_pos) {
cue_marker_group->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));
@ -673,7 +678,26 @@ Editor::update_ruler_visibility ()
cue_mark_label.hide();
}
if (ruler_section_action->get_active()) {
if (Profile->get_livetrax() || ruler_scene_marker_action->get_active()) {
old_unit_pos = scene_marker_group->position().y;
if (tbpos != old_unit_pos) {
scene_marker_group->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));
}
scene_marker_group->show();
scene_mark_label.show();
scene_marker_bar->set_outline(false);
tbpos += timebar_height;
tbgpos += timebar_height;
visible_timebars++;
update_marker_display();
} else {
scene_marker_group->hide ();
scene_mark_label.hide ();
}
if (!Profile->get_livetrax() && ruler_section_action->get_active()) {
old_unit_pos = section_marker_group->position().y;
if (tbpos != old_unit_pos) {
section_marker_group->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));
@ -693,7 +717,7 @@ Editor::update_ruler_visibility ()
update_marker_display();
}
if (ruler_video_action->get_active()) {
if (!Profile->get_livetrax() && ruler_video_action->get_active()) {
old_unit_pos = videotl_group->position().y;
if (tbpos != old_unit_pos) {
videotl_group->move (ArdourCanvas::Duple (0.0, tbpos - old_unit_pos));

View File

@ -152,11 +152,13 @@ setup_gtk_ardour_enums ()
REGISTER_ENUM (StreamItem);
REGISTER_ENUM (PlayheadCursorItem);
REGISTER_ENUM (MarkerItem);
REGISTER_ENUM (SceneMarkerItem);
REGISTER_ENUM (MarkerBarItem);
REGISTER_ENUM (RangeMarkerBarItem);
REGISTER_ENUM (CdMarkerBarItem);
REGISTER_ENUM (SectionMarkerBarItem);
REGISTER_ENUM (CueMarkerBarItem);
REGISTER_ENUM (SceneMarkerBarItem);
REGISTER_ENUM (VideoBarItem);
REGISTER_ENUM (TransportMarkerBarItem);
REGISTER_ENUM (SelectionItem);

View File

@ -19,7 +19,9 @@
#include "pbd/convert.h"
#include "pbd/enumwriter.h"
#include "ardour/profile.h"
#include "ardour/plugin_manager.h"
#include "gtkmm2ext/gui_thread.h"
#include "instrument_selector.h"
@ -47,12 +49,20 @@ InstrumentSelector::drop_plugin_ptr()
{
unset_model ();
clear ();
_instrument_list->clear ();
if (_instrument_list) {
_instrument_list->clear ();
}
}
void
InstrumentSelector::refill()
{
/* XXX conditional can be removed once livetrax has its own simple add
tracks dialog.
*/
if (Profile->get_livetrax()) {
return;
}
TreeModel::iterator iter = get_active();
std::string selected;
if (iter) {

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2024 Paul Davis <paul@linuxaudiosystems.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <gtkmm/stock.h>
#include "livetrax_add_track_dialog.h"
#include "pbd/i18n.h"
using namespace Gtk;
LiveTraxAddTrackDialog::LiveTraxAddTrackDialog ()
: ArdourDialog (_("Add Tracks"))
, track_count (1.0, 1.0, 1024.0, 1.0, 10.)
, track_count_spinner (track_count)
, mono_button (channel_button_group, _("Mono"))
, stereo_button (channel_button_group, _("Stereo"))
{
get_vbox()->pack_start (track_count_spinner);
get_vbox()->pack_start (mono_button);
get_vbox()->pack_start (stereo_button);
mono_button.set_active();
add_button (Stock::CANCEL, RESPONSE_CANCEL);
add_button (Stock::OK, RESPONSE_OK);
show_all ();
}
LiveTraxAddTrackDialog::~LiveTraxAddTrackDialog()
{
}
int
LiveTraxAddTrackDialog::num_tracks() const
{
return track_count.get_value();
}
bool
LiveTraxAddTrackDialog::stereo() const
{
return stereo_button.get_active();
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2024 Paul Davis <paul@linuxaudiosystems.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __gtk_ardour_livetrax_add_track_dialog_h__
#define __gtk_ardour_livetrax_add_track_dialog_h__
#include <gtkmm/dialog.h>
#include <gtkmm/spinbutton.h>
#include <gtkmm/button.h>
#include <gtkmm/comboboxtext.h>
#include <gtkmm/adjustment.h>
#include "ardour_dialog.h"
class LiveTraxAddTrackDialog : public ArdourDialog
{
public:
LiveTraxAddTrackDialog ();
~LiveTraxAddTrackDialog ();
int num_tracks() const;
bool stereo () const;
private:
Gtk::Adjustment track_count;
Gtk::SpinButton track_count_spinner;
Gtk::RadioButtonGroup channel_button_group;
Gtk::RadioButton mono_button;
Gtk::RadioButton stereo_button;
};
#endif // __gtk_ardour_livetrax_add_track_dialog_h__ */

View File

@ -0,0 +1,116 @@
#include "ardour/logmeter.h"
#include "ardour/audioengine.h"
#include "widgets/fastmeter.h"
#include "livetrax_meters.h"
#include "ui_config.h"
using namespace ARDOUR;
using namespace ArdourWidgets;
#define PX_SCALE(px) std::max ((float)px, rintf ((float)px* UIConfiguration::instance ().get_ui_scale ()))
LiveTraxMeters::LiveTraxMeters (size_t initial_cnt)
{
set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_NEVER);
resize (initial_cnt);
meter_box.set_spacing (PX_SCALE (10));
add (meter_box);
fast_screen_update_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &LiveTraxMeters::update_meters), 40, GDK_PRIORITY_REDRAW + 10);
}
LiveTraxMeters::~LiveTraxMeters ()
{
fast_screen_update_connection.disconnect ();
}
void
LiveTraxMeters::resize (size_t sz)
{
size_t old = meters.size();
while (old > sz) {
/* Widgets are all managed so this should delete them as they
are removed.
*/
meter_box.remove (*widgets[old - 1]);
meters.pop_back ();
old--;
}
if (old == sz) {
return;
}
uint32_t c[10];
uint32_t b[4];
float stp[4];
c[0] = UIConfiguration::instance().color ("meter color0");
c[1] = UIConfiguration::instance().color ("meter color1");
c[2] = UIConfiguration::instance().color ("meter color2");
c[3] = UIConfiguration::instance().color ("meter color3");
c[4] = UIConfiguration::instance().color ("meter color4");
c[5] = UIConfiguration::instance().color ("meter color5");
c[6] = UIConfiguration::instance().color ("meter color6");
c[7] = UIConfiguration::instance().color ("meter color7");
c[8] = UIConfiguration::instance().color ("meter color8");
c[9] = UIConfiguration::instance().color ("meter color9");
b[0] = UIConfiguration::instance().color ("meter background bottom");
b[1] = UIConfiguration::instance().color ("meter background top");
b[2] = 0x991122ff; // red highlight gradient Bot
b[3] = 0x551111ff; // red highlight gradient Top
stp[0] = 115.0 * log_meter0dB (-15);
stp[1] = 115.0 * log_meter0dB (-9);
stp[2] = 115.0 * log_meter0dB (-3);
stp[3] = 115.0;
// XXX config changed -> update meter style (and size)
for (size_t i = old; i < sz; ++i) {
meters.push_back (manage (new FastMeter (10 /* (uint32_t)floor (UIConfiguration::instance ().get_meter_hold ()) */,
8, FastMeter::Vertical, PX_SCALE (64),
c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9],
b[0], b[1], b[2], b[3],
stp[0], stp[1], stp[2], stp[3],
(UIConfiguration::instance ().get_meter_style_led () ? 3 : 1))));
Gtk::VBox* vb = manage (new Gtk::VBox);
char buf[16];
snprintf (buf, sizeof (buf), "%zu", i+1);
Gtk::Label* l = manage (new Gtk::Label (buf));
vb->pack_start (*l, false, false);
vb->pack_start (*meters.back(), true, true);
widgets.push_back (vb);
meter_box.pack_start (*vb, false, false, 0);
}
meter_box.show_all ();
}
bool
LiveTraxMeters::update_meters ()
{
PortManager::AudioInputPorts const aip (AudioEngine::instance ()->audio_input_ports ());
size_t n = 0;
for (auto const & p : aip) {
if (n >= meters.size()) {
break;
}
meters[n]->set (p.second.meter->level, p.second.meter->peak);
++n;
}
return true;
}

View File

@ -0,0 +1,35 @@
#ifndef __ardour_gtk_livetrax_meters_h__
#define __ardour_gtk_livetrax_meters_h__
#include <unistd.h>
#include <gtkmm/box.h>
#include <gtkmm/scrolledwindow.h>
namespace Gtk {
class Label;
}
namespace ArdourWidgets {
class FastMeter;
}
class LiveTraxMeters : public Gtk::ScrolledWindow
{
public:
LiveTraxMeters (size_t initial_cnt);
~LiveTraxMeters ();
void resize (size_t);
private:
Gtk::HBox meter_box;
Gtk::HBox global_hbox;
std::vector<Gtk::Widget*> widgets;
std::vector<ArdourWidgets::FastMeter*> meters;
sigc::connection fast_screen_update_connection;
bool update_meters ();
};
#endif /* __ardour_gtk_livetrax_meters_h__ */

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2024 Paul Davis <paul@linuxaudiosystems.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <iostream>
#include "livetrax_tc_widget.h"
#include "ui_config.h"
LiveTraxTCWidget::LiveTraxTCWidget()
{
Gtkmm2ext::Color c;
c = UIConfiguration::instance().color ("widget:blue");
Gtkmm2ext::color_to_rgba (c, bg_r, bg_g, bg_b, bg_a);
c = UIConfiguration::instance().color ("neutral:foreground");
Gtkmm2ext::color_to_rgba (c, txt_r, txt_g, txt_b, txt_a);
c = UIConfiguration::instance().color ("theme:bg1");
Gtkmm2ext::color_to_rgba (c, fg_r, fg_g, fg_b, fg_a);
}
bool
LiveTraxTCWidget::on_button_release_event (GdkEventButton* ev)
{
std::cerr << "here\n";
return true;
}
void
LiveTraxTCWidget::render (Cairo::RefPtr<Cairo::Context> const & context, cairo_rectangle_t*)
{
/* draw the background */
context->set_source_rgba (bg_r, bg_g, bg_b, 1.);
context->rectangle (0, 0, get_width(), get_height());
context->fill ();
Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create (context);
layout->set_text ("TC\nSource");
layout->set_font_description (UIConfiguration::instance().get_NormalBoldFont());
context->move_to (get_width() / 2.0 + 10., 10.);
context->set_source_rgba (txt_r, txt_g, txt_b, 1.);
layout->show_in_cairo_context (context);
double rect_width = (get_width() / 2.);
double rect_height = (get_height() - 3.) / 2.;
context->set_source_rgba (fg_r, fg_g, fg_b, 1.);
context->rectangle (1., 1., rect_width, rect_height);
context->fill ();
context->set_source_rgba (fg_r, fg_g, fg_b, 1.);
context->rectangle (1., 2 + rect_height, rect_width, rect_height);
context->fill ();
layout->set_text ("LTC");
layout->set_font_description (UIConfiguration::instance().get_NormalFont());
context->move_to (4., 3.); // XXXX need to adjust by + text height/2
context->set_source_rgba (txt_r, txt_g, txt_b, 1.);
layout->show_in_cairo_context (context);
layout->set_text ("25 FPS");
layout->set_font_description (UIConfiguration::instance().get_NormalFont());
context->move_to (4., 3. + rect_height); // XXXX need to adjust by + text height/2
context->set_source_rgba (txt_r, txt_g, txt_b, 1.);
layout->show_in_cairo_context (context);
}
void
LiveTraxTCWidget::parameter_changed (std::string const & param)
{
}
void
LiveTraxTCWidget::on_size_request (Gtk::Requisition* r)
{
r->width = 150;
r->height = -1;
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2024 Paul Davis <paul@linuxaudiosystems.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __gtk2_ardour_livetrax_tc_widget_h__
#define __gtk2_ardour_livetrax_tc_widget_h__
#include "gtkmm2ext/cairo_widget.h"
class LiveTraxTCWidget : public CairoWidget
{
public:
LiveTraxTCWidget ();
bool on_button_release_event (GdkEventButton*);
void render (Cairo::RefPtr<Cairo::Context> const&, cairo_rectangle_t*);
void parameter_changed (std::string const &);
void on_size_request (Gtk::Requisition*);
private:
double bg_r, bg_g, bg_b, bg_a;
double fg_r, fg_g, fg_b, fg_a;
double txt_r, txt_g, txt_b, txt_a;
};
#endif /* __gtk2_ardour_livetrax_tc_widget_h__ */

View File

@ -51,6 +51,7 @@
#include "ardour/revision.h"
#include "ardour/ardour.h"
#include "ardour/audioengine.h"
#include "ardour/profile.h"
#include "ardour/session_utils.h"
#include "ardour/filesystem_paths.h"
@ -367,7 +368,7 @@ int main (int argc, char *argv[])
}
if (no_splash) {
cout << _("Copyright (C) 1999-2023 Paul Davis") << endl
cout << _("Copyright (C) 1999-2024 Paul Davis") << endl
<< _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker, Robin Gareus") << endl
<< endl
<< string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
@ -457,6 +458,15 @@ int main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
if (g_getenv ("MIXBUS")) {
ARDOUR::Profile->set_mixbus ();
}
if (g_getenv ("LIVETRAX")) {
ARDOUR::Profile->set_livetrax ();
}
try {
ui = new ARDOUR_UI (&argc, &argv, localedir.c_str());
} catch (failed_constructor& err) {

View File

@ -154,7 +154,7 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session* sess, std::shared_ptr<Route> rt,
, gpm (sess, 250)
, panners (sess)
, trigger_display (-1., 8*16.)
, button_size_group (Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL))
, button_size_group (Gtk::SizeGroup::create (ARDOUR::Profile->get_livetrax() ? Gtk::SIZE_GROUP_BOTH : Gtk::SIZE_GROUP_HORIZONTAL))
, rec_mon_table (2, 2)
, solo_iso_table (1, 2)
, mute_solo_table (1, 2)
@ -237,10 +237,16 @@ MixerStrip::init ()
rec_mon_table.set_homogeneous (true);
rec_mon_table.set_row_spacings (2);
rec_mon_table.set_col_spacings (2);
if (ARDOUR::Profile->get_mixbus()) {
rec_mon_table.resize (1, 3);
if (ARDOUR::Profile->get_livetrax()) {
rec_mon_table.resize (1, 2);
rec_mon_table.attach (*monitor_input_button, 1, 2, 0, 1);
rec_mon_table.attach (*monitor_disk_button, 2, 3, 0, 1);
} else {
if (ARDOUR::Profile->get_mixbus()) {
rec_mon_table.resize (1, 3);
rec_mon_table.attach (*monitor_input_button, 1, 2, 0, 1);
rec_mon_table.attach (*monitor_disk_button, 2, 3, 0, 1);
}
}
rec_mon_table.show ();
@ -324,23 +330,31 @@ MixerStrip::init ()
set_tooltip (&number_label, _("Double-click to edit the route color.\nRight-click to show the route operations context menu."));
global_vpacker.set_spacing (2);
global_vpacker.pack_start (width_hide_box, Gtk::PACK_SHRINK);
global_vpacker.pack_start (name_button, Gtk::PACK_SHRINK);
global_vpacker.pack_start (input_button_box, Gtk::PACK_SHRINK);
global_vpacker.pack_start (invert_button_box, Gtk::PACK_SHRINK);
global_vpacker.pack_start (trigger_display, Gtk::PACK_SHRINK);
global_vpacker.pack_start (_tmaster_widget, Gtk::PACK_SHRINK);
global_vpacker.pack_start (processor_box, true, true);
if (!Profile->get_livetrax()) {
global_vpacker.pack_start (width_hide_box, Gtk::PACK_SHRINK);
global_vpacker.pack_start (name_button, Gtk::PACK_SHRINK);
global_vpacker.pack_start (input_button_box, Gtk::PACK_SHRINK);
global_vpacker.pack_start (invert_button_box, Gtk::PACK_SHRINK);
global_vpacker.pack_start (trigger_display, Gtk::PACK_SHRINK);
global_vpacker.pack_start (_tmaster_widget, Gtk::PACK_SHRINK);
global_vpacker.pack_start (processor_box, true, true);
}
global_vpacker.pack_start (panners, Gtk::PACK_SHRINK);
global_vpacker.pack_start (rec_mon_table, Gtk::PACK_SHRINK);
global_vpacker.pack_start (master_volume_table, Gtk::PACK_SHRINK);
global_vpacker.pack_start (solo_iso_table, Gtk::PACK_SHRINK);
if (!Profile->get_livetrax()) {
global_vpacker.pack_start (master_volume_table, Gtk::PACK_SHRINK);
global_vpacker.pack_start (solo_iso_table, Gtk::PACK_SHRINK);
}
global_vpacker.pack_start (mute_solo_table, Gtk::PACK_SHRINK);
global_vpacker.pack_start (gpm, Gtk::PACK_SHRINK);
global_vpacker.pack_start (control_slave_ui, Gtk::PACK_SHRINK);
global_vpacker.pack_start (bottom_button_table, Gtk::PACK_SHRINK);
global_vpacker.pack_start (output_button, Gtk::PACK_SHRINK);
global_vpacker.pack_start (_comment_button, Gtk::PACK_SHRINK);
if (!Profile->get_livetrax()) {
global_vpacker.pack_start (control_slave_ui, Gtk::PACK_SHRINK);
global_vpacker.pack_start (bottom_button_table, Gtk::PACK_SHRINK);
global_vpacker.pack_start (output_button, Gtk::PACK_SHRINK);
global_vpacker.pack_start (_comment_button, Gtk::PACK_SHRINK);
} else {
global_vpacker.pack_start (name_button, true, true);
}
#ifndef MIXBUS
//add a spacer underneath the master bus;
@ -439,7 +453,7 @@ MixerStrip::~MixerStrip ()
void
MixerStrip::vca_assign (std::shared_ptr<ARDOUR::VCA> vca)
{
std::shared_ptr<Slavable> sl = std::dynamic_pointer_cast<Slavable> ( route() );
std::shared_ptr<Slavable> sl = std::dynamic_pointer_cast<Slavable> (route());
if (sl)
sl->assign(vca);
}
@ -447,14 +461,19 @@ MixerStrip::vca_assign (std::shared_ptr<ARDOUR::VCA> vca)
void
MixerStrip::vca_unassign (std::shared_ptr<ARDOUR::VCA> vca)
{
std::shared_ptr<Slavable> sl = std::dynamic_pointer_cast<Slavable> ( route() );
if (sl)
std::shared_ptr<Slavable> sl = std::dynamic_pointer_cast<Slavable> (route());
if (sl) {
sl->unassign(vca);
}
}
bool
MixerStrip::mixer_strip_enter_event (GdkEventCrossing* /*ev*/)
MixerStrip::mixer_strip_enter_event (GdkEventCrossing* ev)
{
if (ev->detail != GDK_NOTIFY_INFERIOR) {
_mixer.steal_focus ();
}
_entered_mixer_strip = this;
return false;
@ -464,7 +483,7 @@ bool
MixerStrip::mixer_strip_leave_event (GdkEventCrossing *ev)
{
//if we have moved outside our strip, but not into a child view, then deselect ourselves
if ( !(ev->detail == GDK_NOTIFY_INFERIOR) ) {
if (ev->detail != GDK_NOTIFY_INFERIOR) {
_entered_mixer_strip= 0;
//clear keyboard focus in the gain display. this is cheesy but fixes a longstanding "bug" where the user starts typing in the gain entry, and leaves it active, thereby prohibiting other keybindings from working
@ -702,15 +721,19 @@ MixerStrip::set_route (std::shared_ptr<Route> rt)
if (is_track ()) {
rec_mon_table.attach (*rec_enable_button, 0, 1, 0, ARDOUR::Profile->get_mixbus() ? 1 : 2);
rec_mon_table.attach (*rec_enable_button, 0, 1, 0, (ARDOUR::Profile->get_mixbus()|ARDOUR::Profile->get_livetrax()) ? 1 : 2);
rec_enable_button->show();
if (ARDOUR::Profile->get_mixbus()) {
if (ARDOUR::Profile->get_livetrax()) {
rec_mon_table.attach (*monitor_input_button, 1, 2, 0, 1);
rec_mon_table.attach (*monitor_disk_button, 2, 3, 0, 1);
} else {
rec_mon_table.attach (*monitor_input_button, 1, 2, 0, 1);
rec_mon_table.attach (*monitor_disk_button, 1, 2, 1, 2);
if (ARDOUR::Profile->get_mixbus()) {
rec_mon_table.attach (*monitor_input_button, 1, 2, 0, 1);
rec_mon_table.attach (*monitor_disk_button, 2, 3, 0, 1);
} else {
rec_mon_table.attach (*monitor_input_button, 1, 2, 0, 1);
rec_mon_table.attach (*monitor_disk_button, 1, 2, 1, 2);
}
}
} else {
@ -1068,7 +1091,13 @@ MixerStrip::route_color_changed ()
{
using namespace ARDOUR_UI_UTILS;
name_button.modify_bg (STATE_NORMAL, color());
number_label.set_fixed_colors (gdk_color_to_rgba (color()), gdk_color_to_rgba (color()));
Gtkmm2ext::Color c (gdk_color_to_rgba (color()));
if (Profile->get_livetrax()) {
name_button.set_fixed_colors (c, c);
}
number_label.set_fixed_colors (c, c);
reset_strip_style ();
}
@ -1677,7 +1706,7 @@ MixerStrip::revert_to_default_display ()
gain_meter().set_controls (_route, _route->shared_peak_meter(), _route->amp(), _route->gain_control());
gain_meter().setup_meters ();
panner_ui().set_panner (_route->main_outs()->panner_shell(), _route->main_outs()->panner());
panner_ui().set_panner (_route->panner_shell(), _route->panner());
update_panner_choices();
panner_ui().setup_pan ();
panner_ui().set_send_drawing_mode (false);

View File

@ -56,6 +56,7 @@
#include "ardour/monitor_control.h"
#include "ardour/panner_shell.h"
#include "ardour/plugin_manager.h"
#include "ardour/profile.h"
#include "ardour/route_group.h"
#include "ardour/selection.h"
#include "ardour/session.h"
@ -131,7 +132,7 @@ Mixer_UI::Mixer_UI ()
, no_track_list_redisplay (false)
, in_group_row_change (false)
, track_menu (0)
, _plugin_selector (0)
, _plugin_selector (nullptr)
, _surround_strip (0)
, foldback_strip (0)
, _show_foldback_strip (true)
@ -164,6 +165,8 @@ Mixer_UI::Mixer_UI ()
scroller_base.set_name ("MixerWindow");
scroller_base.signal_button_press_event().connect (sigc::mem_fun(*this, &Mixer_UI::strip_scroller_button_event));
scroller_base.signal_button_release_event().connect (sigc::mem_fun(*this, &Mixer_UI::strip_scroller_button_event));
scroller_base.signal_enter_notify_event ().connect (sigc::mem_fun (*this, &Mixer_UI::scroller_enter), false);
/* set up drag-n-drop */
vector<TargetEntry> target_table;
@ -330,57 +333,62 @@ Mixer_UI::Mixer_UI ()
}
_mixer_scene_vbox.pack_start(_mixer_scene_table, false, false);
rhs_pane1.add (favorite_plugins_frame);
rhs_pane1.add (track_display_frame);
if (!Profile->get_livetrax()) {
rhs_pane1.add (favorite_plugins_frame);
rhs_pane1.add (track_display_frame);
rhs_pane2.add (rhs_pane1);
rhs_pane2.add (group_display_frame);
rhs_pane2.add (rhs_pane1);
rhs_pane2.add (group_display_frame);
list_vpacker.pack_start (rhs_pane2, true, true);
list_vpacker.pack_start (rhs_pane2, true, true);
//add a spacer; this fills the area that is normally taken by the pane resizers
_mixer_scene_spacer.set_size_request (-1, 6);
list_vpacker.pack_start (_mixer_scene_spacer, false, false);
_mixer_scene_frame.add(_mixer_scene_vbox);
list_vpacker.pack_start (_mixer_scene_frame, false, false);
//add a spacer; this fills the area that is normally taken by the pane resizers
_mixer_scene_spacer.set_size_request (-1, 6);
list_vpacker.pack_start (_mixer_scene_spacer, false, false);
vca_label_bar.set_size_request (-1, 16 + 1); /* must match height in GroupTabs::set_size_request() + 1 border px*/
vca_vpacker.pack_start (vca_label_bar, false, false);
_mixer_scene_frame.add(_mixer_scene_vbox);
list_vpacker.pack_start (_mixer_scene_frame, false, false);
vca_scroller_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
vca_scroller_base.set_name (X_("MixerWindow"));
vca_scroller_base.signal_button_press_event().connect (sigc::mem_fun(*this, &Mixer_UI::strip_scroller_button_event));
vca_scroller_base.signal_button_release_event().connect (sigc::mem_fun(*this, &Mixer_UI::strip_scroller_button_event));
vca_label_bar.set_size_request (-1, 16 + 1); /* must match height in GroupTabs::set_size_request() + 1 border px*/
vca_vpacker.pack_start (vca_label_bar, false, false);
vca_hpacker.signal_scroll_event().connect (sigc::mem_fun (*this, &Mixer_UI::on_vca_scroll_event), false);
vca_scroller.add (vca_hpacker);
vca_scroller.set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_AUTOMATIC);
vca_scroller_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
vca_scroller_base.set_name (X_("MixerWindow"));
vca_scroller_base.signal_button_press_event().connect (sigc::mem_fun(*this, &Mixer_UI::strip_scroller_button_event));
vca_scroller_base.signal_button_release_event().connect (sigc::mem_fun(*this, &Mixer_UI::strip_scroller_button_event));
vca_vpacker.pack_start (vca_scroller, true, true);
vca_hpacker.signal_scroll_event().connect (sigc::mem_fun (*this, &Mixer_UI::on_vca_scroll_event), false);
vca_scroller.add (vca_hpacker);
vca_scroller.set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_AUTOMATIC);
inner_pane.add (scroller);
inner_pane.add (vca_vpacker);
vca_vpacker.pack_start (vca_scroller, true, true);
global_hpacker.pack_start (inner_pane, true, true);
global_hpacker.pack_start (out_packer, false, false);
inner_pane.add (scroller);
inner_pane.add (vca_vpacker);
list_hpane.set_check_divider_position (true);
list_hpane.add (list_vpacker);
list_hpane.add (global_hpacker);
list_hpane.set_child_minsize (list_vpacker, 30);
global_hpacker.pack_start (inner_pane, true, true);
global_hpacker.pack_start (out_packer, false, false);
rhs_pane1.set_divider (0, .6);
rhs_pane2.set_divider (0, .7);
list_hpane.set_divider (0, .2);
inner_pane.set_divider (0, .8);
list_hpane.set_check_divider_position (true);
list_hpane.add (list_vpacker);
list_hpane.add (global_hpacker);
list_hpane.set_child_minsize (list_vpacker, 30);
rhs_pane1.set_drag_cursor (*PublicEditor::instance().cursors()->expand_up_down);
rhs_pane2.set_drag_cursor (*PublicEditor::instance().cursors()->expand_up_down);
list_hpane.set_drag_cursor (*PublicEditor::instance().cursors()->expand_left_right);
inner_pane.set_drag_cursor (*PublicEditor::instance().cursors()->expand_left_right);
rhs_pane1.set_divider (0, .6);
rhs_pane2.set_divider (0, .7);
list_hpane.set_divider (0, .2);
inner_pane.set_divider (0, .8);
_content.pack_start (list_hpane, true, true);
rhs_pane1.set_drag_cursor (*PublicEditor::instance().cursors()->expand_up_down);
rhs_pane2.set_drag_cursor (*PublicEditor::instance().cursors()->expand_up_down);
list_hpane.set_drag_cursor (*PublicEditor::instance().cursors()->expand_left_right);
inner_pane.set_drag_cursor (*PublicEditor::instance().cursors()->expand_left_right);
_content.pack_start (list_hpane, true, true);
} else {
_content.pack_start (scroller, true, true);
}
update_title ();
@ -429,7 +437,9 @@ Mixer_UI::Mixer_UI ()
ARDOUR_UI::instance()->Escape.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::escape, this), gui_context());
#ifndef DEFER_PLUGIN_SELECTOR_LOAD
_plugin_selector = new PluginSelector (PluginManager::instance ());
if (!Profile->get_livetrax()) {
_plugin_selector = new PluginSelector (PluginManager::instance ());
}
#else
#error implement deferred Plugin-Favorite list
#endif
@ -515,8 +525,17 @@ Mixer_UI::show_window ()
ms->parameter_changed (X_("mixer-element-visibility"));
}
/* force focus into main area */
scroller_base.grab_focus ();
if (!Profile->get_livetrax()) {
/* force focus into main area */
scroller_base.grab_focus ();
}
}
bool
Mixer_UI::scroller_enter (GdkEventCrossing* ev)
{
steal_focus ();
return false;
}
void
@ -1285,7 +1304,9 @@ Mixer_UI::set_session (Session* sess)
return;
}
refill_favorite_plugins();
if (!Profile->get_livetrax()) {
refill_favorite_plugins();
}
XMLNode* node = ARDOUR_UI::instance()->mixer_settings();
set_state (*node, 0);
@ -2293,7 +2314,7 @@ Mixer_UI::toggle_mixer_list ()
void
Mixer_UI::showhide_mixer_list (bool yn)
{
if (yn) {
if (!Profile->get_livetrax() && yn) {
list_vpacker.show ();
} else {
list_vpacker.hide ();
@ -2539,7 +2560,9 @@ Mixer_UI::set_state (const XMLNode& node, int version)
{
bool yn;
Tabbable::set_state (node, version);
if (!Profile->get_livetrax()) {
Tabbable::set_state (node, version);
}
if (node.get_property ("narrow-strips", yn)) {
if (yn) {
@ -2683,7 +2706,9 @@ Mixer_UI::get_state () const
{
XMLNode* node = new XMLNode (X_("Mixer"));
node->add_child_nocopy (Tabbable::get_state());
if (!Profile->get_livetrax()) {
node->add_child_nocopy (Tabbable::get_state());
}
node->set_property (X_("mixer-rhs-pane1-pos"), rhs_pane1.get_divider());
node->set_property (X_("mixer-rhs_pane2-pos"), rhs_pane2.get_divider());
@ -2915,6 +2940,11 @@ Mixer_UI::set_route_group_activation (RouteGroup* g, bool a)
PluginSelector*
Mixer_UI::plugin_selector()
{
if (Profile->get_livetrax()) {
/* no plugins, no plugin selector */
return nullptr;
}
#ifdef DEFER_PLUGIN_SELECTOR_LOAD
if (!_plugin_selector)
_plugin_selector = new PluginSelector (PluginManager::instance());
@ -3167,6 +3197,10 @@ Mixer_UI::save_favorite_ui_state (const TreeModel::iterator& iter, const TreeMod
void
Mixer_UI::plugin_list_mode_changed ()
{
if (Profile->get_livetrax()) {
return;
}
if (plugin_list_mode () == PLM_Favorite) {
PBD::Unwinder<bool> uw (ignore_plugin_refill, true);
favorite_plugins_search_hbox.show ();
@ -3180,6 +3214,10 @@ Mixer_UI::plugin_list_mode_changed ()
void
Mixer_UI::plugin_search_entry_changed ()
{
if (Profile->get_livetrax()) {
return;
}
if (plugin_list_mode () == PLM_Favorite) {
refill_favorite_plugins ();
}
@ -3194,6 +3232,10 @@ Mixer_UI::plugin_search_clear_button_clicked ()
void
Mixer_UI::refiller (PluginInfoList& result, const PluginInfoList& plugs)
{
if (Profile->get_livetrax()) {
return;
}
PluginManager& manager (PluginManager::instance());
PluginListMode plm = plugin_list_mode ();
@ -3240,6 +3282,10 @@ Mixer_UI::refiller (PluginInfoList& result, const PluginInfoList& plugs)
void
Mixer_UI::refill_favorite_plugins ()
{
if (Profile->get_livetrax()) {
return;
}
if (ignore_plugin_refill) {
return;
}
@ -4430,3 +4476,11 @@ Mixer_UI::sync_surround_action ()
Glib::RefPtr<Action> surround_export = ActionManager::get_action (X_("Main"), X_("SurroundExport"));
surround_export->set_sensitive (have_sm && _session->vapor_export_barrier ());
}
void
Mixer_UI::steal_focus ()
{
if (Profile->get_livetrax()) {
scroller_base.grab_focus ();
}
}

View File

@ -169,6 +169,8 @@ public:
void toggle_monitor_action (ARDOUR::MonitorChoice monitor_choice, bool group_override = false, bool all = false);
void steal_focus ();
protected:
void set_axis_targets_for_operation ();
PBD::ControllableSet selected_gaincontrols ();
@ -234,6 +236,7 @@ private:
void scroller_drag_data_received (const Glib::RefPtr<Gdk::DragContext>&, int, int, const Gtk::SelectionData&, guint, guint);
bool strip_scroller_button_event (GdkEventButton*);
bool scroller_enter (GdkEventCrossing*);
void scroll_left ();
void scroll_right ();
void vca_scroll_left ();

View File

@ -33,8 +33,10 @@
#include "ardour/pannable.h"
#include "ardour/panner.h"
#include "ardour/panner_shell.h"
#include "ardour/profile.h"
#include "ardour/session.h"
#include "widgets/ardour_knob.h"
#include "widgets/tooltips.h"
#include "gain_meter.h"
@ -55,24 +57,27 @@ using namespace Gtkmm2ext;
using namespace Gtk;
PannerUI::PannerUI (Session* s)
: _current_nouts (-1)
: in_pan_update (false)
, _current_nouts (-1)
, _current_nins (-1)
, _current_uri ("")
, _send_mode (false)
, twod_panner (nullptr)
, big_window (nullptr)
, _stereo_panner (nullptr)
, _mono_panner (nullptr)
, _knob_panner (nullptr)
, _ignore_width_change (false)
, _ignore_position_change (false)
, pan_astate_menu (nullptr)
, pan_astyle_menu (nullptr)
, pan_automation_state_button ("")
, _panner_list()
, pan_menu (nullptr)
, bypass_menu_item (nullptr)
, send_link_menu_item (nullptr)
{
set_session (s);
pan_menu = 0;
pan_astate_menu = 0;
pan_astyle_menu = 0;
in_pan_update = false;
_stereo_panner = 0;
_mono_panner = 0;
_ignore_width_change = false;
_ignore_position_change = false;
pan_automation_state_button.set_name ("MixerAutomationPlaybackButton");
ArdourWidgets::set_tooltip (pan_automation_state_button, _("Pan automation mode"));
@ -86,10 +91,7 @@ PannerUI::PannerUI (Session* s)
pan_vbox.set_spacing (2);
pack_start (pan_vbox, true, true);
twod_panner = 0;
big_window = 0;
set_width(Narrow);
set_width (Narrow);
}
void
@ -121,6 +123,9 @@ PannerUI::set_panner (std::shared_ptr<PannerShell> ps, std::shared_ptr<Panner> p
delete _mono_panner;
_mono_panner = 0;
delete _knob_panner;
_knob_panner = 0;
if (!_panner) {
return;
}
@ -202,6 +207,7 @@ PannerUI::~PannerUI ()
delete pan_astate_menu;
delete _stereo_panner;
delete _mono_panner;
delete _knob_panner;
}
void
@ -219,11 +225,9 @@ PannerUI::setup_pan ()
assert (_panshell);
if (nouts == _current_nouts
&& nins == _current_nins
&& _current_uri == _panshell->panner_gui_uri()
)
{
if (nouts == _current_nouts &&
nins == _current_nins &&
_current_uri == _panshell->panner_gui_uri()) {
return;
}
@ -239,6 +243,8 @@ PannerUI::setup_pan ()
_stereo_panner = 0;
delete _mono_panner;
_mono_panner = 0;
delete _knob_panner;
_knob_panner = 0;
if (!_panner) {
delete big_window;
@ -283,20 +289,35 @@ PannerUI::setup_pan ()
std::shared_ptr<Pannable> pannable = _panner->pannable();
std::shared_ptr<AutomationControl> ac = pannable->pan_azimuth_control;
_mono_panner = new MonoPanner (_panshell);
if (ARDOUR::Profile->get_livetrax()) {
_mono_panner->StartGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::start_touch),
std::weak_ptr<AutomationControl> (ac)));
_mono_panner->StopGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::stop_touch),
std::weak_ptr<AutomationControl>(ac)));
_knob_panner = new ArdourWidgets::ArdourKnob (ArdourWidgets::ArdourKnob::default_elements,
ArdourWidgets::ArdourCtrlBase::Flags (ArdourWidgets::ArdourCtrlBase::Detent|ArdourWidgets::ArdourCtrlBase::ArcToZero));
_mono_panner->signal_button_release_event().connect (sigc::mem_fun(*this, &PannerUI::pan_button_event));
_knob_panner->set_controllable (ac);
update_pan_sensitive ();
_knob_panner->show ();
_knob_panner->set_size_request (-1, 5 * ceilf(7.f * scale));
_knob_panner->set_name ("monitor section knob");
pan_vbox.pack_start (*_knob_panner, false, false);
_mono_panner->set_size_request (-1, 5 * ceilf(7.f * scale));
_mono_panner->set_send_drawing_mode (_send_mode);
} else {
update_pan_sensitive ();
pan_vbox.pack_start (*_mono_panner, false, false);
_mono_panner = new MonoPanner (_panshell);
_mono_panner->StartGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::start_touch),
std::weak_ptr<AutomationControl> (ac)));
_mono_panner->StopGesture.connect (sigc::bind (sigc::mem_fun (*this, &PannerUI::stop_touch),
std::weak_ptr<AutomationControl>(ac)));
_mono_panner->signal_button_release_event().connect (sigc::mem_fun(*this, &PannerUI::pan_button_event));
_mono_panner->set_size_request (-1, 5 * ceilf(7.f * scale));
_mono_panner->set_send_drawing_mode (_send_mode);
update_pan_sensitive ();
pan_vbox.pack_start (*_mono_panner, false, false);
}
}
else if (_current_uri == "http://ardour.org/plugin/panner_vbap#ui")
{

View File

@ -54,6 +54,10 @@ namespace Gtk {
class Menuitem;
}
namespace ArdourWidgets {
class ArdourKnob;
}
class PannerUI : public Gtk::HBox, public ARDOUR::SessionHandlePtr
{
public:
@ -106,6 +110,7 @@ private:
StereoPanner* _stereo_panner;
MonoPanner* _mono_panner;
ArdourWidgets::ArdourKnob* _knob_panner;
bool _ignore_width_change;
bool _ignore_position_change;

View File

@ -462,7 +462,9 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
if (type == DataType::AUDIO || type == DataType::NIL) {
if (!inputs) {
program->add_bundle (session->the_auditioner()->output()->bundle());
if (session->the_auditioner()) {
program->add_bundle (session->the_auditioner()->output()->bundle());
}
if (session->click_io()) {
program->add_bundle (session->click_io()->bundle());
}

View File

@ -1036,11 +1036,11 @@ ProcessorEntry::Control::Control (ProcessorEntry& e,std::shared_ptr<AutomationCo
_slider.show ();
const ARDOUR::ParameterDescriptor& desc = c->desc();
double const lo = c->internal_to_interface (desc.lower);
double const up = c->internal_to_interface (desc.upper);
double const normal = c->internal_to_interface (desc.normal);
double const smallstep = c->internal_to_interface (desc.lower + desc.smallstep);
double const largestep = c->internal_to_interface (desc.lower + desc.largestep);
double const lo = c->internal_to_interface (desc.lower, true);
double const up = c->internal_to_interface (desc.upper, true);
double const normal = c->internal_to_interface (desc.normal, true);
double const smallstep = fabs (c->internal_to_interface (desc.lower + desc.smallstep, true) - lo);
double const largestep = fabs (c->internal_to_interface (desc.lower + desc.largestep, true) - lo);
_adjustment.set_lower (lo);
_adjustment.set_upper (up);
@ -1099,7 +1099,7 @@ ProcessorEntry::Control::slider_adjusted ()
return;
}
c->set_value ( c->interface_to_internal(_adjustment.get_value ()) , Controllable::NoGroup);
c->set_value ( c->interface_to_internal(_adjustment.get_value (), true) , Controllable::NoGroup);
set_tooltip ();
}
@ -1186,7 +1186,7 @@ ProcessorEntry::Control::control_changed ()
_button.set_active (c->get_value() > 0.5);
} else {
// Note: the _slider watches the controllable by itself
const double nval = c->internal_to_interface (c->get_value ());
const double nval = c->internal_to_interface (c->get_value (), true);
if (_adjustment.get_value() != nval) {
_adjustment.set_value (nval);
set_tooltip ();

View File

@ -35,6 +35,8 @@ ARDOUR::DataType PublicEditor::pbdid_dragged_dt = ARDOUR::DataType::NIL;
PublicEditor::PublicEditor (Gtk::Widget& content)
: Tabbable (content, _("Editor"), X_("editor"))
, vertical_adjustment (0.0, 0.0, 10.0, 400.0)
, horizontal_adjustment (0.0, 0.0, 1e16)
{
_suspend_route_redisplay_counter.store (0);
}

View File

@ -105,6 +105,7 @@ class TempoMarker;
class TimeAxisView;
class VerboseCursor;
struct SelectionRect;
class SelectionPropertiesBox;
class DisplaySuspender;
@ -599,6 +600,14 @@ public:
PBD::Signal0<void> MouseModeChanged;
Gtkmm2ext::Bindings* bindings;
Gtkmm2ext::Bindings* midi_bindings;
virtual SelectionPropertiesBox& properties_box() const = 0;
Gtk::HBox* mouse_mode_hbox;
Gtk::HBox _zoom_box;
/** the adjustment that controls the overall editor vertical scroll position */
Gtk::Adjustment vertical_adjustment;
Gtk::Adjustment horizontal_adjustment;
protected:
friend class DisplaySuspender;

View File

@ -182,85 +182,121 @@ RouteTimeAxisView::set_route (std::shared_ptr<Route> rt)
playlist_button.signal_button_press_event().connect (sigc::mem_fun(*this, &RouteTimeAxisView::playlist_click), false);
automation_button.signal_button_press_event().connect (sigc::mem_fun(*this, &RouteTimeAxisView::automation_click), false);
if (is_track()) {
if (Profile->get_livetrax()) {
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (*rec_enable_button, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
} else {
controls_table.attach (*rec_enable_button, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
}
monitor_input_button->show ();
if (is_midi_track()) {
set_tooltip(*rec_enable_button, _("Record (Right-click for Step Edit)"));
gm.set_fader_name ("MidiTrackFader");
} else {
set_tooltip(*rec_enable_button, _("Record"));
gm.set_fader_name ("AudioTrackFader");
}
controls_table.attach (number_label, 0, 1, 0, 2, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
controls_table.attach (*rec_enable_button, 3, 4, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
controls_table.attach (*monitor_input_button, 4, 5, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
controls_table.attach (*mute_button, 3, 4, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
controls_table.attach (*solo_button, 4, 5, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
/* set playlist button tip to the current playlist, and make it update when it changes */
update_playlist_tip ();
track()->PlaylistChanged.connect (*this, invalidator (*this), ui_bind(&RouteTimeAxisView::update_playlist_tip, this), gui_context());
controls_button_size_group->add_widget(*mute_button);
controls_button_size_group->add_widget(*solo_button);
controls_button_size_group->add_widget(*monitor_input_button);
controls_button_size_group->add_widget(*rec_enable_button);
} else {
gm.set_fader_name ("AudioBusFader");
Gtk::Fixed *blank = manage(new Gtk::Fixed());
controls_button_size_group->add_widget(*blank);
if (ARDOUR::Profile->get_mixbus() ) {
controls_table.attach (*blank, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
} else {
controls_table.attach (*blank, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
}
blank->show();
}
top_hbox.pack_end(gm.get_level_meter(), false, false, 2);
if (!ARDOUR::Profile->get_mixbus()) {
controls_meters_size_group->add_widget (gm.get_level_meter());
}
if (_route->is_master()) {
route_group_button.set_sensitive(false);
}
top_hbox.pack_end(gm.get_level_meter(), false, false, 2);
_route->meter_change.connect (*this, invalidator (*this), bind (&RouteTimeAxisView::meter_changed, this), gui_context());
_route->input()->changed.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::io_changed, this, _1, _2), gui_context());
_route->output()->changed.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::io_changed, this, _1, _2), gui_context());
_route->track_number_changed.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::label_view, this), gui_context());
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (*mute_button, 1, 2, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
} else {
controls_table.attach (*mute_button, 3, 4, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
}
// mute button is always present, it is used to
// force the 'blank' placeholders to the proper size
controls_button_size_group->add_widget(*mute_button);
if (!_route->is_master()) {
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (*solo_button, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
if (is_track()) {
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (*rec_enable_button, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
} else {
controls_table.attach (*rec_enable_button, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
}
if (is_midi_track()) {
set_tooltip(*rec_enable_button, _("Record (Right-click for Step Edit)"));
gm.set_fader_name ("MidiTrackFader");
} else {
set_tooltip(*rec_enable_button, _("Record"));
gm.set_fader_name ("AudioTrackFader");
}
/* set playlist button tip to the current playlist, and make it update when it changes */
update_playlist_tip ();
track()->PlaylistChanged.connect (*this, invalidator (*this), ui_bind(&RouteTimeAxisView::update_playlist_tip, this), gui_context());
} else {
controls_table.attach (*solo_button, 4, 5, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
gm.set_fader_name ("AudioBusFader");
Gtk::Fixed *blank = manage(new Gtk::Fixed());
controls_button_size_group->add_widget(*blank);
if (ARDOUR::Profile->get_mixbus() ) {
controls_table.attach (*blank, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
} else {
controls_table.attach (*blank, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
}
blank->show();
}
} else {
Gtk::Fixed *blank = manage(new Gtk::Fixed());
controls_button_size_group->add_widget(*blank);
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (*blank, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
} else {
controls_table.attach (*blank, 4, 5, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
}
blank->show();
}
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (route_group_button, 2, 3, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
controls_table.attach (gm.get_gain_slider(), 3, 5, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 1, 0);
} else {
controls_table.attach (route_group_button, 4, 5, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
controls_table.attach (gm.get_gain_slider(), 0, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 1, 0);
top_hbox.pack_end(gm.get_level_meter(), false, false, 2);
if (!ARDOUR::Profile->get_mixbus()) {
controls_meters_size_group->add_widget (gm.get_level_meter());
}
if (_route->is_master()) {
route_group_button.set_sensitive(false);
}
_route->meter_change.connect (*this, invalidator (*this), bind (&RouteTimeAxisView::meter_changed, this), gui_context());
_route->input()->changed.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::io_changed, this, _1, _2), gui_context());
_route->output()->changed.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::io_changed, this, _1, _2), gui_context());
_route->track_number_changed.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::label_view, this), gui_context());
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (*mute_button, 1, 2, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
} else {
controls_table.attach (*mute_button, 3, 4, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
}
// mute button is always present, it is used to
// force the 'blank' placeholders to the proper size
controls_button_size_group->add_widget(*mute_button);
if (!_route->is_master()) {
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (*solo_button, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
} else {
controls_table.attach (*solo_button, 4, 5, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
}
} else {
Gtk::Fixed *blank = manage(new Gtk::Fixed());
controls_button_size_group->add_widget(*blank);
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (*blank, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
} else {
controls_table.attach (*blank, 4, 5, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
}
blank->show();
}
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (route_group_button, 2, 3, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
controls_table.attach (gm.get_gain_slider(), 3, 5, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 1, 0);
} else {
controls_table.attach (route_group_button, 4, 5, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
controls_table.attach (gm.get_gain_slider(), 0, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 1, 0);
}
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (automation_button, 1, 2, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
} else {
controls_table.attach (automation_button, 3, 4, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
}
if (is_track() && track()->mode() == ARDOUR::Normal) {
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (playlist_button, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
} else {
controls_table.attach (playlist_button, 2, 3, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
}
}
}
set_tooltip(*solo_button,_("Solo"));
@ -284,20 +320,6 @@ RouteTimeAxisView::set_route (std::shared_ptr<Route> rt)
route_active_changed();
label_view ();
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (automation_button, 1, 2, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
} else {
controls_table.attach (automation_button, 3, 4, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
}
if (is_track() && track()->mode() == ARDOUR::Normal) {
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (playlist_button, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
} else {
controls_table.attach (playlist_button, 2, 3, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
}
}
_y_position = -1;
_route->processors_changed.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::processors_changed, this, _1), gui_context());
@ -447,7 +469,7 @@ void
RouteTimeAxisView::update_track_number_visibility ()
{
DisplaySuspender ds;
bool show_label = _session->config.get_track_name_number();
bool show_label = (Profile->get_livetrax() || _session->config.get_track_name_number());
if (_route && _route->is_master()) {
show_label = false;

View File

@ -484,11 +484,13 @@ RouteUI::mute_press (GdkEventButton* ev)
if (Keyboard::is_context_menu_event (ev)) {
if (mute_menu == 0){
build_mute_menu();
}
if (!Profile->get_livetrax()) {
if (mute_menu == 0){
build_mute_menu();
}
mute_menu->popup (ev->button, ev->time);
mute_menu->popup (ev->button, ev->time);
}
return true;
@ -650,11 +652,13 @@ RouteUI::solo_press(GdkEventButton* ev)
if (Keyboard::is_context_menu_event (ev)) {
if (solo_menu == 0) {
build_solo_menu ();
}
if (!Profile->get_livetrax()) {
if (solo_menu == 0) {
build_solo_menu ();
}
solo_menu->popup (ev->button, ev->time);
solo_menu->popup (ev->button, ev->time);
}
} else {
@ -1025,7 +1029,7 @@ RouteUI::step_edit_changed (bool yn)
bool
RouteUI::rec_enable_release (GdkEventButton* ev)
{
if (Keyboard::is_context_menu_event (ev)) {
if (!Profile->get_livetrax() && Keyboard::is_context_menu_event (ev)) {
build_record_menu ();
if (_record_menu) {
_record_menu->popup (ev->button, ev->time);
@ -2880,4 +2884,3 @@ RouteUI::clear_time_domain (bool apply_to_selection)
}
}

View File

@ -175,7 +175,7 @@ SelectionPropertiesBox::selection_changed ()
_header_label.hide();
if (!selection.time.empty()) {
if (Profile->get_livetrax() || !selection.time.empty()) {
_time_info_box->show();
_header_label.set_text(_("Range Properties (Press ESC to Deselect All)"));
_header_label.show();

View File

@ -497,6 +497,7 @@ SessionOptionEditor::parameter_changed (std::string const & p)
_sf->add (FormatInt24, _("24-bit integer"));
_sf->add (FormatInt16, _("16-bit integer"));
}
if (need_refill) {
parameter_changed ("native-file-data-format");
}

View File

@ -286,8 +286,10 @@ SoundFileBox::set_session(Session* s)
auditioner_connections.drop_connections();
} else {
auditioner_connections.drop_connections();
_session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
_session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
if (_session->the_auditioner()) {
_session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_active, this, _1), gui_context());
_session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&SoundFileBox::audition_progress, this, _1, _2), gui_context());
}
}
}
@ -310,15 +312,19 @@ SoundFileBox::audition_progress(ARDOUR::samplecnt_t pos, ARDOUR::samplecnt_t len
}
bool
SoundFileBox::seek_button_press(GdkEventButton*) {
SoundFileBox::seek_button_press (GdkEventButton*)
{
_seeking = true;
return false; // pass on to slider
}
bool
SoundFileBox::seek_button_release(GdkEventButton*) {
SoundFileBox::seek_button_release (GdkEventButton*)
{
_seeking = false;
_session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
if (_session->the_auditioner()) {
_session->the_auditioner()->seek_to_percent(seek_slider.get_value() / 10.0);
}
seek_slider.set_sensitive (false);
return false; // pass on to slider
}
@ -991,18 +997,20 @@ SoundFileBrowser::add_gain_meter ()
{
delete gm;
gm = new GainMeter (_session, 250);
std::shared_ptr<Route> r = _session->the_auditioner ();
gm->set_controls (r, r->shared_peak_meter(), r->amp(), r->gain_control());
gm->set_fader_name (X_("GainFader"));
if (r) {
gm = new GainMeter (_session, 250);
meter_packer.set_border_width (12);
meter_packer.pack_start (*gm, false, true);
hpacker.pack_end (meter_packer, false, false);
meter_packer.show_all ();
start_metering ();
gm->set_controls (r, r->shared_peak_meter(), r->amp(), r->gain_control());
gm->set_fader_name (X_("GainFader"));
meter_packer.set_border_width (12);
meter_packer.pack_start (*gm, false, true);
hpacker.pack_end (meter_packer, false, false);
meter_packer.show_all ();
start_metering ();
}
}
void
@ -2126,7 +2134,9 @@ SoundFileOmega::where_combo_changed()
void
SoundFileOmega::instrument_combo_changed()
{
_session->the_auditioner()->set_audition_synth_info( instrument_combo.selected_instrument() );
if (_session->the_auditioner()) {
_session->the_auditioner()->set_audition_synth_info( instrument_combo.selected_instrument() );
}
}
MidiTrackNameSource

View File

@ -238,6 +238,10 @@ Splash::expose (GdkEventExpose* ev)
{
RefPtr<Gdk::Window> window = darea.get_window();
/* clear background (for transparent splash images */
Glib::RefPtr<Gdk::GC> bg = get_style()->get_bg_gc (STATE_NORMAL);
window->draw_rectangle(bg, true, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
/* note: height & width need to be constrained to the pixbuf size
in case a WM provides us with a screwy allocation
*/

View File

@ -125,21 +125,30 @@ TransportControlUI::setup (TransportControlProvider* ui)
#undef PX_SCALE
if (!ARDOUR::Profile->get_mixbus()) {
pack_start (midi_panic_button, true, true, 0);
if (!ARDOUR::Profile->get_livetrax()) {
if (!ARDOUR::Profile->get_mixbus()) {
pack_start (midi_panic_button, true, true, 0);
} else {
pack_start (midi_panic_button, true, true, 3);
}
pack_start (click_button, true, true, 0);
pack_start (goto_start_button, true, true);
pack_start (goto_end_button, true, true);
pack_start (auto_loop_button, true, true);
if (!ARDOUR::Profile->get_mixbus()) {
pack_start (play_selection_button, true, true);
}
pack_start (roll_button, true, true);
pack_start (stop_button, true, true);
pack_start (rec_button, true, true, 3);
} else {
pack_start (midi_panic_button, true, true, 3);
pack_start (goto_start_button, true, true);
pack_start (goto_end_button, true, true);
pack_start (roll_button, true, true);
pack_start (stop_button, true, true);
pack_start (rec_button, true, true, 3);
pack_start (auto_loop_button, true, true);
}
pack_start (click_button, true, true, 0);
pack_start (goto_start_button, true, true);
pack_start (goto_end_button, true, true);
pack_start (auto_loop_button, true, true);
if (!ARDOUR::Profile->get_mixbus()) {
pack_start (play_selection_button, true, true);
}
pack_start (roll_button, true, true);
pack_start (stop_button, true, true);
pack_start (rec_button, true, true, 3);
roll_button.set_name ("transport button");
stop_button.set_name ("transport button");

View File

@ -33,7 +33,7 @@ UI_CONFIG_VARIABLE (bool, all_floating_windows_are_dialogs, "all-floating-window
UI_CONFIG_VARIABLE (bool, floating_monitor_section, "floating-monitor-section", false)
UI_CONFIG_VARIABLE (bool, transients_follow_front, "transients-follow-front", false)
UI_CONFIG_VARIABLE (bool, allow_to_resize_engine_dialog, "allow-to-resize-engine-dialog", false)
UI_CONFIG_VARIABLE (bool, color_regions_using_track_color, "color-regions-using-track-color", false)
UI_CONFIG_VARIABLE (bool, color_regions_using_track_color, "color-regions-using-track-color", true)
UI_CONFIG_VARIABLE (bool, use_route_color_widely, "use-route-color-widely", false)
UI_CONFIG_VARIABLE (uint32_t, vertical_region_gap, "vertical-region-gap", 0)
UI_CONFIG_VARIABLE (bool, editor_stereo_only_meters, "editor-stereo-only-meters", true)

View File

@ -143,6 +143,9 @@ gtk2_ardour_sources = [
'led.cc',
'level_meter.cc',
'library_download_dialog.cc',
'livetrax_add_track_dialog.cc',
'livetrax_meters.cc',
'livetrax_tc_widget.cc',
'location_ui.cc',
'loudness_dialog.cc',
'loudness_settings.cc',

View File

@ -338,6 +338,10 @@ public:
return false;
}
typedef std::vector<bool> ChannelMask;
ChannelMask const & input_channel_mask() const { return _input_channel_mask; }
ChannelMask const & output_channel_mask() const { return _output_channel_mask; }
/** Returns a collection of float identifying sample rates that are
* potentially usable with the hardware identified by \p device .
* Any of these values may be supplied in other calls to this backend
@ -854,11 +858,16 @@ public:
PBD::TimingStats dsp_stats[NTT];
void setup_channel_masks (size_t in, size_t out);
protected:
AudioBackendInfo& _info;
AudioEngine& engine;
virtual int _start (bool for_latency_measurement) = 0;
ChannelMask _input_channel_mask;
ChannelMask _output_channel_mask;
};
} // namespace ARDOUR

View File

@ -56,7 +56,9 @@ public:
/* aux - internal send used to deliver to any bus, by user request */
Aux = 0x10,
/* foldback - internal send used only to deliver to a personal monitor bus */
Foldback = 0x20
Foldback = 0x20,
/* master send - used only with LiveTrax, delivers to master bus */
MasterSend = 0x40
};
static bool role_requires_output_ports (Role r) { return r == Main || r == Send || r == Insert; }

View File

@ -69,6 +69,7 @@ public:
IsXrun = 0x400,
IsCueMarker = 0x800,
IsSection = 0x1000,
IsScene = 0x2000
};
Location (Session &);
@ -125,6 +126,7 @@ public:
bool is_skipping() const { return (_flags & IsSkip) && (_flags & IsSkipping); }
bool is_xrun() const { return _flags & IsXrun; }
bool is_section() const { return _flags & IsSection; }
bool is_scene() const { return (bool) _scene_change && _flags & IsScene; }
bool matches (Flags f) const { return _flags & f; }
/* any range with start < end -- not a marker */
@ -274,6 +276,7 @@ public:
bool clear_ranges ();
bool clear_cue_markers (samplepos_t start, samplepos_t end);
bool clear_scene_markers (samplepos_t start, samplepos_t end);
void cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, SectionOperation const op);

View File

@ -42,11 +42,12 @@ class LIBARDOUR_API MuteMaster : public SessionHandleRef, public PBD::Stateful
public:
/** deliveries to mute when the channel is "muted" */
enum MutePoint {
PreFader = 0x1, ///< mute all pre-fader sends
PostFader = 0x2, ///< mute all post-fader sends
Listen = 0x4, ///< mute listen out
Main = 0x8, ///< mute main out
SurroundSend = 0x10 ///< mute surround send (if any)
PreFader = 0x1, ///< mute all pre-fader sends
PostFader = 0x2, ///< mute all post-fader sends
Listen = 0x4, ///< mute listen out
Main = 0x8, ///< mute main out
SurroundSend = 0x10, ///< mute surround send (if any)
MasterSend = 0x20 ///< mute master send (LiveTrax only)
};
static const MutePoint AllPoints;

View File

@ -32,6 +32,7 @@ public:
SmallScreen,
SinglePackage,
Mixbus,
LiveTrax,
LastElement,
};
@ -44,6 +45,9 @@ public:
bool get_mixbus() const { return bits[Mixbus]; }
void set_mixbus() { bits[Mixbus] = true; }
bool get_livetrax() const { return bits[LiveTrax]; }
void set_livetrax() { bits[LiveTrax] = true; }
void set_single_package () { bits[SinglePackage] = true; }
bool get_single_package () const { return bits[SinglePackage]; }

View File

@ -30,7 +30,7 @@
the value of the variable.
*****************************************************/
CONFIG_VARIABLE (Temporal::TimeDomain, preferred_time_domain, "preferred_time_domain", Temporal::BeatTime)
CONFIG_VARIABLE (Temporal::TimeDomain, preferred_time_domain, "preferred_time_domain", Temporal::AudioTime)
/* IO connection */
@ -129,6 +129,7 @@ CONFIG_VARIABLE (bool, mute_affects_post_fader, "mute-affects-post-fader", true)
CONFIG_VARIABLE (bool, mute_affects_control_outs, "mute-affects-control-outs", true)
CONFIG_VARIABLE (bool, mute_affects_main_outs, "mute-affects-main-outs", true)
CONFIG_VARIABLE (bool, mute_affects_surround_sends, "mute-affects-surround-sends", true)
CONFIG_VARIABLE (bool, mute_affects_master_sends, "mute-affects-master-sends", true)
CONFIG_VARIABLE (MonitorModel, monitoring_model, "monitoring-model", ExternalMonitoring)
CONFIG_VARIABLE (ListenPosition, listen_position, "listen-position", AfterFaderListen)
CONFIG_VARIABLE (PFLPosition, pfl_position, "pfl-position", PFLFromAfterProcessors)

View File

@ -99,6 +99,7 @@ class MonitorControl;
class TriggerBox;
class SurroundReturn;
class SurroundSend;
class Send;
class LIBARDOUR_API Route : public Stripable,
public GraphNode,
@ -195,8 +196,16 @@ public:
bool can_monitor () const {
return can_solo() || is_foldbackbus ();
}
void enable_monitor_send ();
void enable_surround_send ();
void enable_master_send ();
void remove_monitor_send ();
void remove_surround_send ();
void remove_master_send ();
int add_aux_send (std::shared_ptr<Route>, std::shared_ptr<Processor>);
int add_foldback_send (std::shared_ptr<Route>, bool post_fader);
void set_denormal_protection (bool yn);
bool denormal_protection() const;
@ -278,12 +287,14 @@ public:
std::shared_ptr<Delivery> main_outs() const { return _main_outs; }
std::shared_ptr<InternalReturn> internal_return() const { return _intreturn; }
std::shared_ptr<MonitorProcessor> monitor_control() const { return _monitor_control; }
std::shared_ptr<InternalSend> master_send() const { return _master_send; }
std::shared_ptr<Send> internal_send_for (std::shared_ptr<const Route> target) const;
void add_internal_return ();
void add_send_to_internal_return (InternalSend *);
void remove_send_from_internal_return (InternalSend *);
void listen_position_changed ();
std::shared_ptr<CapturingProcessor> add_export_point(/* Add some argument for placement later */);
void add_master_send (std::shared_ptr<Route>);
/** A record of the stream configuration at some point in the processor list.
* Used to return where and why an processor list configuration request failed.
@ -439,11 +450,6 @@ public:
PBD::Signal1<void,void*> SelectedChanged;
int add_aux_send (std::shared_ptr<Route>, std::shared_ptr<Processor>);
int add_foldback_send (std::shared_ptr<Route>, bool post_fader);
void remove_monitor_send ();
void remove_surround_send ();
/**
* return true if this route feeds the first argument directly, via
* either its main outs or a send. This is checked by the actual
@ -695,6 +701,9 @@ protected:
std::shared_ptr<PeakMeter> _meter;
std::shared_ptr<PolarityProcessor> _polarity;
std::shared_ptr<TriggerBox> _triggerbox;
std::shared_ptr<InternalSend> _master_send;
void create_master_send ();
bool _volume_applies_to_output;

View File

@ -1405,6 +1405,15 @@ public:
void start_domain_bounce (Temporal::DomainBounceInfo&);
void finish_domain_bounce (Temporal::DomainBounceInfo&);
void enable_file_format_reset ();
void disable_file_format_reset ();
void reset_native_file_format();
void enable_virtual_soundcheck ();
void disable_virtual_soundcheck ();
bool virtual_soundcheck() const;
PBD::Signal1<void,bool> VirtualSoundCheckChanged;
protected:
friend class AudioEngine;
void set_block_size (pframes_t nframes);
@ -1801,6 +1810,7 @@ private:
MidiPortFlags exclude = MidiPortFlags (0));
void auto_connect (const AutoConnectRequest&);
void livetrax_auto_connect (std::shared_ptr<Route>);
void queue_latency_recompute ();
/* SessionEventManager interface */
@ -1981,6 +1991,7 @@ private:
bool find_route_name (std::string const &, uint32_t& id, std::string& name, bool);
void count_existing_track_channels (ChanCount& in, ChanCount& out);
void auto_connect_route (std::shared_ptr<Route>, bool, bool, const ChanCount&, const ChanCount&, const ChanCount& io = ChanCount(), const ChanCount& oo = ChanCount());
void livetrax_auto_connect_route (std::shared_ptr<Route>);
void midi_output_change_handler (IOChange change, void* /*src*/, std::weak_ptr<Route> midi_track);
/* track numbering */
@ -2226,6 +2237,7 @@ private:
void setup_route_monitor_sends (bool enable, bool need_process_lock);
void setup_route_surround_sends (bool enable, bool need_process_lock);
void setup_route_master_sends (bool enable, bool need_process_lock);
int find_all_sources (std::string path, std::set<std::string>& result);
int find_all_sources_across_snapshots (std::set<std::string>& result, bool exclude_this_snapshot);
@ -2239,7 +2251,6 @@ private:
void controllable_touched (std::weak_ptr<PBD::Controllable>);
std::weak_ptr<PBD::Controllable> _recently_touched_controllable;
void reset_native_file_format();
bool first_file_data_format_reset;
bool first_file_header_format_reset;
@ -2410,6 +2421,10 @@ private:
void handle_slots_empty_status (std::weak_ptr<Route> const &);
void time_domain_changed ();
uint32_t _no_file_format_reset;
void set_virtual_soundcheck (bool);
bool _virtual_soundcheck;
};

View File

@ -608,6 +608,13 @@ enum HeaderFormat {
FLAC,
};
struct LiveTraxFileFormat {
LiveTraxFileFormat (SampleFormat sff, HeaderFormat hff) : sf (sff), hf (hff) {}
SampleFormat sf;
HeaderFormat hf;
};
struct PeakData {
typedef Sample PeakDatum;

View File

@ -111,4 +111,14 @@ AudioBackend::get_standard_device_name (StandardDeviceName device_name)
return std::string();
}
void
AudioBackend::setup_channel_masks (size_t in, size_t out)
{
_input_channel_mask.assign (in, true);
_output_channel_mask.assign (out, true);
_input_channel_mask[2] = false;
_output_channel_mask[3] = false;
}
} // namespace ARDOUR

View File

@ -1075,13 +1075,15 @@ AudioEngine::start (bool for_latency)
}
if (!for_latency) {
/* Do this here so we do not have to add it to every backend */
_backend->setup_channel_masks (_backend->input_channels(), _backend->output_channels());
/* Call the library-wide ::init_post_engine() before emitting
* running to ensure that its tasks are complete before any
* signal handlers execute. PBD::Signal does not ensure
* ordering of signal handlers so even if ::init_post_engine()
* is connected first, it may not run first.
*/
ARDOUR::init_post_engine (_start_cnt);
Running (_start_cnt); /* EMIT SIGNAL */

View File

@ -67,7 +67,9 @@ Delivery::Delivery (Session& s, std::shared_ptr<IO> io, std::shared_ptr<Pannable
{
if (pannable) {
bool is_send = false;
if (r & (Delivery::Send|Delivery::Aux|Delivery::Foldback)) is_send = true;
if (r & (Delivery::Send|Delivery::Aux|Delivery::Foldback|Delivery::MasterSend)) {
is_send = true;
}
_panshell = std::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable, *this, is_send));
}
@ -91,7 +93,9 @@ Delivery::Delivery (Session& s, std::shared_ptr<Pannable> pannable, std::shared_
{
if (pannable) {
bool is_send = false;
if (r & (Delivery::Send|Delivery::Aux|Delivery::Foldback)) is_send = true;
if (r & (Delivery::Send|Delivery::Aux|Delivery::Foldback|Delivery::MasterSend)) {
is_send = true;
}
_panshell = std::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable, *this, is_send));
}
@ -188,7 +192,8 @@ Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out)
}
void
Delivery::set_gain_control (std::shared_ptr<GainControl> gc) {
Delivery::set_gain_control (std::shared_ptr<GainControl> gc)
{
if (gc) {
_gain_control = gc;
_amp.reset (new Amp (_session, _("Fader"), _gain_control, true));
@ -589,22 +594,25 @@ Delivery::target_gain ()
MuteMaster::MutePoint mp = MuteMaster::Main; // stupid gcc uninit warning
switch (_role) {
case Main:
mp = MuteMaster::Main;
break;
case Listen:
mp = MuteMaster::Listen;
break;
case Send:
case Insert:
case Aux:
case Foldback:
if (_pre_fader) {
mp = MuteMaster::PreFader;
} else {
mp = MuteMaster::PostFader;
}
break;
case Main:
mp = MuteMaster::Main;
break;
case Listen:
mp = MuteMaster::Listen;
break;
case MasterSend:
mp = MuteMaster::MasterSend;
break;
case Send:
case Insert:
case Aux:
case Foldback:
if (_pre_fader) {
mp = MuteMaster::PreFader;
} else {
mp = MuteMaster::PostFader;
}
break;
}
gain_t desired_gain = _mute_master->mute_gain_at (mp);

View File

@ -612,6 +612,7 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (Location, IsXrun);
REGISTER_CLASS_ENUM (Location, IsCueMarker);
REGISTER_CLASS_ENUM (Location, IsSection);
REGISTER_CLASS_ENUM (Location, IsScene);
REGISTER_BITS (_Location_Flags);
REGISTER_CLASS_ENUM (Track, NoFreeze);
@ -731,6 +732,7 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (Delivery, Main);
REGISTER_CLASS_ENUM (Delivery, Aux);
REGISTER_CLASS_ENUM (Delivery, Foldback);
REGISTER_CLASS_ENUM (Delivery, MasterSend);
REGISTER_BITS (_Delivery_Role);
REGISTER_CLASS_ENUM (MuteMaster, PreFader);
@ -738,6 +740,7 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (MuteMaster, Listen);
REGISTER_CLASS_ENUM (MuteMaster, Main);
REGISTER_CLASS_ENUM (MuteMaster, SurroundSend);
REGISTER_CLASS_ENUM (MuteMaster, MasterSend);
REGISTER_BITS (_MuteMaster_MutePoint);
REGISTER_CLASS_ENUM (IO, Input);

View File

@ -47,9 +47,9 @@ InternalReturn::run (BufferSet& bufs, samplepos_t /*start_sample*/, samplepos_t
return;
}
for (list<InternalSend*>::iterator i = _sends.begin(); i != _sends.end(); ++i) {
if ((*i)->active () && (!(*i)->source_route() || (*i)->source_route()->active())) {
bufs.merge_from ((*i)->get_buffers(), nframes);
for (auto & send : _sends) {
if (send->active () && (!send->source_route() || send->source_route()->active())) {
bufs.merge_from (send->get_buffers(), nframes);
}
}
}

View File

@ -141,6 +141,12 @@ InternalSend::init_gain ()
if (_role == Listen) {
/* send to monitor bus is always at unity */
gain_control ()->set_value (GAIN_COEFF_UNITY, PBD::Controllable::NoGroup);
} else if (_role == MasterSend) {
if (_session.virtual_soundcheck()) {
gain_control ()->set_value (GAIN_COEFF_ZERO, PBD::Controllable::NoGroup);
} else {
gain_control ()->set_value (GAIN_COEFF_UNITY, PBD::Controllable::NoGroup);
}
} else {
/* aux sends start at -inf dB */
gain_control ()->set_value (GAIN_COEFF_ZERO, PBD::Controllable::NoGroup);
@ -150,6 +156,8 @@ InternalSend::init_gain ()
int
InternalSend::use_target (std::shared_ptr<Route> sendto, bool update_name)
{
assert (sendto);
if (_send_to) {
propagate_solo ();
_send_to->remove_send_from_internal_return (this);
@ -165,9 +173,12 @@ InternalSend::use_target (std::shared_ptr<Route> sendto, bool update_name)
_meter->configure_io (_send_to->internal_return ()->input_streams (), _send_to->internal_return ()->input_streams ());
_send_delay->configure_io (_send_to->internal_return ()->input_streams (), _send_to->internal_return ()->input_streams ());
reset_panner ();
if (_role == MasterSend) {
_panshell->set_linked_to_route (false);
}
if (update_name) {
set_name (sendto->name ());
}
@ -455,7 +466,6 @@ InternalSend::after_connect ()
if ((sendto = _session.route_by_id (_send_to_id)) == 0) {
error << string_compose (_("%1 - cannot find any track/bus with the ID %2 to connect to"), display_name (), _send_to_id) << endmsg;
cerr << string_compose (_("%1 - cannot find any track/bus with the ID %2 to connect to"), display_name (), _send_to_id) << endl;
return -1;
}

View File

@ -801,6 +801,11 @@ Location::set_scene_change (std::shared_ptr<SceneChange> sc)
{
if (_scene_change != sc) {
_scene_change = sc;
if (_scene_change) {
_flags = Flags (_flags | IsScene);
} else {
_flags = Flags (_flags & ~IsScene);
}
_session.set_dirty ();
emit_signal (Scene); /* EMIT SIGNAL */
}
@ -2046,6 +2051,60 @@ Locations::clear_cue_markers (samplepos_t start, samplepos_t end)
return removed_at_least_one;
}
bool
Locations::clear_scene_markers (samplepos_t start, samplepos_t end)
{
TempoMap::SharedPtr tmap (TempoMap::use());
Temporal::Beats sb;
Temporal::Beats eb;
bool have_beats = false;
vector<Location*> r;
bool removed_at_least_one = false;
{
Glib::Threads::RWLock::WriterLock lm (_lock);
for (LocationList::iterator i = locations.begin(); i != locations.end(); ) {
if ((*i)->is_scene()) {
Location* l (*i);
if (l->start().time_domain() == AudioTime) {
samplepos_t when = l->start().samples();
if (when >= start && when < end) {
i = locations.erase (i);
r.push_back (l);
continue;
}
} else {
if (!have_beats) {
sb = tmap->quarters_at (timepos_t (start));
eb = tmap->quarters_at (timepos_t (end));
have_beats = true;
}
Temporal::Beats when = l->start().beats();
if (when >= sb && when < eb) {
r.push_back (l);
i = locations.erase (i);
continue;
}
}
removed_at_least_one = true;
}
++i;
}
} /* end lock scope */
for (auto & l : r) {
removed (l); /* EMIT SIGNAL */
delete l;
}
return removed_at_least_one;
}
void
Locations::start_domain_bounce (Temporal::DomainBounceInfo& cmd)
{

View File

@ -108,6 +108,22 @@ MonitorProcessor::allocate_channels (uint32_t size)
while (_channels.size() < size) {
_channels.push_back (new ChannelRecord (n));
/* update solo_cnt when Solo changes */
std::shared_ptr<Controllable> sc = _channels.back()->soloed_control;
std::weak_ptr<Controllable> wc (sc);
sc->Changed.connect_same_thread (*this, [this, wc](bool, PBD::Controllable::GroupControlDisposition)
{
std::shared_ptr<Controllable> ac = wc.lock ();
if (ac && ac->get_value () > 0) {
solo_cnt++;
} else {
if (solo_cnt > 0) {
solo_cnt--;
}
}
update_monitor_state ();
});
}
}
@ -391,18 +407,8 @@ MonitorProcessor::set_cut (uint32_t chn, bool yn)
void
MonitorProcessor::set_solo (uint32_t chn, bool solo)
{
if (solo != _channels[chn]->soloed) {
_channels[chn]->soloed = solo;
if (solo) {
solo_cnt++;
} else {
if (solo_cnt > 0) {
solo_cnt--;
}
}
}
update_monitor_state ();
_channels[chn]->soloed = solo;
/* update_monitor_state is called via the Changed signal */
}
void

View File

@ -39,7 +39,7 @@ using namespace std;
const string MuteMaster::xml_node_name (X_("MuteMaster"));
const MuteMaster::MutePoint MuteMaster::AllPoints = MuteMaster::MutePoint(
PreFader|PostFader|Listen|Main|SurroundSend);
PreFader|PostFader|Listen|Main|SurroundSend|MasterSend);
MuteMaster::MuteMaster (Session& s, Muteable& m, const std::string&)
: SessionHandleRef (s)
@ -70,6 +70,10 @@ MuteMaster::MuteMaster (Session& s, Muteable& m, const std::string&)
if (Config->get_mute_affects_surround_sends ()) {
_mute_point = MutePoint (_mute_point | SurroundSend);
}
if (Config->get_mute_affects_master_sends ()) {
_mute_point = MutePoint (_mute_point | MasterSend);
}
}
void

View File

@ -79,7 +79,7 @@ PannerShell::PannerShell (string name, Session& s, std::shared_ptr<Pannable> p,
{
if (is_send) {
_pannable_internal.reset(new Pannable (s, tdp));
if (Config->get_link_send_and_route_panner()) {
if (!Profile->get_livetrax() && Config->get_link_send_and_route_panner()) {
_panlinked = true;
} else {
_panlinked = false;
@ -200,8 +200,7 @@ PannerShell::set_state (const XMLNode& node, int version)
if ((*niter)->get_property (X_("uri"), str)) {
PannerInfo* p = PannerManager::instance().get_by_uri(str);
if (p) {
_panner.reset (p->descriptor.factory (
_is_send ? _pannable_internal : _pannable_route, _session.get_speakers ()));
_panner.reset (p->descriptor.factory (_is_send ? _pannable_internal : _pannable_route, _session.get_speakers ()));
_current_panner_uri = p->descriptor.panner_uri;
_panner_gui_uri = p->descriptor.gui_uri;
if (_is_send) {
@ -473,7 +472,7 @@ PannerShell::set_linked_to_route (bool onoff)
*/
if (pannable()) {
XMLNode state = pannable()->get_state();
pannable()->set_state(state, Stateful::loading_state_version);
pannable()->set_state (state, Stateful::loading_state_version);
}
_panlinked = onoff;
@ -489,5 +488,6 @@ PannerShell::set_linked_to_route (bool onoff)
}
_session.set_dirty ();
}
PannableChanged();
}

View File

@ -83,6 +83,7 @@
#include "ardour/lv2_plugin.h"
#include "ardour/plugin.h"
#include "ardour/plugin_manager.h"
#include "ardour/profile.h"
#include "ardour/rc_configuration.h"
#include "ardour/search_paths.h"
@ -194,6 +195,10 @@ PluginManager::PluginManager ()
, _cancel_scan_timeout_all (false)
, _enable_scan_timeout (false)
{
if (Profile->get_livetrax()) {
return;
}
char* s;
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined VST3_SUPPORT
@ -458,6 +463,10 @@ PluginManager::conceal_duplicates (ARDOUR::PluginInfoList* old, ARDOUR::PluginIn
void
PluginManager::refresh (bool cache_only)
{
if (Profile->get_livetrax()) {
return;
}
Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
if (!lm.locked()) {

View File

@ -135,7 +135,9 @@ PortManager::AudioInputPort::silence (pframes_t n_samples)
void
PortManager::AudioInputPort::process (Sample const* buf, pframes_t n_samples, bool reset)
{
scope->write (buf, n_samples);
if (!Profile->get_livetrax()) {
scope->write (buf, n_samples);
}
float level = reset ? 0 : meter->level;
level = compute_peak (buf, n_samples, level);

View File

@ -281,9 +281,27 @@ Route::init ()
_volume.reset (new Amp (_session, X_("LAN Amp"), _volume_control, false));
_volume->set_display_to_user (false);
_volume->deactivate ();
if (Profile->get_livetrax()) {
_intreturn.reset (new InternalReturn (_session, tdp));
_intreturn->activate ();
}
}
_main_outs->activate ();
if (Profile->get_livetrax() && is_track()) {
/* We need a separate gain control the main outs, because we
* will use that when switching between stereo outs and direct
* outs for virtual soundcheck
*/
_volume_control.reset (new GainControl (_session, MainOutVolume));
_volume_control->set_flag (Controllable::NotAutomatable);
_main_outs->set_gain_control (_volume_control);
_volume_control->set_value (_session.virtual_soundcheck() ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO, PBD::Controllable::NoGroup);
}
if (is_monitor()) {
/* where we listen to tracks */
_intreturn.reset (new MonitorReturn (_session, tdp));
@ -1457,7 +1475,13 @@ Route::clear_processors (Placement p)
bool
Route::is_internal_processor (std::shared_ptr<Processor> p) const
{
if (p == _amp || p == _meter || p == _main_outs || p == _delayline || p == _trim || p == _polarity || (_volume && p == _volume) || (_triggerbox && p == _triggerbox) || (_surround_return && p == _surround_return) || (_surround_send && p == _surround_send)) {
if (p == _amp || p == _meter || p == _main_outs || p == _delayline || p == _trim ||
p == _polarity || (_volume && p == _volume) ||
(_triggerbox && p == _triggerbox) ||
(_surround_return && p == _surround_return) ||
(_surround_send && p == _surround_send) ||
(_master_send && p == _master_send) ||
(is_master() && p == _intreturn)) {
return true;
}
return false;
@ -1847,10 +1871,11 @@ Route::try_configure_processors_unlocked (ChanCount in, ProcessorStreams* err)
if ((*p)->can_support_io_configuration(in, out)) {
if (std::dynamic_pointer_cast<Delivery> (*p)
&& std::dynamic_pointer_cast<Delivery> (*p)->role() == Delivery::Main
&& !is_auditioner()
&& (is_monitor() || _strict_io || Profile->get_mixbus ())) {
if (!Profile->get_livetrax()
&& std::dynamic_pointer_cast<Delivery> (*p)
&& std::dynamic_pointer_cast<Delivery> (*p)->role() == Delivery::Main
&& !is_auditioner()
&& (is_monitor() || _strict_io || Profile->get_mixbus ())) {
/* with strict I/O the panner + output are forced to
* follow the last processor's output.
*
@ -2522,41 +2547,49 @@ Route::customize_plugin_insert (std::shared_ptr<Processor> proc, uint32_t count,
}
bool
Route::set_strict_io (const bool enable)
Route::set_strict_io (bool enable)
{
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
if (_strict_io != enable) {
_strict_io = enable;
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
if (Profile->get_livetrax()) {
/* cannot be disabled, and is set to true by default */
// enable = true;
}
if (_strict_io == enable) {
return true;
}
_strict_io = enable;
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p) {
std::shared_ptr<PluginInsert> pi;
if ((pi = std::dynamic_pointer_cast<PluginInsert>(*p)) != 0) {
pi->set_strict_io (_strict_io);
}
}
list<pair<ChanCount, ChanCount> > c = try_configure_processors_unlocked (n_inputs (), 0);
if (c.empty()) {
// not possible
_strict_io = !enable; // restore old value
for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p) {
std::shared_ptr<PluginInsert> pi;
if ((pi = std::dynamic_pointer_cast<PluginInsert>(*p)) != 0) {
pi->set_strict_io (_strict_io);
}
}
list<pair<ChanCount, ChanCount> > c = try_configure_processors_unlocked (n_inputs (), 0);
if (c.empty()) {
// not possible
_strict_io = !enable; // restore old value
for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p) {
std::shared_ptr<PluginInsert> pi;
if ((pi = std::dynamic_pointer_cast<PluginInsert>(*p)) != 0) {
pi->set_strict_io (_strict_io);
}
}
return false;
}
lm.release ();
configure_processors (0);
lx.release ();
processors_changed (RouteProcessorChange (RouteProcessorChange::CustomPinChange, false)); /* EMIT SIGNAL */
_session.set_dirty ();
return false;
}
lm.release ();
configure_processors (0);
lx.release ();
processors_changed (RouteProcessorChange (RouteProcessorChange::CustomPinChange, false)); /* EMIT SIGNAL */
_session.set_dirty ();
return true;
}
@ -3305,7 +3338,16 @@ Route::set_processor_state (XMLNode const& node, int version, XMLProperty const*
if (prop->value() == "intsend") {
processor.reset (new InternalSend (_session, _pannable, _mute_master, std::dynamic_pointer_cast<ARDOUR::Route>(shared_from_this()), std::shared_ptr<Route>(), Delivery::Aux, true));
XMLProperty const * role_prop = node.property (X_("role"));
if (role_prop && role_prop->value() == "MasterSend") {
if (Profile->get_livetrax()) {
create_master_send ();
assert (_master_send);
processor = _master_send;
}
} else {
processor.reset (new InternalSend (_session, _pannable, _mute_master, std::dynamic_pointer_cast<ARDOUR::Route>(shared_from_this()), std::shared_ptr<Route>(), Delivery::Aux, true));
}
} else if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
prop->value() == "lv2" ||
@ -3484,6 +3526,61 @@ Route::enable_monitor_send ()
configure_processors (0);
}
void
Route::remove_monitor_send ()
{
/* caller needs to hold process lock */
if (!_monitor_send) {
return;
}
ProcessorStreams err;
remove_processor (_monitor_send, &err, false);
_monitor_send.reset ();
}
void
Route::create_master_send ()
{
_master_send.reset (new InternalSend (_session, pannable(), _mute_master, std::dynamic_pointer_cast<Route> (shared_from_this()), _session.master_out(), Delivery::MasterSend, false));
_master_send->set_display_to_user (false);
}
void
Route::enable_master_send()
{
if (!Profile->get_livetrax()) {
return;
}
/* Caller must hold process lock */
assert (!AudioEngine::instance()->process_lock().trylock());
/* master sends are for tracks only */
assert (is_track());
/* make sure we have one */
if (!_master_send) {
/* An internal send with its own panner to deliver to the master bus */
create_master_send ();
}
/* set it up */
configure_processors (0);
}
void
Route::remove_master_send ()
{
/* caller needs to hold process lock */
if (!_master_send) {
return;
}
ProcessorStreams err;
remove_processor (_master_send, &err, false);
_master_send.reset ();
}
/** Add an aux send to a route.
* @param route route to send to.
* @param before Processor to insert before, or 0 to insert at the end.
@ -3571,18 +3668,6 @@ Route::add_foldback_send (std::shared_ptr<Route> route, bool post_fader)
return 0;
}
void
Route::remove_monitor_send ()
{
/* caller needs to hold process lock */
if (!_monitor_send) {
return;
}
ProcessorStreams err;
remove_processor (_monitor_send, &err, false);
_monitor_send.reset ();
}
void
Route::set_comment (string cmt, void *src)
{
@ -4848,13 +4933,24 @@ Route::pannable() const
std::shared_ptr<Panner>
Route::panner() const
{
/* may be null ! */
/* may return null ! */
if (Profile->get_livetrax() && _master_send) {
return _master_send->panner_shell()->panner();
}
return _main_outs->panner_shell()->panner();
}
std::shared_ptr<PannerShell>
Route::panner_shell() const
{
/* may return null ! */
if (Profile->get_livetrax() && _master_send) {
return _master_send->panner_shell();
}
return _main_outs->panner_shell();
}
@ -5284,6 +5380,11 @@ Route::setup_invisible_processors ()
new_processors.push_back (_surround_send);
}
if (Profile->get_livetrax() && _master_send) {
assert (!_master_send->display_to_user());
new_processors.push_back (_master_send);
}
/* MAIN OUTS */
assert (_main_outs);

View File

@ -36,6 +36,7 @@
#include "ardour/io.h"
#include "ardour/meter.h"
#include "ardour/panner_shell.h"
#include "ardour/profile.h"
#include "ardour/send.h"
#include "ardour/session.h"
@ -72,9 +73,17 @@ Send::name_and_id_new_send (Session& s, Role r, uint32_t& bitslot, bool ignore_b
return string ();
}
switch (r) {
case Delivery::Aux:
return string_compose (_("aux %1"), (bitslot = s.next_aux_send_id ()));
if (Profile->get_livetrax()) {
/* The only type of aux send possible with livetrax */
return _("master");
} else {
return string_compose (_("aux %1"), (bitslot = s.next_aux_send_id ()));
}
case Delivery::Listen:
bitslot = 0; /* unused */
return _("listen"); // no ports, no need for numbering
@ -82,6 +91,8 @@ Send::name_and_id_new_send (Session& s, Role r, uint32_t& bitslot, bool ignore_b
return string_compose (_("send %1"), (bitslot = s.next_send_id ()));
case Delivery::Foldback:
return string_compose (_("foldback %1"), (bitslot = s.next_aux_send_id ()));
case Delivery::MasterSend:
return string_compose (_("master %1"), (bitslot = s.next_aux_send_id ()));
default:
fatal << string_compose (_("programming error: send created using role %1"), enum_2_string (r)) << endmsg;
abort(); /*NOTREACHED*/
@ -389,7 +400,7 @@ Send::set_state (const XMLNode& node, int version)
*/
if ((prop = node.property ("bitslot")) == 0) {
if (_role == Delivery::Aux || _role == Delivery::Foldback) {
if (_role == Delivery::Aux || _role == Delivery::Foldback || _role == Delivery::MasterSend) {
_bitslot = _session.next_aux_send_id ();
} else if (_role == Delivery::Send) {
_bitslot = _session.next_send_id ();
@ -398,7 +409,7 @@ Send::set_state (const XMLNode& node, int version)
_bitslot = 0;
}
} else {
if (_role == Delivery::Aux || _role == Delivery::Foldback) {
if (_role == Delivery::Aux || _role == Delivery::Foldback || _role == Delivery::MasterSend) {
_session.unmark_aux_send_id (_bitslot);
_bitslot = string_to<uint32_t>(prop->value());
_session.mark_aux_send_id (_bitslot);
@ -551,6 +562,10 @@ Send::set_name (const string& new_name)
bool
Send::display_to_user () const
{
if (_role == MasterSend && Profile->get_livetrax()) {
return false;
}
/* we ignore Deliver::_display_to_user */
if (_role == Listen || _role == Foldback) {

View File

@ -84,6 +84,8 @@
#include "ardour/filename_extensions.h"
#include "ardour/gain_control.h"
#include "ardour/graph.h"
#include "ardour/internal_return.h"
#include "ardour/internal_send.h"
#include "ardour/io_plug.h"
#include "ardour/luabindings.h"
#include "ardour/lv2_plugin.h"
@ -345,6 +347,8 @@ Session::Session (AudioEngine &eng,
, _pending_cue (-1)
, _active_cue (-1)
, tb_with_filled_slots (0)
, _no_file_format_reset (0)
, _virtual_soundcheck (false)
{
_suspend_save.store (0);
_playback_load.store (0);
@ -1116,7 +1120,9 @@ Session::remove_monitor_section ()
void
Session::add_monitor_section ()
{
RouteList rl;
if (Profile->get_livetrax()) {
return;
}
if (!_engine.running()) {
error << _("Cannot create monitor section while the engine is offline.") << endmsg;
@ -1127,6 +1133,7 @@ Session::add_monitor_section ()
return;
}
std::shared_ptr<Route> r (new Route (*this, _("Monitor"), PresentationInfo::MonitorOut, DataType::AUDIO));
if (r->init ()) {
@ -1144,6 +1151,7 @@ Session::add_monitor_section ()
return;
}
RouteList rl;
rl.push_back (r);
add_routes (rl, false, false, 0);
@ -1284,6 +1292,34 @@ Session::setup_route_monitor_sends (bool enable, bool need_process_lock)
}
}
void
Session::setup_route_master_sends (bool enable, bool need_process_lock)
{
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock (), Glib::Threads::NOT_LOCK);
if (need_process_lock) {
/* Hold process lock while doing this so that we don't hear bits and
* pieces of audio as we work on each route.
*/
lx.acquire();
}
std::shared_ptr<RouteList const> rl = routes.reader ();
ProcessorChangeBlocker pcb (this, false /* XXX */);
for (auto const& x : *rl) {
if (x->is_track()) {
if (enable) {
x->enable_master_send ();
} else {
x->remove_master_send ();
}
}
}
if (auditioner) {
auditioner->connect ();
}
}
void
Session::reset_monitor_section ()
@ -1610,7 +1646,7 @@ Session::hookup_io ()
_state_of_the_state = StateOfTheState (_state_of_the_state | InitialConnecting);
if (!auditioner) {
if (!Profile->get_livetrax() && !auditioner) {
/* we delay creating the auditioner till now because
it makes its own connections to ports.
@ -3019,6 +3055,8 @@ Session::new_audio_track (int input_channels, int output_channels, RouteGroup* r
goto failed;
}
std::cerr << "new track with " << output_channels << " channels\n";
if (track->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
error << string_compose (
_("cannot configure %1 in/%2 out configuration for new audio track"),
@ -3508,7 +3546,7 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
* we will resort when done.
*/
if (!_monitor_out && !loading() && !input_auto_connect && !output_auto_connect) {
if (!_monitor_out && !loading() && !input_auto_connect && !output_auto_connect && !Profile->get_livetrax()) {
resort_routes_using (r);
}
}
@ -3540,7 +3578,10 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
}
if (r->is_monitor()) {
_monitor_out = r;
/* ignore for livetrax */
if (!Profile->get_livetrax()) {
_monitor_out = r;
}
}
if (r->is_surround_master()) {
@ -3601,27 +3642,38 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
ARDOUR::GUIIdle ();
}
ensure_stripable_sort_order ();
if (Profile->get_livetrax()) {
reassign_track_numbers ();
}
}
if (_monitor_out && !loading()) {
if (!loading()) {
Glib::Threads::Mutex::Lock lm (_engine.process_lock());
for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
if ((*x)->can_monitor ()) {
(*x)->enable_monitor_send ();
if (_monitor_out) {
for (auto & r : new_routes) {
if (r->can_monitor ()) {
r->enable_monitor_send ();
}
}
}
if (_surround_master) {
for (auto & r : new_routes) {
r->enable_surround_send ();
}
}
if (Profile->get_livetrax ()) {
for (auto & r : new_routes) {
if (r->is_track()) {
r->enable_master_send ();
}
}
}
}
if (_surround_master && !loading()) {
Glib::Threads::Mutex::Lock lm (_engine.process_lock());
for (auto & r : new_routes) {
r->enable_surround_send ();
}
}
reassign_track_numbers ();
}
void
@ -4578,15 +4630,19 @@ Session::reassign_track_numbers ()
StateProtector sp (this);
for (RouteList::iterator i = r.begin(); i != r.end(); ++i) {
assert (!(*i)->is_auditioner());
if (std::dynamic_pointer_cast<Track> (*i)) {
(*i)->set_track_number(++tn);
} else if (!(*i)->is_main_bus ()) {
(*i)->set_track_number(--bn);
for (auto & route : r) {
assert (!route->is_auditioner());
if (std::dynamic_pointer_cast<Track> (route)) {
route->set_track_number(++tn);
} else if (!route->is_main_bus ()) {
route->set_track_number(--bn);
}
std::shared_ptr<TriggerBox> tb = (*i)->triggerbox();
if (Profile->get_livetrax() && !route->is_auditioner() && route->is_track()) {
livetrax_auto_connect_route (route);
}
std::shared_ptr<TriggerBox> tb = (route)->triggerbox();
if (tb) {
tb->set_order (trigger_order);
trigger_order++;
@ -4597,8 +4653,8 @@ Session::reassign_track_numbers ()
_track_number_decimals = decimals;
if (decimals_changed && config.get_track_name_number ()) {
for (RouteList::iterator i = r.begin(); i != r.end(); ++i) {
std::shared_ptr<Track> t = std::dynamic_pointer_cast<Track> (*i);
for (auto & route : r) {
std::shared_ptr<Track> t = std::dynamic_pointer_cast<Track> (route);
if (t) {
t->resync_take_name ();
}
@ -6071,9 +6127,27 @@ Session::unmark_insert_id (uint32_t id)
}
}
void
Session::enable_file_format_reset ()
{
if (_no_file_format_reset) {
_no_file_format_reset--;
}
}
void
Session::disable_file_format_reset ()
{
_no_file_format_reset++;
}
void
Session::reset_native_file_format ()
{
if (_no_file_format_reset) {
return;
}
std::shared_ptr<RouteList const> rl = routes.reader ();
for (auto const& i : *rl) {
@ -6446,7 +6520,7 @@ Session::write_one_track (Track& track, samplepos_t start, samplepos_t end,
plist.add (Properties::whole_file, true);
plist.add (Properties::length, len); //ToDo: in nutempo, if the Range is snapped to bbt, this should be in bbt (?)
plist.add (Properties::name, region_name_from_path (srcs.front()->name(), true)); // TODO: allow custom region-name when consolidating
plist.add (Properties::name, region_name_from_path (srcs.front()->name(), true)); // TODO: allow custom region-name when consolidating
plist.add (Properties::tags, "(bounce)");
result = RegionFactory::create (srcs, plist, true);
@ -7653,6 +7727,13 @@ Session::cut_copy_section (timepos_t const& start_, timepos_t const& end_, timep
commit_reversible_command ();
}
void
Session::livetrax_auto_connect_route (std::shared_ptr<Route> route)
{
ChanCount ignored;
auto_connect_route (route, true, true, ignored, ignored, ignored, ignored);
}
void
Session::auto_connect_route (std::shared_ptr<Route> route,
bool connect_inputs,
@ -7694,6 +7775,109 @@ Session::queue_latency_recompute ()
auto_connect_thread_wakeup ();
}
void
Session::livetrax_auto_connect (std::shared_ptr<Route> route)
{
vector<string> physinputs;
vector<string> physoutputs;
get_physical_ports (physinputs, physoutputs, DataType::AUDIO);
AudioBackend::ChannelMask const & input_channel_mask ( _engine.current_backend()->input_channel_mask());
AudioBackend::ChannelMask const & output_channel_mask ( _engine.current_backend()->output_channel_mask());
route->input()->disconnect (this);
route->output()->disconnect (this);
vector<string>::size_type n;
vector<string>::size_type ichn;
vector<string>::size_type ochn;
vector<string>::size_type i;
vector<string>::size_type start_from;
vector<string>::size_type enabled;
n = route->track_number() - 1;
/* move to the nth enabled input channel */
i = 0;
start_from = 0;
enabled = 0;
while (enabled <= n && i < input_channel_mask.size()) {
if (input_channel_mask[i]) {
start_from = i;
enabled++;
}
++i;
}
n = start_from;
size_t attempts = 0;
size_t limit = physinputs.size();
while (attempts < limit) {
ichn = n % physinputs.size();
if (input_channel_mask[ichn]) {
route->input()->connect (route->input()->ports().port (DataType::AUDIO, 0), physinputs[ichn], this);
break;
} else {
/* reduce limit because we found a channel that can't be used */
--limit;
}
++attempts;
++n;
if (n >= physinputs.size()) {
n = 0;
}
}
n = route->track_number() - 1;
i = 0;
start_from = 0;
enabled = 0;
while (enabled <= n && i < output_channel_mask.size()) {
if (output_channel_mask[i]) {
start_from = i;
enabled++;
}
++i;
}
n = start_from;
attempts = 0;
limit = physoutputs.size();
while (attempts < limit) {
ochn = n % physoutputs.size();
if (output_channel_mask[ochn]) {
route->output()->connect (route->output()->ports().port (DataType::AUDIO, 0), physoutputs[ochn], this);
break;
} else {
/* reduce limit because we found a channel that can't be used */
--limit;
}
++attempts;
++n;
if (n >= physinputs.size()) {
n = 0;
}
}
DEBUG_TRACE (DEBUG::PortConnectAuto, string_compose ("livetrax auto connect %1 [%2] to %3 and %4\n", route->name(), route->track_number(),
physinputs[ichn],
physoutputs[ochn]));
}
void
Session::auto_connect (const AutoConnectRequest& ar)
{
@ -7705,6 +7889,11 @@ Session::auto_connect (const AutoConnectRequest& ar)
return;
}
if (Profile->get_livetrax() && !route->is_auditioner() && route->is_track()) {
livetrax_auto_connect (route);
return;
}
/* If both inputs and outputs are auto-connected to physical ports,
* use the max of input and output offsets to ensure auto-connected
* port numbers always match up (e.g. the first audio input and the
@ -7734,7 +7923,6 @@ Session::auto_connect (const AutoConnectRequest& ar)
vector<string> physinputs;
vector<string> physoutputs;
/* for connecting track inputs we only want MIDI ports marked
* for "music".
*/
@ -7759,6 +7947,8 @@ Session::auto_connect (const AutoConnectRequest& ar)
DEBUG_TRACE (DEBUG::PortConnectAuto, "Failed to auto-connect input.");
break;
}
DEBUG_TRACE (DEBUG::PortConnectAuto, string_compose ("autoconnected input %1/%2 [%4]to %3\n", route->name(), i, port, route->track_number()));
}
}
@ -7785,6 +7975,8 @@ Session::auto_connect (const AutoConnectRequest& ar)
DEBUG_TRACE (DEBUG::PortConnectAuto, "Failed to auto-connect output.");
break;
}
DEBUG_TRACE (DEBUG::PortConnectAuto, string_compose ("autoconnected output %1/%2 [%4]to %3\n", route->name(), i, port, route->track_number()));
}
}
}
@ -8117,3 +8309,59 @@ Session::foreach_route (void (Route::*method)())
}
}
void
Session::enable_virtual_soundcheck ()
{
set_virtual_soundcheck (true);
}
void
Session::disable_virtual_soundcheck ()
{
set_virtual_soundcheck (false);
}
void
Session::set_virtual_soundcheck (bool yn)
{
if (!Profile->get_livetrax()) {
return;
}
std::shared_ptr<RouteList const> rl = routes.reader ();
std::shared_ptr<AutomationControlList> master_sends (new AutomationControlList);
std::shared_ptr<AutomationControlList> main_outs (new AutomationControlList);
gain_t main_val = (yn ? 1. : 0.);
gain_t send_val = (yn ? 0. : 1.);
for (auto & route : *rl) {
if (!route->is_track()) {
continue;
}
master_sends->push_back (route->master_send()->gain_control());
main_outs->push_back (route->main_outs()->gain_control());
}
if (!master_sends->empty()) {
set_controls (master_sends, send_val, PBD::Controllable::NoGroup);
set_controls (main_outs, main_val, PBD::Controllable::NoGroup);
}
_virtual_soundcheck = yn;
VirtualSoundCheckChanged (yn); /* EMIT SIGNAL */
}
bool
Session::virtual_soundcheck () const
{
if (!Profile->get_livetrax()) {
return false;
}
return _virtual_soundcheck;
}

View File

@ -657,7 +657,7 @@ Session::create (const string& session_template, BusProfile const * bus_profile,
return rv;
}
if (Config->get_use_monitor_bus()) {
if (Config->get_use_monitor_bus() && !Profile->get_livetrax()) {
add_monitor_section ();
}
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2023 Ayan Shafqat <ayan.x.shafqat@gmail.com>
* Copyright (C) 2024 Robin Gareus <robin@gareus.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -50,7 +51,7 @@ x86_avx512f_compute_peak(const float *src, uint32_t nframes, float current)
break;
}
if (IS_ALIGNED_TO(src, sizeof(__m256))) {
if (frames >=8 && IS_ALIGNED_TO(src, sizeof(__m256))) {
__m512 x = _mm512_castps256_ps512(_mm256_load_ps(src));
x = _mm512_abs_ps(x);
@ -61,7 +62,7 @@ x86_avx512f_compute_peak(const float *src, uint32_t nframes, float current)
continue;
}
if (IS_ALIGNED_TO(src, sizeof(__m128))) {
if (frames >= 4 && IS_ALIGNED_TO(src, sizeof(__m128))) {
__m512 x = _mm512_castps128_ps512(_mm_load_ps(src));
x = _mm512_abs_ps(x);
@ -286,7 +287,7 @@ x86_avx512f_find_peaks(const float *src, uint32_t nframes, float *minf, float *m
break;
}
if (IS_ALIGNED_TO(src, sizeof(__m256))) {
if (frames >= 8 && IS_ALIGNED_TO(src, sizeof(__m256))) {
__m512 x = _mm512_castps256_ps512(_mm256_load_ps(src));
zmin = _mm512_min_ps(zmin, x);
@ -297,7 +298,7 @@ x86_avx512f_find_peaks(const float *src, uint32_t nframes, float *minf, float *m
continue;
}
if (IS_ALIGNED_TO(src, sizeof(__m128))) {
if (frames >= 4 && IS_ALIGNED_TO(src, sizeof(__m128))) {
__m512 x = _mm512_castps128_ps512(_mm_load_ps(src));
zmin = _mm512_min_ps(zmin, x);
@ -522,7 +523,7 @@ x86_avx512f_apply_gain_to_buffer(float *dst, uint32_t nframes, float gain)
break;
}
if (IS_ALIGNED_TO(dst, sizeof(__m256))) {
if (frames >= 8 && IS_ALIGNED_TO(dst, sizeof(__m256))) {
__m256 x = _mm256_load_ps(dst);
__m256 y = _mm256_mul_ps(ygain, x);
_mm256_store_ps(dst, y);
@ -531,7 +532,7 @@ x86_avx512f_apply_gain_to_buffer(float *dst, uint32_t nframes, float gain)
continue;
}
if (IS_ALIGNED_TO(dst, sizeof(__m128))) {
if (frames >= 4 && IS_ALIGNED_TO(dst, sizeof(__m128))) {
__m128 x = _mm_load_ps(dst);
__m128 y = _mm_mul_ps(xgain, x);
_mm_store_ps(dst, y);
@ -658,7 +659,8 @@ x86_avx512f_mix_buffers_with_gain(float *dst, const float *src, uint32_t nframes
break;
}
if (IS_ALIGNED_TO(src, sizeof(__m256)) &&
if (frames >= 8 &&
IS_ALIGNED_TO(src, sizeof(__m256)) &&
IS_ALIGNED_TO(dst, sizeof(__m256))) {
__m256 x = _mm256_load_ps(src);
__m256 y = _mm256_load_ps(dst);
@ -672,7 +674,8 @@ x86_avx512f_mix_buffers_with_gain(float *dst, const float *src, uint32_t nframes
continue;
}
if (IS_ALIGNED_TO(src, sizeof(__m128)) &&
if (frames >= 4 &&
IS_ALIGNED_TO(src, sizeof(__m128)) &&
IS_ALIGNED_TO(dst, sizeof(__m128))) {
__m128 x = _mm_load_ps(src);
__m128 y = _mm_load_ps(dst);
@ -826,7 +829,8 @@ x86_avx512f_mix_buffers_no_gain(float *dst, const float *src, uint32_t nframes)
break;
}
if (IS_ALIGNED_TO(src, sizeof(__m256)) &&
if (frames >= 8 &&
IS_ALIGNED_TO(src, sizeof(__m256)) &&
IS_ALIGNED_TO(dst, sizeof(__m256))) {
__m256 x = _mm256_load_ps(src);
__m256 y = _mm256_load_ps(dst);
@ -838,7 +842,8 @@ x86_avx512f_mix_buffers_no_gain(float *dst, const float *src, uint32_t nframes)
continue;
}
if (IS_ALIGNED_TO(src, sizeof(__m128)) &&
if (frames >= 4 &&
IS_ALIGNED_TO(src, sizeof(__m128)) &&
IS_ALIGNED_TO(dst, sizeof(__m128))) {
__m128 x = _mm_load_ps(src);
__m128 y = _mm_load_ps(dst);
@ -989,7 +994,8 @@ x86_avx512f_copy_vector(float *dst, const float *src, uint32_t nframes)
break;
}
if (IS_ALIGNED_TO(src, sizeof(__m256)) &&
if (frames >= 8 &&
IS_ALIGNED_TO(src, sizeof(__m256)) &&
IS_ALIGNED_TO(dst, sizeof(__m256))) {
__m256 x = _mm256_load_ps(src);
_mm256_store_ps(dst, x);
@ -999,7 +1005,8 @@ x86_avx512f_copy_vector(float *dst, const float *src, uint32_t nframes)
continue;
}
if (IS_ALIGNED_TO(src, sizeof(__m128)) &&
if (frames >= 4 &&
IS_ALIGNED_TO(src, sizeof(__m128)) &&
IS_ALIGNED_TO(dst, sizeof(__m128))) {
__m128 x = _mm_load_ps(src);
_mm_store_ps(dst, x);

View File

@ -101,6 +101,7 @@ TrackingText::pointer_motion (Duple const& winpos)
/* move */
set_position (pos);
set_bbox_dirty ();
}
void

View File

@ -117,6 +117,7 @@ namespace Gtkmm2ext {
/* C++ API for rounded rectangles */
LIBGTKMM2EXT_API void rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r=10);
LIBGTKMM2EXT_API void rounded_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r=10);
LIBGTKMM2EXT_API void rounded_top_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r=10);
LIBGTKMM2EXT_API void rounded_top_left_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r=10);
@ -128,6 +129,7 @@ namespace Gtkmm2ext {
/* C API for rounded rectangles */
LIBGTKMM2EXT_API void rectangle (cairo_t*, double x, double y, double w, double h, double r=10);
LIBGTKMM2EXT_API void rounded_rectangle (cairo_t*, double x, double y, double w, double h, double r=10);
LIBGTKMM2EXT_API void rounded_top_rectangle (cairo_t*, double x, double y, double w, double h, double r=10);
LIBGTKMM2EXT_API void rounded_top_left_rectangle (cairo_t*, double x, double y, double w, double h, double r=10);

View File

@ -588,6 +588,12 @@ Gtkmm2ext::container_clear (Gtk::Container& c, bool and_delete)
}
}
void
Gtkmm2ext::rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double /*r*/)
{
cairo_rectangle (context->cobj(), x, y, w, h);
}
void
Gtkmm2ext::rounded_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
{
@ -631,6 +637,12 @@ Gtkmm2ext::rounded_right_half_rectangle (Cairo::RefPtr<Cairo::Context> context,
rounded_right_half_rectangle (context->cobj(), x, y, w, h, r);
}
void
Gtkmm2ext::rectangle (cairo_t* cr, double x, double y, double w, double h, double /*r*/)
{
cairo_rectangle (cr, x, y, w, h);
}
void
Gtkmm2ext::rounded_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
{

View File

@ -220,13 +220,27 @@ public:
boost::detail::yield (i);
}
#if 0 // TODO find a good solition here...
/* if we are not the only user, put the old value into dead_wood.
* if we are the only user, then it is safe to drop it here.
*/
if (!_current_write_old->unique ()) {
_dead_wood.push_back (*_current_write_old);
_dead_wood.push_back (*_current_write_old);
}
#else
/* above ->unique() condition is subject to a race condition.
*
* Particulalry with JACK2 graph-order callbacks arriving
* concurrently to processing, which can lead to heap-use-after-free
* of the RouteList.
*
* std::shared_ptr<T>::use_count documetation reads:
* > In multithreaded environment, the value returned by use_count is approximate
* > (typical implementations use a memory_order_relaxed load).
*/
_dead_wood.push_back (*_current_write_old);
#endif
/* now delete it - if we are the only user, this deletes the
* underlying object. If other users existed, then there will

View File

@ -46,6 +46,7 @@ enum RMIDI_EV_TYPE {
NOTE_OFF,
PROGRAM_CHANGE,
CONTROL_CHANGE,
PITCH_BEND,
};
struct rmidi_event_t {
@ -60,6 +61,10 @@ struct rmidi_event_t {
uint8_t param;
uint8_t value;
} control;
struct {
uint8_t lo;
uint8_t hi;
} bend;
} d;
};
@ -78,8 +83,9 @@ typedef struct _RSSynthChannel {
int8_t midimsgs[128]; // internal, note-off + on in same cycle, sustained-off
int8_t sustain; // sustain pedal pressed
ADSRcfg adsr;
float pitch_bend;
void (*synthesize) (struct _RSSynthChannel* sc,
const uint8_t note, const float vol, const float pc,
const uint8_t note, const float vol, float pc,
const size_t n_samples, float* left, float* right);
} RSSynthChannel;
@ -180,12 +186,16 @@ adsr_env (RSSynthChannel* sc, const uint8_t note)
/* piano like sound w/slight stereo phase */
static void
synthesize_sineP (RSSynthChannel* sc,
const uint8_t note, const float vol, const float fq,
const uint8_t note, const float vol, float fq,
const size_t n_samples, float* left, float* right)
{
size_t i;
float phase = sc->phase[note];
if (sc->pitch_bend != 1) {
fq *= sc->pitch_bend;
}
for (i = 0; i < n_samples; ++i) {
float env = adsr_env (sc, note);
if (sc->adsr_cnt[note] == 0) {
@ -337,7 +347,8 @@ synth_reset_channel (RSSynthChannel* sc)
sc->miditable[k] = 0;
sc->midimsgs[k] = 0;
}
sc->keycomp = 0;
sc->keycomp = 0;
sc->pitch_bend = 1.0;
}
static void
@ -398,6 +409,12 @@ synth_process_midi_event (void* synth, struct rmidi_event_t* ev)
/* params 122-127 are reserved - skip them. */
}
break;
case PITCH_BEND:
{
float st = ((((int)ev->d.bend.hi << 7) | ev->d.bend.lo) - 8192) / 4096.0; // +/- 2 semitones
rs->sc[ev->channel].pitch_bend = powf (2, st / 12.0);
}
break;
default:
break;
}
@ -484,6 +501,11 @@ synth_parse_midi (void* synth, const uint8_t* data, const size_t size)
ev.type = PROGRAM_CHANGE;
ev.d.control.value = data[1] & 0x7f;
break;
case 0xE0:
ev.type = PITCH_BEND;
ev.d.bend.lo = data[1] & 0x7f;
ev.d.bend.hi = data[2] & 0x7f;
break;
default:
return;
}

View File

@ -88,8 +88,7 @@ _gdk_screen_quartz_init (GdkScreenQuartz *screen_quartz)
gdk_screen_get_system_colormap (screen));
nsscreen = [[NSScreen screens] objectAtIndex:0];
gdk_screen_set_resolution (screen,
72.0 * [nsscreen userSpaceScaleFactor]);
gdk_screen_set_resolution (screen, 72.0 /* * [nsscreen userSpaceScaleFactor] */);
gdk_screen_quartz_calculate_layout (screen_quartz);
@ -362,7 +361,7 @@ get_mm_from_pixels (NSScreen *screen, int pixels)
* and 25.4 is the number of millimeters per inch.
*/
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_3
float dpi = [screen userSpaceScaleFactor] * 72.0;
float dpi = /* [screen userSpaceScaleFactor] * */ 72.0;
#else
float dpi = 96.0 / 72.0;
#endif

View File

@ -2826,6 +2826,13 @@ gdk_window_fullscreen (GdkWindow *window)
!WINDOW_IS_TOPLEVEL (window))
return;
if ([impl->toplevel styleMask] & NSWindowStyleMaskFullScreen) {
/* already in full screen, this can happen when a user
* uses the "green button" to maximize the window.
*/
return;
}
geometry = get_fullscreen_geometry (window);
if (!geometry)
{

View File

@ -53,6 +53,7 @@ using namespace std;
ArdourButton::Element ArdourButton::default_elements = ArdourButton::Element (ArdourButton::Edge|ArdourButton::Body|ArdourButton::Text);
ArdourButton::Element ArdourButton::led_default_elements = ArdourButton::Element (ArdourButton::default_elements|ArdourButton::Indicator);
ArdourButton::Element ArdourButton::just_led_default_elements = ArdourButton::Element (ArdourButton::Edge|ArdourButton::Body|ArdourButton::Indicator);
ArdourButton::Tweaks ArdourButton::default_tweaks = ArdourButton::Tweaks (0);
ArdourButton::ArdourButton (Element e, bool toggle)
: _markup (false)
@ -60,7 +61,7 @@ ArdourButton::ArdourButton (Element e, bool toggle)
, _icon (ArdourIcon::NoIcon)
, _icon_render_cb (0)
, _icon_render_cb_data (0)
, _tweaks (Tweaks (0))
, _tweaks (default_tweaks)
, _char_pixel_width (0)
, _char_pixel_height (0)
, _char_avg_pixel_width (0)
@ -108,7 +109,7 @@ ArdourButton::ArdourButton (const std::string& str, Element e, bool toggle)
: _markup (false)
, _elements (e)
, _icon (ArdourIcon::NoIcon)
, _tweaks (Tweaks (0))
, _tweaks (default_tweaks)
, _char_pixel_width (0)
, _char_pixel_height (0)
, _char_avg_pixel_width (0)
@ -300,22 +301,25 @@ ArdourButton::render (Cairo::RefPtr<Cairo::Context> const& ctx, cairo_rectangle_
}
void (*rounded_function)(cairo_t*, double, double, double, double, double);
switch (_corner_mask) {
case 0x1: /* upper left only */
rounded_function = Gtkmm2ext::rounded_top_left_rectangle;
break;
case 0x2: /* upper right only */
rounded_function = Gtkmm2ext::rounded_top_right_rectangle;
break;
case 0x3: /* upper only */
rounded_function = Gtkmm2ext::rounded_top_rectangle;
break;
/* should really have functions for lower right, lower left,
lower only, but for now, we don't
*/
default:
rounded_function = Gtkmm2ext::rounded_rectangle;
if (corner_radius) {
switch (_corner_mask) {
case 0x1: /* upper left only */
rounded_function = Gtkmm2ext::rounded_top_left_rectangle;
break;
case 0x2: /* upper right only */
rounded_function = Gtkmm2ext::rounded_top_right_rectangle;
break;
case 0x3: /* upper only */
rounded_function = Gtkmm2ext::rounded_top_rectangle;
break;
/* should really have functions for lower right, lower left,
lower only, but for now, we don't
*/
default:
rounded_function = Gtkmm2ext::rounded_rectangle;
}
} else {
rounded_function = Gtkmm2ext::rectangle;
}
// draw edge (filling a rect underneath, rather than stroking a border on top, allows the corners to be lighter-weight.
@ -1211,10 +1215,9 @@ ArdourButton::on_focus_out_event (GdkEventFocus* ev)
}
bool
ArdourButton::on_key_release_event (GdkEventKey *ev) {
if (_act_on_release && _focused &&
(ev->keyval == GDK_space || ev->keyval == GDK_Return))
{
ArdourButton::on_key_release_event (GdkEventKey *ev)
{
if (_act_on_release && _focused && (ev->keyval == GDK_space || ev->keyval == GDK_Return)) {
if (_auto_toggle && !_action) {
set_active (!get_active ());
}
@ -1228,12 +1231,11 @@ ArdourButton::on_key_release_event (GdkEventKey *ev) {
}
bool
ArdourButton::on_key_press_event (GdkEventKey *ev) {
if (!_act_on_release && _focused &&
(ev->keyval == GDK_space || ev->keyval == GDK_Return))
{
ArdourButton::on_key_press_event (GdkEventKey *ev)
{
if (!_act_on_release && _focused && (ev->keyval == GDK_space || ev->keyval == GDK_Return)) {
if (_auto_toggle && !_action) {
set_active (!get_active ());
set_active (!get_active ());
}
signal_clicked();
if (_action) {

View File

@ -69,6 +69,9 @@ class LIBWIDGETS_API ArdourButton : public CairoWidget , public Gtkmm2ext::Activ
ForceFlat = 0x20,
};
static Tweaks default_tweaks;
static void set_default_tweaks (Tweaks t) { default_tweaks = t; }
Tweaks tweaks() const { return _tweaks; }
void set_tweaks (Tweaks);