Compare commits

...

251 Commits

Author SHA1 Message Date
Robin Gareus 6e0c5e6a34
Unify build scripts w/derivative projects 2024-05-19 01:40:02 +02:00
Robin Gareus 897610a047
Fix macOS builds (after 93e1e1c1f2) 2024-05-19 01:04:42 +02:00
Paul Davis f1e7ab08c7 no need to lookup smart mode action, it is cached 2024-05-18 12:24:23 -06:00
Paul Davis 6ed9835677 emove some sneakily hidden indirect references to no-longer existing rulers 2024-05-18 07:20:14 -06:00
Robin Gareus 6fbf2f37d9
Set meter-height depending on configured fader-length
Previously when len was zero, FastMeter enforced a length
of at least 250px.
2024-05-18 01:44:28 +02:00
Robin Gareus 4ec86a2657
Add API to query Fader orientation 2024-05-18 01:42:44 +02:00
Robin Gareus cd2db2c3aa
NO-OP: whitespace 2024-05-17 17:25:45 +02:00
Robin Gareus 5f52329bed
Update mixer and lock icon 2024-05-17 17:25:41 +02:00
Paul Davis 907cf66a63 restructure ruler context menu 2024-05-17 09:08:22 -06:00
Paul Davis 553e534455 remove a number of canvas items that no longer exist after ruler consolidation 2024-05-17 09:07:00 -06:00
Paul Davis fc194237eb Locations::clear_ranges() now removes punch & loop ranges 2024-05-17 09:05:27 -06:00
Paul Davis 93e1e1c1f2 remove Cue, CD, Scene, Punch, Loop rulers, consolidate to just a pair (ranges, locations)
a menu allows choosing between all markers or 1 specific type, and all ranges or 1 specific type

more work required on menu structure and menu options/dialogs to specify the type of new location
and range marker creation
2024-05-16 22:58:55 -06:00
Robin Gareus 9d046af47a Update Lua allocator for sessions scripts
* increase memory pool (bindings alone require 1.5 MB), and all session
  scripts have a shared memory pool.
* use TLSF (like Lua DSP processors) - this fixes an issue with atomics
  (notably int62_t, temporal) on macOS and ARM, which need to be
  aligned.
2024-05-15 20:18:21 +02:00
Robin Gareus afb519cd84
Bump required boost version to 1.68 (for optional::has_value) 2024-05-15 18:50:17 +02:00
Robin Gareus 1f0ee56726
Fix Lua Session scripts (amend df12126909) 2024-05-15 17:33:59 +02:00
Robin Gareus b3df8ea6ef
Expose UI config fonts to libwidgets
Currently this is only for the benefit of derivative projects.
2024-05-15 17:02:35 +02:00
agfline fc1377ae46
AAF: set session name from AAF filename instead of AAF composition name
https://github.com/agfline/LibAAF/issues/5#issuecomment-1952193515
2024-05-15 04:51:36 +02:00
Robin Gareus 7b75748299
Revert "As we've yet to implement user options, let's prefer AAF filenames rather than extracting an internal Comp name"
This reverts commit 2e55f4452f.
2024-05-15 04:49:43 +02:00
Robin Gareus 0bac1e07f5
There is no TraxLive here (amend a0e2749) 2024-05-15 03:35:23 +02:00
Robin Gareus a0e27495c6
Abstract base class for ArdourFader
This allows derivative projects to use other fader
render implementations.
2024-05-15 02:41:37 +02:00
Robin Gareus dad32d8b11
Clean up slider-controller includes 2024-05-14 23:41:51 +02:00
Robin Gareus 3c524098b4
Fix CC event for DM10-mkII Plugin 2024-05-14 22:07:31 +02:00
Paul Davis 86c3b70c54 add some utility functions to Buffers and BufferSets to allow some kinds of debugging easily 2024-05-14 12:25:58 -06:00
Robin Gareus ac47688023
Add Lua plugin to map DM10-mkII Studio HiHat MIDI messages 2024-05-14 17:20:52 +02:00
Robin Gareus 5b02561573
Fix MIDI Tracer (print polypress value) 2024-05-14 17:20:01 +02:00
Robin Gareus e75ad3399e
Fix BBT marker calculation when removing time 2024-05-14 03:20:04 +02:00
Robin Gareus aa55bf35eb
Catch issues with invalid region vs. source length
e.g. the session from
https://tracker.ardour.org/view.php?id=9704#c28732
2024-05-14 02:12:45 +02:00
Robin Gareus caae3501ec
TransportMasterWidget may not have a session
Other parts in this dialog already test for session == nullptr.
This can happen in the Preferences, when switching a timecode
master w/o a session (not possible in Ardour, but some derivative
project).
2024-05-13 23:11:43 +02:00
Paul Davis c3eb30d96b action group names must not be translatable 2024-05-13 15:08:53 -06:00
Robin Gareus 6b8018d927
Indicate remaining record time for FLAC with >= 2024-05-13 21:54:18 +02:00
Robin Gareus 68d3be8918
Support querying disk space for disks > 16TB
under the hood `fsblkcnt_t` is used.
2024-05-13 21:32:10 +02:00
Robin Gareus 1b1d6e767b
Include YTK in doxygen doc 2024-05-13 20:09:30 +02:00
Paul Davis 2f32a22a4d Revert "ensure that the master send is directly before the main outs."
MasterSends are not (currently) part of Ardour.

This reverts commit dcdcaf4b47.
2024-05-10 15:16:13 -06:00
Paul Davis 384739aa80 Revert "fix for metering of a MasterSend (internal send)"
MasterSends are not (currently) part of Ardour.

This reverts commit de1a425704.
2024-05-10 15:15:32 -06:00
Paul Davis fce1f15a87 avoid timecnt_t exception when loading a region with an excessively long length
This is not a fix for whatever underlying problem causes this, but it does allow sessions to load
when the faulty region(s) are not in use
2024-05-10 08:36:06 -06:00
Paul Davis dcdcaf4b47 ensure that the master send is directly before the main outs. 2024-05-10 08:35:03 -06:00
Paul Davis b929e8a4e2 revert inadvertently committed change made for debugging. 2024-05-10 08:35:03 -06:00
Paul Davis de1a425704 fix for metering of a MasterSend (internal send)
Metering for these sends should be effectively PostFader not Output,
and should not reflect the impact of solo & mute.
2024-05-10 08:35:03 -06:00
Paul Davis edc03002eb for DEBUG::Processors, use display_name() not name()
This allows us to differentiate between different instances of the same
type of processor (e.g. Trim vs Fader, which are both of type Amp)
2024-05-10 08:35:03 -06:00
John Emmas 2e55f4452f As we've yet to implement user options, let's prefer AAF filenames rather than extracting an internal Comp name
This helps to avoid situations where 2 x unrelated AAF imports use the same name internally - and/or they give us meaningless session names like "Untitled.ardour"
2024-05-10 15:07:44 +01:00
Robin Gareus c62fbc5c5b
Fix boundary condition first/last marker label length 2024-05-08 19:16:07 +02:00
Robin Gareus a0dc432e7a
Fix Marker label ellipsis for concurrent markers
* Sort markers: range-end before range-start
* When two marker have the same position, use distance
  to next marker not on the same position
2024-05-08 19:07:09 +02:00
Robin Gareus e542a8e0a0
Add action to reset all peak-hold (incl input meters) 2024-05-08 17:09:13 +02:00
Robin Gareus 3bab92f9a7
Add action to reset all meter peak hold 2024-05-08 15:11:36 +02:00
Paul Davis 94e0f2d3cd make dbl-click on mixer strip name button start a rename 2024-05-07 16:58:26 -06:00
Paul Davis 7d04a8bdd4 remove redundant button number check 2024-05-07 16:58:26 -06:00
Paul Davis 90d21161e7 more correct implementation for RouteProcessorSelection::set (AxisView*)
Suspending changes while clearing core selection stripables doesn't work
correctly, because we are not notified of the change before attempting
to add the argument.
2024-05-07 16:58:26 -06:00
Paul Davis fd1f68c34a allow mixer strip button events to fall through to parent, part 2 2024-05-07 16:58:26 -06:00
Paul Davis 29aeb88ce1 allow mixer strip button events to fall through to parent 2024-05-07 16:58:26 -06:00
Robin Gareus 88df55f86d
Remove debug messages, cleanup output (2/2) 2024-05-08 00:56:57 +02:00
Robin Gareus 5d175786e8
Remove debug messages, cleanup output (1/2) 2024-05-08 00:56:43 +02:00
Mattias Ohlsson 10109c3147
Fix typos 2024-05-07 18:52:02 +02:00
John Emmas dc74533fab Remove a declaration that won't be needed now 2024-05-07 16:06:47 +01:00
John Emmas a345d05f0f When importing AAF's move some code so that it only gets executed once per Source, rather than once for every Region
Fixes a problem where the Editor's 'Sources' pane was showing too many entries if there were more Regions than Sources.
2024-05-07 10:32:25 +01:00
Robin Gareus 4b8b5acfc4
Fix builds with gcc-14 lstat (#9703 PR #893)
from stat(2)
```
lstat():
    /* glibc 2.19 and earlier */ _BSD_SOURCE
        || /* Since glibc 2.20 */ _DEFAULT_SOURCE
        || _XOPEN_SOURCE >= 500
        || /* Since glibc 2.10: */ _POSIX_C_SOURCE >= 200112L

```
2024-05-07 00:17:56 +02:00
Robin Gareus 4f59b1ddf5
show/hide group-tab spacer above VCA pane 2024-05-06 23:47:10 +02:00
Robin Gareus 70898a676b
Allow to run IOTasklist without rt permissions 2024-05-06 23:20:26 +02:00
Paul Davis 576403c4cb no track movement up/down when a selected track is already at the relevant edge 2024-05-06 10:11:09 -06:00
Paul Davis f92d821a72 working track drag-n-drop, re-picked from a 2nd implementation on a branch 2024-05-05 15:09:34 -06:00
Paul Davis fdd91cc325 remove debug output 2024-05-05 15:05:09 -06:00
Paul Davis 51d2b3329c more work catching button release after track drag 2024-05-05 15:03:12 -06:00
Paul Davis c3fb69c385 catch button release after track drag 2024-05-05 15:02:59 -06:00
Paul Davis b515174e6a initialize track_drag member of Editor 2024-05-05 15:02:41 -06:00
Paul Davis e71fcaa92d add private object to Editor for use with track drag-n-drop 2024-05-05 15:02:29 -06:00
Paul Davis e170b34bf0 add pure virtual API for track DnD to PublicEditor 2024-05-05 15:02:19 -06:00
Paul Davis 89d7d85239 remove weird unused member of ARDOUR_UI 2024-05-05 15:02:03 -06:00
Paul Davis 81d1724931 NO-OP: add clarifying comment 2024-05-05 15:01:54 -06:00
Robin Gareus dec7b9a9af
Fix macOS signing when excluding xjadeo 2024-05-05 18:49:12 +02:00
Robin Gareus 8cf0fe5c77
Fix FPE when adding audio pins to a MIDI plugins 2024-05-04 20:17:25 +02:00
jean-emmanuel 4e44f44e71
mixer: use ardour widgets instead of native gtk's for plugin list dropdown and search clear button 2024-05-03 21:19:48 +02:00
Maciej Bliziński 18949a8730
Add a hint about quotes in post-export.
When I saw the post-export hint, I thought I needed to quote the arguments. Usually, either you provide a string which will be interpolated by the shell, in which case you need to add quotes, or you build an array of strings, and in this case you don't need to add quotes - but you build an array and not write a command template. Ardour's approach is a departure from this mode, so let's save future people time trying to figure this detail out.
2024-05-03 21:11:34 +02:00
Olivier HUMBERT 68402aae12
Update French translation 2024-05-03 21:09:24 +02:00
Florian Hülsmann 27154d9769
set explicit StartupWMClass for better Linux desktop UX 2024-05-03 21:06:49 +02:00
Robin Gareus df4f998231
Arrangement DnD now defaults to move (not copy) 2024-05-03 21:02:20 +02:00
Robin Gareus 100ee72cec
Fix copying RegionFx Automation 2024-05-03 14:44:49 +02:00
Robin Gareus 233a82d5f9
Separate xjadeo and harvid packaging (and remove 32c)
This is mainly for the benefit of traxlive, which needs
ffmpeg to encode mp3 or import encoded files, without
support for video.
2024-05-03 03:52:57 +02:00
Robin Gareus 37d24eee7d
Flush Audioregion local [fx] cache when changing region gain 2024-05-02 23:04:50 +02:00
Ben Loftis 27e2348b47 when capturing a midi pgm change, display the pgm num (for LT) 2024-05-02 12:43:12 -05:00
Ben Loftis a88d430609 null check for a missing session (for LT) 2024-05-02 12:42:23 -05:00
John Emmas 631ee17e34 Modify class ARDOUR::DiskReader because it now includes members declared using 'thread_local'
On Windows, variables defined as having thread storage can have a different address in different threads and as such, they aren't allowed to be imported or exported from a DLL.
2024-05-02 10:22:44 +01:00
Robin Gareus 99e2ac28e1
Update debug message to include regionfx and offset 2024-05-01 22:30:04 +02:00
Robin Gareus f355551839
Don't nag Trax users after export 2024-05-01 14:54:31 +02:00
Robin Gareus b9da1a5bd5
Expose HW concurrency to LV2 plugins 2024-05-01 03:51:42 +02:00
Robin Gareus 2ccda116c7
Add preference for I/O thread count 2024-04-30 03:54:57 +02:00
Robin Gareus 5b9e4fff63
Parallelize Disk I/O and RegionFx processing 2024-04-30 03:46:39 +02:00
Robin Gareus 4b0da72bc2
Delegate all DiskReader I/O to the IOTaskList (amend 170b9150) 2024-04-30 01:55:44 +02:00
Robin Gareus ee87b068e8
Move RegionFx ThreadBuffers to Butler thread 2024-04-30 01:54:33 +02:00
Robin Gareus 170b915038
Prepare for parallel Disk I/O 2024-04-30 00:01:32 +02:00
Robin Gareus 2af2df3516
Raise the butler's I/O priority
This likely won't make much difference on modern systems,
since it requires a kernel based I/O scheduler. which is
disabled (set to "none" for NVMe and SSDs).
2024-04-29 21:46:06 +02:00
Robin Gareus e90e31d682
Add a Tracks/Waveform icon 2024-04-29 21:00:27 +02:00
Robin Gareus ce4f91483b
Fix OSX packaging and signing for LiveTrax 2024-04-29 00:56:27 +02:00
Robin Gareus 9bafa8a216
Remove svn related part in bundle script 2024-04-29 00:42:12 +02:00
Robin Gareus 75167ac347
Bundle/package script updates for LiveTrax 2024-04-28 17:54:20 +02:00
Robin Gareus 5f7ecf59a5
Allow to compile w/o LV2 support (trax) 2024-04-28 17:50:51 +02:00
Robin Gareus dcb732f07c
Only allow editing top-most MIDI region in layered view
NoteDrag (change pitch) only works correctly for the topmost
region when using Stacked LayerDisplay. Note-grid is also only
displayed for the top layer.
2024-04-27 00:04:29 +02:00
Paul Davis 201580f7ba fix crashes caused by assert (_fx_line); item does not exist for livetrax 2024-04-25 13:07:00 -06:00
Paul Davis fc86629daf sometimes concision with variable naming is of no help 2024-04-25 13:07:00 -06:00
Paul Davis 21a39c5f1f profile initialization per-program needs to happen earlier, in ARDOUR::init() 2024-04-25 13:07:00 -06:00
Paul Davis b2570bcaa3 remove debug output 2024-04-25 13:07:00 -06:00
Paul Davis 0b8cfdee40 display MIDI scene markers 2024-04-25 13:07:00 -06:00
Paul Davis 87f40ddc7f some libardour support for MIDI scene support 2024-04-25 13:07:00 -06:00
Paul Davis a0756429cf auto-fication of a loop in InternalReturn 2024-04-25 13:07:00 -06:00
Paul Davis 7bcdd5b2e4 NO-OP: add space before bracket 2024-04-25 13:07:00 -06:00
Paul Davis e3b21ed77a NO-OP: linebeeak removed 2024-04-25 13:07:00 -06:00
Paul Davis a7dbf57afa more crash avoidance in sfdb UI if there's no auditioner 2024-04-25 13:07:00 -06:00
Paul Davis ad53c31e50 sfdb UI should not crash if there's no auditioner 2024-04-25 13:07:00 -06:00
Paul Davis 5d1233e60a NO-OP: fix space near braces/brackets 2024-04-25 13:07:00 -06:00
Paul Davis 43e0f08b93 sfdb_ui should be smart if there's no auditioner 2024-04-25 13:07:00 -06:00
Paul Davis 8f7f204ae4 port group display should not crash if there's no auditioner 2024-04-25 13:07:00 -06:00
Paul Davis 9052eb013e no crash if instrument selector has no _instrument_list 2024-04-25 13:07:00 -06:00
Paul Davis 125b0f9432 add a new Profile flag for livetrax 2024-04-25 13:07:00 -06:00
Paul Davis 16ed245977 allow true boxy buttons for ArdourButtons
Also add a default tweaks static member to force all buttons to a given tweak state
2024-04-25 13:03:52 -06:00
Paul Davis 46fa056da6 add unrounded rectangle methods to Gtkmm2ext for use in truly boxy buttons 2024-04-25 13:03:52 -06:00
Robin Gareus 354e60d657
Drop session's monitor bus reference when removing the bus 2024-04-25 19:18:06 +02:00
Robin Gareus 848832f8b0
Flush GraphNode RCU when removing Routes
Since 44610c787 RCU keeps references until another write happens.
even before then, some shared_ptr references may have been kept.

When using a process graph, a route's activision-set can
hold references to other graph-nodes (routes). This lead
to Routes not being deleted until a second graph-reorder
flushed the RCU.
2024-04-25 19:18:06 +02:00
Robin Gareus 97becda83a
Update icon rendering tool 2024-04-25 19:18:02 +02:00
Paul Davis f1a3eb1e3d use a different source file for ardour.menus in the livetrax case 2024-04-25 09:26:33 -06:00
Robin Gareus 4665cdcb6b
Add icons for livetrax (lock, mixer, meter) 2024-04-25 02:21:10 +02:00
Robin Gareus b00ddcfe1c
Fix -Waddress (and expand tabs)
The expansion of the macro resulted in:
"the comparison will always evaluate as 'true' for the address of .."
2024-04-24 18:06:27 +02:00
agfline 8ea3a14cd6
Update AAF import UI 2024-04-24 17:13:00 +02:00
agfline 41587d3c06
Update libaaf to v1.0-11-gb04c547 2024-04-24 17:13:00 +02:00
Robin Gareus 895fe2f753
Fix Windows builds 2/2 (amend b2d4280e0) 2024-04-24 06:08:26 +02:00
Robin Gareus df12126909
Fix Windows builds 1/2 (amend bcbb4393fc) 2024-04-24 06:02:13 +02:00
Robin Gareus 38adfdf79e
Add custom color for region effect automation 2024-04-23 21:56:26 +02:00
Robin Gareus b2d4280e0f
Add support for Region Fx Automation 2024-04-23 21:56:22 +02:00
Robin Gareus e5506d281a
GUI support for Region Fx (in Region Properties) 2024-04-23 21:56:18 +02:00
Robin Gareus 457238ec2e
Per [Audio] Region Fx
* apply effects during region-read in non-rt context
* Add multi-channel audioregion read cache
  to process stereo effects
2024-04-23 21:56:15 +02:00
Robin Gareus 1996945353
Add custom RegionFxPlugin
Less than a PluginInsert but more than an IOPlug.
2024-04-23 21:56:10 +02:00
Robin Gareus ad9a3ae103
Fix region-gain envelope auto-enable when dragging
When using freehand drawing of automation, the line itself
is not notified (no ::start_drag(), ::end_drag() calls).

This adds a end_draw() call which allows the AutomatioLine
to perform additional actions.
2024-04-23 21:56:05 +02:00
Robin Gareus b04fa05f20
NO-OP: sort debug bits 2024-04-23 21:55:59 +02:00
Robin Gareus 1cd9a9b57d
Only show automation mode button for PluginInsert ctrls
Previously the generic UI of I/O plugins (and upcoming Region
Fx showed an insensitive Automation mode (manual, play, touch etc)
dropdown for all controls.

That accomplished nothing but wasted space.
2024-04-23 21:55:54 +02:00
Robin Gareus 59b2369736
Remove unused gain-buffer for master-read (NOOP) 2024-04-23 21:52:02 +02:00
Robin Gareus f3823e8d7c
Fix redeclaration of DnDVbox 2024-04-23 21:51:55 +02:00
Robin Gareus 2bb4a9ac4e
Add API to configure plugins for non-realtime offline processing 2024-04-23 21:51:50 +02:00
Robin Gareus 598ff1cb9a
Separate PluginWindowProxy into public class 2024-04-23 21:51:31 +02:00
Robin Gareus f858316503
Plugins: Ignore offset for scratch/silent buffers
This allows to process buffers at an offset, as long
as the number of processed samples is less or equal to the
current buffersize.
2024-04-23 21:51:19 +02:00
Robin Gareus 2ca5f28910
NO-OP: whitespace 2024-04-23 21:51:07 +02:00
Robin Gareus 2f6a428f05
Overhaul and optimize thread-buffer allocation
Every route calls Session::ensure_buffers when configuring
processors. Previously that unconditionally invoked the
BufferManager, even if no change was required.

This also fixes a potential issue when bouncing tracks.
::write_one_track() increases the buffersize to 8k, but only for
the ChanCount required to bounce. This was never properly reset.

Furthermore this is in preparation for RegionFX which may
need to increase the ChanCount of Threadbuffers.
2024-04-23 21:51:04 +02:00
Robin Gareus 6dfcb60763
Automatable find_next/prev_ac_event requires no context
This allows to use the functions from a class that
does not inherit from Automatable but has AutomationControls
with an AutomationList.
2024-04-23 21:50:58 +02:00
Robin Gareus f111f200c1
Fix signal analysis when buffer-size changes
PI::signal-analysis buffers were not updated when a user
changes the buffersize.

This also remove a single use Session API.
2024-04-23 21:49:48 +02:00
Robin Gareus df8106bd85
PluginInsert match I/O: skip div by zero 2024-04-23 21:49:41 +02:00
Robin Gareus 92183430b9
IOPlug: various small fixes (port-names, VST compat, etc) 2024-04-23 21:49:28 +02:00
Robin Gareus 5216a6d987
Refactor and consolidate setting and copying plugin state 2024-04-21 16:32:47 +02:00
Robin Gareus f5b53a6d14
Consolidate PluginInsert Match, move to parent class 2024-04-21 16:32:47 +02:00
Robin Gareus 2da3141706
Consolidate plugin_factory, move to parent class 2024-04-21 16:32:47 +02:00
Robin Gareus d2bdf440c8
Consolidate PluginControl Code
This code was (for the most part) duplicated, and with
preparation for Region FX, a third copy motivated this
consolidation.
2024-04-21 16:32:47 +02:00
Robin Gareus 6191f89d55
Properly update Solo state when setting multiple ctrls 2024-04-21 16:32:13 +02:00
Robin Gareus bcbb4393fc
Allow Lua [session] script to directly set controllables 2024-04-21 16:32:10 +02:00
Paul Davis 894e6d27a4 NOOP: whitespace cleanup 2024-04-19 10:43:10 -06:00
Paul Davis c96e12ba58 expand null/destroyed tests for gdk objects in NSView methods 2024-04-19 10:42:59 -06:00
Robin Gareus e64a071e39
(YDK) amend previous commit, call parent method 2024-04-19 16:46:49 +02:00
Robin Gareus 08e394f681
(YDK) possible fix for Catalina event loop crashes
```
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libydk.dylib 0x0000000110d8942d -[GdkQuartzView setNeedsDisplay:] + 93
1 com.apple.AppKit 0x00007fff34af6848 -[NSView(NSViewContentStyle) _recursivelyInvalidateCachedContentStyle] + 120
2 com.apple.AppKit 0x00007fff34af60fb -[NSView _setSuperview:] + 521
3 com.apple.AppKit 0x00007fff34b200a6 -[NSView removeFromSuperview] + 140
4 com.apple.AppKit 0x00007fff34ba882f -[NSView removeFromSuperviewWithoutNeedingDisplay] + 36
5 com.apple.AppKit 0x00007fff34b27168 -[NSView _finalize] + 977
6 com.apple.AppKit 0x00007fff34b26c0c -[NSView dealloc] + 121
7 com.apple.AppKit 0x00007fff34e30db4 -[NSFrameView dealloc] + 119
8 com.apple.AppKit 0x00007fff34e30d36 -[NSTitledFrame dealloc] + 62
9 com.apple.AppKit 0x00007fff34e30ce9 -[NSThemeFrame dealloc] + 603
10 com.apple.Foundation 0x00007fff39ed5992 NSKVODeallocate + 172
11 com.apple.AppKit 0x00007fff34d85884 -[NSWindow dealloc] + 1083
12 com.apple.AppKit 0x00007fff34d85442 -[NSWindow _dealloc] + 76
13 libobjc.A.dylib 0x00007fff6f6f3054 AutoreleasePoolPage::releaseUntil(objc_object**) + 134
14 libobjc.A.dylib 0x00007fff6f6d7dba objc_autoreleasePoolPop + 175
15 com.apple.CoreFoundation 0x00007fff377c9cb5 _CFAutoreleasePoolPop + 22
16 com.apple.Foundation 0x00007fff39e7d04e -[NSAutoreleasePool drain] + 126
17 libydk.dylib 0x0000000110d8ef29 gdk_event_prepare + 73
18 libglib-2.0.0.dylib 0x00000001110ded45 g_main_context_prepare + 533
19 libglib-2.0.0.dylib 0x00000001110df800 g_main_context_iterate + 128
20 libglib-2.0.0.dylib 0x00000001110dfcc2 g_main_loop_run + 210
21 libytk.dylib 0x0000000110a4f11f gtk_main + 191
22 libgtkmm2ext.dylib 0x00000001104cef1e Gtkmm2ext::UI::run(Receiver&) + 318
23 com.harrisonconsoles.Mixbus10 0x000000010dc6fb9c main + 2652
```
2024-04-19 15:38:12 +02:00
Robin Gareus 136b7f42d5
Skip tags for plugins that are not installed
This prevents empty sub-menus in the "By Tag" Plugin menu.
2024-04-18 17:07:12 +02:00
Robin Gareus 4b6e372ce7
Fix deleting the same point multiple times (#9689)
When iterating over automation tracks, previously it was
possible that the same point was added multiple times to
the selection.
2024-04-15 00:39:20 +02:00
Edgar Aichinger c9c419213f
update german translation 2024-04-14 00:42:09 +02: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
Robin Gareus 4a0505979d
macOS provides z-axis stacking for Dialogs
see also d1b462c213 and Manager::set_transient_for.

This fixes a bug on macOS: detach Editor, re-attach Editor.
After that `own_window()` is true. Showing the LAN dialog
showed the editor's hidden Window as its parent.
2024-04-04 22:50:26 +02:00
Robin Gareus 2e991b0067
Fix thinko in bda7041643 2024-04-04 17:32:50 +02:00
Robin Gareus 3b0e421de4
Use proper _POSIX_C_SOURCE constant 2024-04-04 17:06:31 +02:00
Robin Gareus bda7041643
Fix #9642 - fdopen(3) requires _POSIX_C_SOURCE
Without this, fdopen() returns some garbage FILE* which
causes a crash when used.
2024-04-04 17:06:28 +02:00
Robin Gareus 15dc06b12a
Ardour non longer uses gtk modules 2024-04-04 17:06:22 +02:00
Robin Gareus 02220783e1
Clarify that there are no archive file format options 2024-04-02 09:53:24 +02:00
Paul Davis 6d29a0e99b amend b96d556451 by using g_alloca() rather than non-standard variable-size array 2024-04-01 15:11:59 -06:00
Paul Davis b96d556451 avoid heap allocation by std::vector in realtime context 2024-04-01 15:00:11 -06:00
Robin Gareus e29ac27c59
Tweak binarual port names 2024-04-01 17:39:08 +02:00
Paul Davis 719debf292 if we're asked to use RF64_WAV, actually enabled libsndfile's downgrade capability
Note that this does not alter the filename, which we might also want to consider
2024-03-27 17:32:23 -06:00
Robin Gareus e0db21d484
Save versioned backups in backup/ folder
This makes it harder for users to accidentally open session
files which are intended to be used only with older versions
of Ardour.

Note that backup/ is not included in ::find_all_sources_across_snapshots
so Session > Cleanup can remove files used in old backups.
2024-03-27 21:38:09 +01:00
Robin Gareus 41115f1282
Prevent double-click on the pianoroll to toggle track height 2024-03-27 03:25:36 +01:00
Robin Gareus 26b6bece95
Fix a -Wunused-variable 2024-03-27 00:38:02 +01:00
Robin Gareus 93934dfb92
Really fix Windows build (amend prev. commit) 2024-03-26 21:08:42 +01:00
Robin Gareus 1c55cc6ee2
Fix Windows builds (amend 980eb595)
```
undefined reference to `luabridge::ClassInfo<std::shared_ptr<ARDOUR::PluginInsert> >::getClassKey
``
2024-03-26 19:28:10 +01:00
Florian Walpen 845171807f
Fix undefined symbol when built with VST3 disabled.
Commit cd5369c added some cleanup code to `libs/ardour/session.cc`,
which drags in the type info symbol of VST3PluginInfo. When built
with `--no-vst3`, the resulting binary dies at startup:

```
ld-elf.so.1: /usr/local/lib/ardour8/libardour.so.3: Undefined symbol
"_ZTIN6ARDOUR14VST3PluginInfoE"
```

Make that code compile conditional on VST3_SUPPORT.
Occurs on FreeBSD 14.0-RELEASE, clang 16.0.6, amd64.
2024-03-25 16:41:36 +01:00
Robin Gareus 0bb3c166e8
Add example script to exercise Plugin Properties 2024-03-24 23:09:53 +01:00
Robin Gareus 980eb595cf
Add Lua API to query plugin properties 2024-03-24 23:09:53 +01:00
Robin Gareus cfa45be99f
Add Lua API to set plugin properties 2024-03-24 23:09:53 +01:00
Paul Davis 4d5175e32e change default for use-cocoa-invalidation 2024-03-22 14:51:19 -06:00
Paul Davis adfba3d39d allow runtime control over cairo save/restore around item rendering
This is to allow easier debugging of whether a given item's render method fails to leave a cairo
context in the same state it received it in
2024-03-22 13:39:03 -06:00
Paul Davis d57ce0eba1 provide control over use-cocoa-invalidation 2024-03-22 13:13:16 -06:00
Paul Davis 6c38e0a4e3 explicitly initialize the needs_display_region member of a GDK quartz window
This may not be necessary but it is better to have it be explicit
2024-03-22 13:13:16 -06:00
Paul Davis fe6a635c3a provide a GDK function to enable/disable use of Cocoa-provided rect in drawRect 2024-03-22 13:13:16 -06:00
Paul Davis 7324070628 gdk/quartz: add some additional GDK_NOTE debugging 2024-03-22 13:13:16 -06:00
Robin Gareus bd4d6b4cba
Ellipsize inactive track-header name-label #9674 2024-03-21 17:44:33 +01:00
Robin Gareus 082297b932
Update UI for SurroundSendLevel control type 2024-03-21 14:24:11 +01:00
Robin Gareus 73fea85381
Vapor: set surround-send level range to +/-20 dB 2024-03-21 14:23:43 +01:00
agfline 25397d7812
AAF: Update import UI 2024-03-19 20:59:10 +01:00
Robin Gareus 4883867f2b
Update libaaf to v1.0-10-g13f0b0a 2024-03-19 20:59:04 +01:00
Robin Gareus da4218c2db
YTK: remove unused code
This addresses a missing `readlink` due to missing
`_POSIX_C_SOURCE=200809` define when including unistd.h
2024-03-18 22:02:54 +01:00
Mads Kiilerich a2bb1a3511 Fix more -Wincompatible-pointer-types
c10154ad23 showed the direction  but was not correct and insufficient
for building with Fedora 40 and gcc 14.0.1 .
2024-03-18 21:24:46 +01:00
Robin Gareus c10154ad23
Fix a -Wincompatible-pointer-types 2024-03-18 20:29:19 +01:00
Paul Davis e64af8e4ed add a test for an environment variable before switching canvas single-expose off 2024-03-18 11:28:16 -06:00
Paul Davis 4b563ae518 move CairoCanvas::render() implementation for ArdourCanvas::Canvas into source
Note that this implementation only redraws a single (cairo_rectangle_t-defined) rect, and cannot
provide sub-rects the way that a normal GDK/GTK expose-driven redraw can
2024-03-18 10:50:36 -06:00
Paul Davis 71e085d825 ensure that the canvas fully redraws after style/visibility events 2024-03-18 10:49:15 -06:00
Paul Davis 0c4eada414 make editor canvas use multi-expose redraws
This is not required for any functionality or performance fixes, but may be useful
and also helps tracking redraw issues with other related changes
2024-03-18 10:48:38 -06:00
Paul Davis 802d9fa487 correctly implement canvas expose redraw for both single- and multi-expose contexts 2024-03-18 10:47:31 -06:00
Paul Davis 9efd521ea6 (GDK) keep our own record of invalidated rectangles for GdkQuartzView
macOS has broken its exposure/redraw model at least twice by always providing the entire area
of an NSView for every call to drawRect, and cannot provide the list of rects. This change
expands the tracking done using the needs_display_region, and does so directly via the
objective C methods of an NSView (and its derived children like GdkQuartzView).

The result is that when we send an expose signal, GDK/GTK code can obtain an accurate
list of the invalidated rects if desired, and thus avoiding redrawing the entire contents
of a window
2024-03-18 10:40:42 -06:00
agfline 52cce5adc6 AAF: fix import of embedded files shared across regions
https://github.com/agfline/LibAAF/issues/5#issuecomment-1994155327
2024-03-14 12:47:21 +01:00
Robin Gareus 2224aca75c
Fix SNAFU in 20d813cd17 (surround mute point) 2024-03-13 23:00:59 +01:00
Robin Gareus f1ecd8c124
Vapor: mute master (not monitor), the latter is used for audition, etc 2024-03-13 22:19:17 +01:00
Robin Gareus 9e9fd201b5
Prevent crashes when trying to add/remove IOPlug ports
IOPlugins pinout is not [yet] configurable. Trying to add ports
resuled in a segfault since the BufferSet was not resized
(nor the plugin reconfigured)
2024-03-13 03:56:01 +01:00
Robin Gareus 069bf034ab
Accumulate IO port-change signals return values
This was already done for IO::remove_port, but not yet for
::add_port
2024-03-13 03:54:52 +01:00
Robin Gareus 16fb29d576
Vaporgate: special case content creation
This allows to change behavior to match some other notable DAW
which can only send automation events at cycle boundaries.
2024-03-12 17:43:38 +01:00
Robin Gareus 0fff58f905
Remove outdated adm import scripts 2024-03-12 17:39:32 +01:00
Robin Gareus f2d938914d
Fix loading session by relative path
Previously (since bc91ea3c4) that would create a new session
even if -N was not specified.

This also uses Glib API to test for absolute path, rather
than a custom hack.
2024-03-12 04:29:33 +01:00
Robin Gareus 2f61071974
Update Lua Action scripts from local file when possible 2024-03-12 04:24:58 +01:00
Robin Gareus 682f4dafd3
Vapor: add additional options for ADM export 2024-03-12 00:32:35 +01:00
Robin Gareus 35017245d9
Fix typo 2024-03-12 00:31:32 +01:00
Robin Gareus 5d60c2668c
Add Lua bindings to set session range 2024-03-11 22:07:07 +01:00
Robin Gareus b783e3eab1
Vapor: add additional export constraint 2024-03-11 20:52:53 +01:00
Ben Loftis e467e0c014 in the case of nudging (1) CP, locate the phead so we can see its position 2024-03-11 14:45:07 -05:00
Robin Gareus 46a8b547fa
Half-baked automation-point nudge
There are currently combined constraints when moving multiple
points like ContiguousControlPoints::move enforces, but otherwise
it works fine.
2024-03-11 19:18:27 +01:00
Robin Gareus c012ab19e0 Fix AAF compilation with clang (macOS) 2024-03-11 18:52:45 +01:00
Ben Loftis f873f9f621 typos: "ADM/BWM" -> "ADM BWF" 2024-03-11 09:14:44 -05:00
Ben Loftis 310e7f2279 make a distinction between total channels with or without the embedded bed chans 2024-03-11 08:29:56 -05:00
agfline d03cdf86e1
Update AAF import UI 2024-03-10 22:11:58 +01:00
agfline bd937366fd
Update libaaf to v1.0-1-gdef35bf 2024-03-10 22:11:47 +01:00
agfline 2b1349ffc2
Update libAAF import tool 2024-03-10 21:53:36 +01:00
Robin Gareus 5e2f027ee9
NO-OP: whitespace 2024-03-09 23:35:39 +01:00
Ben Loftis 258b22c9f1 remove signal emission from run() func 2024-03-08 11:48:16 -06:00
Ben Loftis e907aad05c ObjectCount signal should include the count 2024-03-08 11:31:44 -06:00
Ben Loftis 7ad5278bfd fix typos: ADM BWF 2024-03-08 11:22:33 -06:00
Robin Gareus 43c08dd2f5
Do not automatically bind ADM import script 2024-03-08 16:15:13 +01:00
Robin Gareus 8a8a1b9fb9
Vapor: export file timecode must be < 24h 2024-03-07 17:24:12 +01:00
Robin Gareus 13383b11a7
Set correct Timecode widget name 2024-03-07 14:29:50 +01:00
Ben Loftis 24b18c889b allow SurroundReturn to publish the number of channels in use 2024-03-06 18:34:33 -06:00
Robin Gareus 42dc033636
Vapor: work-around stem export alignment
This is a somewhat fragile solution to ensure that
processor reset happens in the same cycle in which
the actual data arrives at the start of the cycle.
2024-03-07 01:28:22 +01:00
Robin Gareus 77e7470270
Vapor: handle export abort 2024-03-06 18:35:08 +01:00
Robin Gareus 922ad14217
Gap-less overwrite_existing_audio
AudioPlaylist::read first clears the buffer passed to it, in
order to sum all layered regions into the buffer.

This cleared data in the ringbuffer that is concurrently being
used for playback.
2024-03-06 02:33:39 +01:00
Robin Gareus 6df34a307d
Match surround panner automation line convention
move to the left -> automation line moves upwards
move to the front -> automation line moves upwards
2024-03-05 14:59:26 +01:00
Robin Gareus 3a6171428a
Do not include hidden plugin in plugin-list 2024-03-05 00:56:42 +01:00
Robin Gareus bf7d4f895e
Fix jump to next/prev bar
Previously this only located to the prev/next bar if the
playhead was not already on a bar boundary
2024-03-04 20:25:41 +01:00
Robin Gareus 517d82a6f2
Vapor: add script to perform live rendering tests 2024-03-04 17:00:00 +01:00
Robin Gareus 53b951f6a9
Vapor: Properly name sync&aling API 2024-03-04 16:53:33 +01:00
GianfrancoCostamagna 338cd09a4a
Work around itstools bug #9648
Forwarded from debian.
Having stderr output inside the returned command tricks the system
to fail in detecting the version.
Ignoring stderr output looks fine to make it build properly:

```
itstool --version
/usr/bin/itstool:239: SyntaxWarning: invalid escape sequence '\s'
  if re.sub('\s+', ' ', text).strip() != '':
/usr/bin/itstool:337: SyntaxWarning: invalid escape sequence '\s'
  message = re.sub('\s+', ' ', message).strip()
/usr/bin/itstool:475: SyntaxWarning: invalid escape sequence '\s'
  return re.sub('\s+', ' ', self.locnote).strip()
/usr/bin/itstool:477: SyntaxWarning: invalid escape sequence '\s'
  return '(itstool) link: ' + re.sub('\s+', ' ', self.locnoteref).strip()
/usr/bin/itstool:891: SyntaxWarning: invalid escape sequence '\<'
  regex = re.compile('(.*) \<(.*)\>, (.*)')
/usr/bin/itstool:926: SyntaxWarning: invalid escape sequence '\s'
  if re.sub('\s+', '', prevtext) == '':
/usr/bin/itstool:1452: SyntaxWarning: invalid escape sequence '\.'
  _locale_pattern = re.compile('([a-zA-Z0-9-]+)(_[A-Za-z0-9]+)?(@[A-Za-z0-9]+)?(\.[A-Za-z0-9]+)?')
itstool 2.0.6
```
2024-03-04 14:27:23 +01:00
Robin Gareus 37d130f6e1
Fix Aux-send gain automation latency compensation 2024-03-03 01:08:07 +01:00
Robin Gareus ed98ff97b2
Fix adding new route in front (#9651)
When adding a new route using "Front", its presentation info
order is set to 1, after the master-bus which has PI order 0.
(see Session::ensure_route_presentation_info_gap).

Mixer_UI::add_stripables, looks up the insert iterator:
"after the route with order 0", but since the master bus is
not in mixer's track-model, the insert-iterator is left "at end".

A later call to `sync_presentation_info_from_treeview` then updated
the new track's order key to be at the end.
2024-03-02 14:55:58 +01:00
284 changed files with 18645 additions and 12721 deletions

View File

@ -778,7 +778,11 @@ INPUT = ../libs/ardour \
../libs/widgets \
../libs/zita-convolver \
../libs/zita-resampler \
../libs/zita-resampler \
../gtk2_ardour \
../libs/tk/ytkmm/ytkmm/gtkmm \
../libs/tk/ydkmm/ydkmm/gdkmm \
../libs/tk/ydk/ydk/gdk \
mainpage.txt
## audiographer assumes it's documented separately (has it's own @mainpage)

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

@ -7,3 +7,4 @@ Terminal=false
MimeType=application/x-ardour;
Type=Application
Categories=AudioVideo;Audio;AudioEditing;X-Recorders;X-Multitrack;X-Jack;
StartupWMClass=Ardour

View File

@ -548,11 +548,8 @@
<menuitem action="toggle-meter-ruler"/>
<menuitem action="toggle-tempo-ruler"/>
<menuitem action="toggle-range-ruler"/>
<menuitem action="toggle-loop-punch-ruler"/>
<menuitem action="toggle-cd-marker-ruler"/>
<menuitem action="toggle-arrangement-ruler"/>
<menuitem action="toggle-marker-ruler"/>
<menuitem action="toggle-cue-marker-ruler"/>
<separator/>
<menuitem action="toggle-video-ruler"/>
</menu>
@ -801,10 +798,7 @@
<menuitem action="toggle-meter-ruler"/>
<menuitem action="toggle-tempo-ruler"/>
<menuitem action="toggle-range-ruler"/>
<menuitem action="toggle-loop-punch-ruler"/>
<menuitem action="toggle-cd-marker-ruler"/>
<menuitem action="toggle-marker-ruler"/>
<menuitem action="toggle-cue-marker-ruler"/>
<separator/>
<menuitem action="toggle-video-ruler"/>
</popup>
@ -869,6 +863,22 @@
<menuitem action='removeUnusedRegions'/>
</popup>
<popup name='MarkerShowMenu' accelerators='true'>
<menuitem action='show-all-markers'/>
<menuitem action='show-cd-markers'/>
<menuitem action='show-cue-markers'/>
<menuitem action='show-scene-markers'/>
<menuitem action='show-location-markers'/>
</popup>
<popup name='RangeShowMenu' accelerators='true'>
<menuitem action='show-all-ranges'/>
<menuitem action='show-session-range'/>
<menuitem action='show-punch-range'/>
<menuitem action='show-loop-range'/>
<menuitem action='show-other-ranges'/>
</popup>
<popup name='PopupRegionMenu' action='PopupRegionMenu' accelerators='true'>
<menuitem action='play-selected-regions'/>
<menuitem action='tag-selected-regions'/>

View File

@ -1432,6 +1432,10 @@ ARDOUR_UI::format_disk_space_label (float remain_sec)
std::string label = string_compose (X_("<span weight=\"ultralight\">%1</span>: "), _("Rec"));
if (_session && FLAC == _session->config.get_native_file_header_format () && remain_sec <= 86400) {
label += u8"\u2265"; // Greater-Than or Equal To
}
if (remain_sec > 86400) {
disk_space_label.set_markup (label + _(">24h"));
} else if (remain_sec > 32400 /* 9 hours */) {
@ -2210,8 +2214,6 @@ ARDOUR_UI::update_clocks ()
void
ARDOUR_UI::start_clocking ()
{
std::cerr << "start clocking\n";
if (UIConfiguration::instance().get_no_strobe()) {
if (!_session) {
return;

View File

@ -275,8 +275,6 @@ public:
void reset_focus (Gtk::Widget*);
static PublicEditor* _instance;
/** Emitted frequently with the audible sample, false, and the edit point as
* parameters respectively.
*

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2023 Robin Gareus <robin@gareus.org>
* Copyright (C) 2023 Adrien Gesta-Fline <dev.agfline@posteo.net>
* Copyright (C) 2023-2024 Adrien Gesta-Fline <dev.agfline@posteo.net>
*
* 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
@ -17,6 +17,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <fcntl.h> // O_WRONLY
#include <glib/gstdio.h> // g_unlink()
#include "pbd/basename.h"
#include "pbd/convert.h"
#include "pbd/file_utils.h"
@ -45,8 +48,43 @@ using namespace PBD;
using namespace ARDOUR;
static void
aaf_debug_callback (struct dbg* dbg, void* ctxdata, int lib, int type, const char* srcfile, const char* srcfunc, int lineno, const char* msg, void* user)
aaf_debug_callback (struct aafLog* log, void* ctxdata, int libid, int type, const char* srcfile, const char* srcfunc, int lineno, const char* msg, void* user)
{
const char* eol = "";
if (libid != LOG_SRC_ID_TRACE && libid != LOG_SRC_ID_DUMP) {
switch (type) {
case VERB_SUCCESS:
PBD::info << string_compose ("[libaaf] %1:%2 in %3(): ", srcfile, lineno, srcfunc);
break;
case VERB_ERROR:
PBD::error << string_compose ("[libaaf] %1:%2 in %3(): ", srcfile, lineno, srcfunc);
break;
case VERB_WARNING:
PBD::warning << string_compose ("[libaaf] %1:%2 in %3(): ", srcfile, lineno, srcfunc);
break;
// case VERB_DEBUG: PBD::debug << string_compose ("[libaaf] %1:%2 in %3(): ", srcfile, lineno, srcfunc); break;
}
}
if (libid != LOG_SRC_ID_DUMP) {
eol = "\n";
}
switch (type) {
case VERB_SUCCESS:
PBD::info << msg << eol;
break;
case VERB_ERROR:
PBD::error << msg << eol;
break;
case VERB_WARNING:
PBD::warning << msg << eol;
break;
// case VERB_DEBUG: PBD::debug << msg << eol; break;
}
LOG_BUFFER_RESET (log);
}
static std::shared_ptr<AudioTrack>
@ -78,15 +116,13 @@ prepare_audio_track (aafiAudioTrack* aafTrack, Session* s)
}
/* ..or create a new track */
wstring ws_track_name = std::wstring (aafTrack->name);
string track_name = string (ws_track_name.begin (), ws_track_name.end ());
uint32_t outputs = 2;
if (s->master_out ()) {
outputs = max (outputs, s->master_out ()->n_inputs ().n_audio ());
}
list<std::shared_ptr<AudioTrack>> at (s->new_audio_track (aafTrack->format, outputs, NULL, 1, track_name, PresentationInfo::max_order));
list<std::shared_ptr<AudioTrack>> at (s->new_audio_track (aafTrack->format, outputs, NULL, 1, aafTrack->name, PresentationInfo::max_order));
if (at.empty ()) {
PBD::fatal << "AAF: Could not create new audio track." << endmsg;
@ -97,91 +133,106 @@ prepare_audio_track (aafiAudioTrack* aafTrack, Session* s)
}
static bool
import_sndfile_as_region (Session* s, struct aafiAudioEssence* audioEssence, SrcQuality quality, timepos_t& pos, SourceList& sources, ImportStatus& status, vector<std::shared_ptr<Region>>& regions)
import_sndfile_as_region (Session* s, struct aafiAudioEssencePointer* aafAudioEssencePtrList, SrcQuality quality, timepos_t& pos, SourceList** oneClipSources, ImportStatus& status, vector<std::shared_ptr<Region>>& regions)
{
wstring ws (audioEssence->usable_file_path);
string usable_file_path (ws.begin (), ws.end ());
SourceList* sources = NULL;
/* Import the source */
status.clear ();
if (aafAudioEssencePtrList->user) {
sources = (SourceList*)aafAudioEssencePtrList->user;
} else {
sources = new SourceList;
status.current = 1;
status.total = 1;
status.freeze = false;
status.quality = quality;
status.replace_existing_source = false;
status.split_midi_channels = false;
status.import_markers = false;
status.done = false;
status.cancel = false;
/* Import the source */
status.clear ();
status.paths.push_back (usable_file_path);
status.current = 1;
status.total = 1;
status.freeze = false;
status.quality = quality;
status.replace_existing_source = false;
status.split_midi_channels = false;
status.import_markers = false;
status.done = false;
status.cancel = false;
s->import_files (status);
int channelCount = 0;
status.progress = 1.0;
sources.clear ();
aafiAudioEssencePointer* aafAudioEssencePtr = NULL;
AAFI_foreachEssencePointer (aafAudioEssencePtrList, aafAudioEssencePtr)
{
if (aafAudioEssencePtr->essenceFile->usable_file_path)
status.paths.push_back (aafAudioEssencePtr->essenceFile->usable_file_path);
else
status.paths.push_back (aafAudioEssencePtr->essenceFile->original_file_path);
/* FIXME: There is no way to tell if cancel button was pressed
* or if the file failed to import, just that one of these occurred.
* We want status.cancel to reflect the user's choice only
*/
if (status.cancel && status.current > 1) {
/* Succeeded to import file, assume user hit cancel */
return false;
} else if (status.cancel && status.current == 1) {
/* Failed to import file, assume user did not hit cancel */
status.cancel = false;
return false;
channelCount++;
PBD::info << string_compose ("AAF: Preparing to import clip channel %1: %2\n", channelCount, aafAudioEssencePtr->essenceFile->unique_name);
}
s->import_files (status);
status.progress = 1.0;
sources->clear ();
/* FIXME: There is no way to tell if cancel button was pressed
* or if the file failed to import, just that one of these occurred.
* We want status.cancel to reflect the user's choice only
*/
if (status.cancel && status.current > 1) {
/* Succeeded to import file, assume user hit cancel */
return false;
} else if (status.cancel && status.current == 1) {
/* Failed to import file, assume user did not hit cancel */
status.cancel = false;
return false;
}
for (int i = 0; i < channelCount; i++) {
PropertyList proplist;
sources->push_back (status.sources.at (i));
proplist.add (ARDOUR::Properties::start, 0);
proplist.add (ARDOUR::Properties::length, timecnt_t ((*sources)[0]->length (), pos));
proplist.add (ARDOUR::Properties::name, aafAudioEssencePtrList->essenceFile->unique_name);
proplist.add (ARDOUR::Properties::layer, 0);
proplist.add (ARDOUR::Properties::whole_file, true);
proplist.add (ARDOUR::Properties::external, true);
RegionFactory::create (*sources, proplist);
}
/* build peakfiles */
for (SourceList::iterator x = sources->begin (); x != sources->end (); ++x) {
SourceFactory::setup_peakfile (*x, true);
}
aafAudioEssencePtrList->user = sources;
}
for (int i = 0; i < audioEssence->channels; i++) {
sources.push_back (status.sources.at (i));
}
/* build peakfiles */
for (SourceList::iterator x = sources.begin (); x != sources.end (); ++x) {
SourceFactory::setup_peakfile (*x, true);
}
*oneClipSources = sources;
/* Put the source on a region */
std::shared_ptr<Region> region;
string region_name;
string region_name;
/* take all the sources we have and package them up as a region */
region_name = region_name_from_path (status.paths.front (), (sources.size () > 1), false);
region_name = region_name_from_path (status.paths.front (), (sources->size () > 1), false);
/* we checked in import_sndfiles() that there were not too many */
while (RegionFactory::region_by_name (region_name)) {
region_name = bump_name_once (region_name, '.');
}
ws = audioEssence->unique_file_name;
string unique_file_name (ws.begin (), ws.end ());
PropertyList proplist;
proplist.add (ARDOUR::Properties::start, 0);
proplist.add (ARDOUR::Properties::length, timecnt_t (sources[0]->length (), pos));
proplist.add (ARDOUR::Properties::name, unique_file_name);
proplist.add (ARDOUR::Properties::layer, 0);
proplist.add (ARDOUR::Properties::whole_file, true);
proplist.add (ARDOUR::Properties::external, true);
region = RegionFactory::create (sources, proplist);
regions.push_back (region);
return true;
}
static std::shared_ptr<Region>
create_region (vector<std::shared_ptr<Region>> source_regions, aafiAudioClip* aafAudioClip, SourceList& oneClipSources, aafPosition_t clipOffset, aafRational_t samplerate_r)
{
wstring ws = aafAudioClip->essencePointerList->essence->unique_file_name; // XXX
string unique_file_name (ws.begin (), ws.end ());
string unique_file_name = aafAudioClip->essencePointerList->essenceFile->unique_name; // XXX
aafPosition_t clipPos = laaf_util_converUnit (aafAudioClip->pos, aafAudioClip->track->edit_rate, &samplerate_r);
aafPosition_t clipLen = laaf_util_converUnit (aafAudioClip->len, aafAudioClip->track->edit_rate, &samplerate_r);
aafPosition_t essenceOffset = laaf_util_converUnit (aafAudioClip->essence_offset, aafAudioClip->track->edit_rate, &samplerate_r);
aafPosition_t clipPos = aafi_convertUnit (aafAudioClip->pos, aafAudioClip->track->edit_rate, &samplerate_r);
aafPosition_t clipLen = aafi_convertUnit (aafAudioClip->len, aafAudioClip->track->edit_rate, &samplerate_r);
aafPosition_t essenceOffset = aafi_convertUnit (aafAudioClip->essence_offset, aafAudioClip->track->edit_rate, &samplerate_r);
PropertyList proplist;
@ -223,7 +274,7 @@ set_region_gain (aafiAudioClip* aafAudioClip, std::shared_ptr<Region> region, Se
std::shared_ptr<AudioRegion> ar = std::dynamic_pointer_cast<AudioRegion> (region);
std::shared_ptr<AutomationList> al = ar->envelope ();
for (int i = 0; i < level->pts_cnt; ++i) {
for (unsigned int i = 0; i < level->pts_cnt; ++i) {
al->fast_simple_add (timepos_t (aafRationalToFloat (level->time[i]) * region->length ().samples ()), aafRationalToFloat (level->value[i]));
}
}
@ -257,9 +308,9 @@ set_region_fade (aafiAudioClip* aafAudioClip, std::shared_ptr<Region> region, aa
return;
}
aafiTransition* fadein = aafi_get_fadein (aafAudioClip->Item);
aafiTransition* fadeout = aafi_get_fadeout (aafAudioClip->Item);
aafiTransition* xfade = aafi_get_xfade (aafAudioClip->Item);
aafiTransition* fadein = aafi_getFadeIn (aafAudioClip);
aafiTransition* fadeout = aafi_getFadeOut (aafAudioClip);
aafiTransition* xfade = (aafAudioClip->timelineItem->prev) ? aafi_timelineItemToCrossFade (aafAudioClip->timelineItem->prev) : NULL;
if (xfade) {
if (fadein == NULL) {
@ -273,15 +324,15 @@ set_region_fade (aafiAudioClip* aafAudioClip, std::shared_ptr<Region> region, aa
samplecnt_t fade_len;
if (fadein != NULL) {
fade_shape = aaf_fade_interpol_to_ardour_fade_shape ((aafiInterpolation_e) (fadein->flags & AAFI_INTERPOL_MASK));
fade_len = laaf_util_converUnit (fadein->len, aafAudioClip->track->edit_rate, samplerate);
fade_shape = aaf_fade_interpol_to_ardour_fade_shape ((aafiInterpolation_e)(fadein->flags & AAFI_INTERPOL_MASK));
fade_len = aafi_convertUnit (fadein->len, aafAudioClip->track->edit_rate, samplerate);
std::dynamic_pointer_cast<AudioRegion> (region)->set_fade_in (fade_shape, fade_len);
}
if (fadeout != NULL) {
fade_shape = aaf_fade_interpol_to_ardour_fade_shape ((aafiInterpolation_e) (fadeout->flags & AAFI_INTERPOL_MASK));
fade_len = laaf_util_converUnit (fadeout->len, aafAudioClip->track->edit_rate, samplerate);
fade_shape = aaf_fade_interpol_to_ardour_fade_shape ((aafiInterpolation_e)(fadeout->flags & AAFI_INTERPOL_MASK));
fade_len = aafi_convertUnit (fadeout->len, aafAudioClip->track->edit_rate, samplerate);
std::dynamic_pointer_cast<AudioRegion> (region)->set_fade_out (fade_shape, fade_len);
}
@ -346,7 +397,7 @@ set_session_timecode (AAF_Iface* aafi, Session* s)
break;
default:
PBD::error << string_compose ("Unknown AAF timecode fps : %1.", aafFPS) << endmsg;
PBD::error << string_compose ("Unknown AAF timecode fps : %1 (%2/%3).", aafFPS, aafi->Timecode->edit_rate->numerator, aafi->Timecode->edit_rate->denominator) << endmsg;
return;
}
@ -372,21 +423,41 @@ ARDOUR_UI::new_session_from_aaf (string const& aaf, string const& target_dir, st
}
}
/* Possible libaaf log to external file : part 1/2 */
// string logfile = Glib::build_filename (g_get_tmp_dir (), "aaf-import-XXXXXX.log");
// int logfd = g_mkstemp_full (&logfile[0], O_WRONLY, 0700);
//
// fprintf(stderr, "Logfile: %s\n",&logfile[0] );
//
// if (logfd < 0) {
// error << _("AAF: Could not prepare log file") << endmsg;
// fprintf(stderr, "AAF: Could not prepare log file\n" );
// return -1;
// }
//
// FILE *logfp = fdopen( logfd, "w" );
//
// if (!logfp) {
// error << _("AAF: Could not prepare log file") << endmsg;
// fprintf(stderr, "AAF: Could not prepare log file\n" );
// return -1;
// }
AAF_Iface* aafi = aafi_alloc (NULL);
uint32_t aaf_resolve_options = 0;
uint32_t aaf_protools_options = 0;
if (!aafi) {
error << "AAF: Could not init AAF library." << endmsg;
return -1;
}
/* protools options must be set (there is no sens not setting them with Ardour) */
uint32_t aaf_protools_options = (AAFI_PROTOOLS_OPT_REPLACE_CLIP_FADES | AAFI_PROTOOLS_OPT_REMOVE_SAMPLE_ACCURATE_EDIT);
aafi_set_option_int (aafi, "trace", 1);
aafi_set_option_int (aafi, "protools", aaf_protools_options);
aafi_set_option_int (aafi, "resolve", aaf_resolve_options);
// aafi_set_option_str (aafi, "media_location", media_location_path.c_str ());
// XXX use Glib::convert_with_fallback
aafi->ctx.options.forbid_nonlatin_filenames = 1;
aafi_set_debug (aafi, VERB_DEBUG, 0, 0, aaf_debug_callback, this);
//aafi_set_option_str (aafi, "media_location", media_location_path.c_str ());
aafi_set_debug (aafi, VERB_DEBUG, 0, NULL, &aaf_debug_callback, this);
if (aafi_load_file (aafi, aaf.c_str ())) {
error << "AAF: Could not load AAF file." << endmsg;
@ -394,19 +465,11 @@ ARDOUR_UI::new_session_from_aaf (string const& aaf, string const& target_dir, st
return -1;
}
/* extract or set session name */
if (aafi->compositionName && aafi->compositionName[0] != 0x00) {
wstring ws_session_name = std::wstring (aafi->compositionName);
snapshot = string (ws_session_name.begin (), ws_session_name.end ());
} else {
snapshot = basename_nosuffix (aaf);
}
snapshot = legalize_for_universal_path (snapshot);
snapshot = legalize_for_universal_path (basename_nosuffix (aaf));
path = Glib::build_filename (target_dir, snapshot);
if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
error << string_compose (_("AAF: Destination '%1' already exists."), path) << endmsg;
error << string_compose (_ ("AAF: Destination '%1' already exists."), path) << endmsg;
snapshot = ""; // XXX?
path = "";
aafi_release (&aafi);
@ -418,7 +481,7 @@ ARDOUR_UI::new_session_from_aaf (string const& aaf, string const& target_dir, st
char* td = g_dir_make_tmp ("aaf-cache-XXXXXX", &err);
if (!td) {
error << string_compose (_("AAF: Could not prepare media cache: %1"), err->message) << endmsg;
error << string_compose (_ ("AAF: Could not prepare media cache: %1"), err->message) << endmsg;
aafi_release (&aafi);
return -1;
}
@ -437,16 +500,16 @@ ARDOUR_UI::new_session_from_aaf (string const& aaf, string const& target_dir, st
samplerate_r.denominator = 1;
std::string restore_backend;
if (!AudioEngine::instance()->running ()) {
AudioEngine* e = AudioEngine::instance();
if (!AudioEngine::instance ()->running ()) {
AudioEngine* e = AudioEngine::instance ();
restore_backend = e->current_backend_name ();
e->set_backend ("None (Dummy)", "", "");
e->start ();
PluginManager::instance ().refresh (true);
attach_to_engine ();
}
if (!AudioEngine::instance()->running ()) {
error << _("Could not start [dummy] engine for AAF import .") << endmsg;
if (!AudioEngine::instance ()->running ()) {
PBD::error << _ ("AAF: Could not start [dummy] engine for AAF import .") << endmsg;
return -1;
}
@ -456,13 +519,31 @@ ARDOUR_UI::new_session_from_aaf (string const& aaf, string const& target_dir, st
aafi_release (&aafi);
PBD::remove_directory (media_cache_path);
if (!restore_backend.empty ()) {
AudioEngine::instance()->stop ();
AudioEngine::instance()->set_backend (restore_backend, "", "");
AudioEngine::instance ()->stop ();
AudioEngine::instance ()->set_backend (restore_backend, "", "");
}
error << _("Could not create new session for AAF import .") << endmsg;
error << _ ("AAF: Could not create new session for AAF import .") << endmsg;
return -1;
}
/* Possible libaaf log to external file : part 2/2
* Moving log file from temp/ to session/
*/
// string newlogfile = Glib::build_filename (path, "aaf-import.log");
//
// if (!PBD::copy_file (logfile, newlogfile)) {
// // if (g_rename (logfile.c_str(), newlogfile.c_str()) != 0) {
// error << string_compose (_("Could not copy logfile from \"%1\" to \"%2\": %3"),
// logfile, newlogfile, strerror (errno)) << endmsg;
// fprintf(stderr, "Could not copy logfile from \"%s\" to \"%s\": %s\n", logfile.c_str(), newlogfile.c_str(), strerror (errno) );
// } else {
// fprintf(stderr, "Copied logfile from \"%s\" to \"%s\"\n", logfile.c_str(), newlogfile.c_str() );
// g_unlink(logfile.c_str ());
// logfile = newlogfile;
// fprintf(stderr, "New logfile : \"%s\"\n", logfile.c_str() );
// }
switch (aafi->Audio->samplesize) {
case 16:
_session->config.set_native_file_data_format (ARDOUR::FormatInt16);
@ -479,121 +560,117 @@ ARDOUR_UI::new_session_from_aaf (string const& aaf, string const& target_dir, st
/* Import Sources */
SourceList oneClipSources;
SourceList* oneClipSources;
ARDOUR::ImportStatus import_status;
vector<std::shared_ptr<Region>> source_regions;
timepos_t pos = timepos_t::max (Temporal::AudioTime);
aafiAudioEssence* audioEssence = NULL;
aafiAudioTrack* aafAudioTrack = NULL;
aafiTimelineItem* aafAudioItem = NULL;
aafiAudioClip* aafAudioClip = NULL;
aafiAudioEssencePointer* aafAudioEssencePtr = NULL;
for (aafiAudioEssence* audioEssence = aafi->Audio->Essences; audioEssence != NULL; audioEssence = audioEssence->next) {
/* If we extract embedded essences to `s->session_directory().sound_path()` then we end up with a duplicate on import.
* So we extract essence to a cache folder
*/
aafPosition_t sessionStart = aafi_convertUnit (aafi->compositionStart, aafi->compositionStart_editRate, &samplerate_r);
if (audioEssence->is_embedded) {
if (media_cache_path.empty ()) {
error << _("Could not extract audio file from AAF: media cache was not set.") << endmsg;
continue;
}
if (aafi_extract_audio_essence (aafi, audioEssence, media_cache_path.c_str (), NULL) < 0) {
error << string_compose (_("AAF: Could not extract audio file '%1' from AAF."), audioEssence->unique_file_name) << endmsg;
continue;
}
} else {
if (!audioEssence->usable_file_path) {
error << string_compose (_("AAF: Could not locate external audio file: '%1'"), audioEssence->original_file_path) << endmsg;
continue;
}
}
if (!import_sndfile_as_region (_session, audioEssence, SrcBest, pos, oneClipSources, import_status, source_regions)) {
error << string_compose (_("AAF: Could not import '%1' to session."), audioEssence->unique_file_name) << endmsg;
continue;
}
audioEssence->user = new SourceList (oneClipSources);
info << string_compose ("Source file '%1' successfully imported to session.", audioEssence->unique_file_name) << endmsg;
}
oneClipSources.clear ();
aafPosition_t sessionStart = laaf_util_converUnit (aafi->compositionStart, aafi->compositionStart_editRate, &samplerate_r);
aafiAudioTrack* aafAudioTrack = NULL;
aafiTimelineItem* aafAudioItem = NULL;
aafiAudioClip* aafAudioClip = NULL;
foreach_audioTrack (aafAudioTrack, aafi)
AAFI_foreachAudioTrack (aafi, aafAudioTrack)
{
std::shared_ptr<AudioTrack> track = prepare_audio_track (aafAudioTrack, _session);
foreach_Item (aafAudioItem, aafAudioTrack)
AAFI_foreachTrackItem (aafAudioTrack, aafAudioItem)
{
if (aafAudioItem->type != AAFI_AUDIO_CLIP) {
aafAudioClip = aafi_timelineItemToAudioClip (aafAudioItem);
if (!aafAudioClip) {
continue;
}
aafAudioClip = (aafiAudioClip*)aafAudioItem->data;
if (aafAudioClip->essencePointerList == NULL) {
error << _("AAF: Clip has no essence.") << endmsg;
error << _ ("AAF: Clip has no essence.") << endmsg;
continue;
}
int essenceError = 0;
char* essenceName = aafAudioClip->essencePointerList->essenceFile->name;
AAFI_foreachEssencePointer (aafAudioClip->essencePointerList, aafAudioEssencePtr)
{
struct aafiAudioEssenceFile* audioEssenceFile = aafAudioEssencePtr->essenceFile;
if (!audioEssenceFile) {
PBD::error << string_compose (_ ("AAF: Could not create new region for clip '%1': Missing audio essence"), audioEssenceFile->unique_name) << endmsg;
essenceError++;
continue;
}
if (audioEssenceFile->is_embedded) {
if (aafi_extractAudioEssenceFile (aafi, audioEssenceFile, AAFI_EXTRACT_DEFAULT, media_cache_path.c_str (), 0, 0, NULL, NULL) < 0) {
PBD::error << string_compose ("AAF: Could not extract audio file '%1' from AAF.", audioEssenceFile->unique_name) << endmsg;
essenceError++;
continue;
}
} else if (!audioEssenceFile->is_embedded && !audioEssenceFile->usable_file_path) {
PBD::error << string_compose ("AAF: Could not locate external audio file: '%1'", audioEssenceFile->original_file_path) << endmsg;
essenceError++;
continue;
}
}
if (essenceError) {
PBD::error << string_compose ("AAF: Error parsing audio essence pointerlist : %1\n", essenceName);
continue;
}
if (!import_sndfile_as_region (_session, aafAudioClip->essencePointerList, SrcBest, pos, &oneClipSources, import_status, source_regions)) {
PBD::error << string_compose ("AAF: Could not import '%1' to session.", essenceName) << endmsg;
continue;
} else {
AAFI_foreachEssencePointer (aafAudioClip->essencePointerList, aafAudioEssencePtr)
{
if (aafAudioEssencePtr->essenceFile->is_embedded) {
g_unlink (aafAudioEssencePtr->essenceFile->usable_file_path);
}
}
}
if (!oneClipSources || oneClipSources->size () == 0) {
error << string_compose (_ ("AAF: Could not create new region for clip '%1': Region has no source"), essenceName) << endmsg;
continue;
}
std::shared_ptr<Region> region = create_region (source_regions, aafAudioClip, *oneClipSources, sessionStart, samplerate_r);
if (!region) {
error << string_compose (_ ("AAF: Could not create new region for clip '%1'"), essenceName) << endmsg;
continue;
}
/* converts whatever edit_rate clip is in, to samples */
aafPosition_t clipPos = laaf_util_converUnit (aafAudioClip->pos, aafAudioClip->track->edit_rate, &samplerate_r);
aafPosition_t clipPos = aafi_convertUnit (aafAudioClip->pos, aafAudioClip->track->edit_rate, &samplerate_r);
aafiAudioEssencePointer *audioEssencePtr = aafAudioClip->essencePointerList;
while (audioEssencePtr) {
struct aafiAudioEssence* audioEssence = audioEssencePtr->essence;
if (!audioEssence || !audioEssence->user) {
error << string_compose (_("AAF: Could not create new region for clip '%1': Missing audio essence"), audioEssence->unique_file_name) << endmsg;
continue;
}
SourceList* oneClipSources = static_cast<SourceList*> (audioEssence->user);
if (oneClipSources->size () == 0) {
error << string_compose (_("AAF: Could not create new region for clip '%1': Region has no source"), audioEssence->unique_file_name) << endmsg;
continue;
}
std::shared_ptr<Region> region = create_region (source_regions, aafAudioClip, *oneClipSources, sessionStart, samplerate_r);
if (!region) {
error << string_compose (_("AAF: Could not create new region for clip '%2'"), audioEssence->unique_file_name) << endmsg;
continue;
}
track->playlist ()->add_region (region, timepos_t (clipPos + sessionStart));
set_region_gain (aafAudioClip, region, _session);
set_region_fade (aafAudioClip, region, &samplerate_r);
if (aafAudioClip->mute) {
region->set_muted (true);
}
audioEssencePtr = audioEssencePtr->next;
track->playlist ()->add_region (region, timepos_t (clipPos + sessionStart));
set_region_gain (aafAudioClip, region, _session);
set_region_fade (aafAudioClip, region, &samplerate_r);
if (aafAudioClip->mute) {
region->set_muted (true);
}
}
}
for (aafiMarker* marker = aafi->Markers; marker != NULL; marker = marker->next) {
aafPosition_t markerStart = sessionStart + laaf_util_converUnit (marker->start, marker->edit_rate, &samplerate_r);
aafPosition_t markerEnd = sessionStart + laaf_util_converUnit ((marker->start + marker->length), marker->edit_rate, &samplerate_r);
// oneClipSources.clear ();
wstring markerName (marker->name);
aafiMarker* marker = NULL;
AAFI_foreachMarker (aafi, marker)
{
aafPosition_t markerStart = sessionStart + aafi_convertUnit (marker->start, marker->edit_rate, &samplerate_r);
aafPosition_t markerEnd = sessionStart + aafi_convertUnit ((marker->start + marker->length), marker->edit_rate, &samplerate_r);
Location* location;
if (marker->length == 0) {
location = new Location (*_session, timepos_t (markerStart), timepos_t (markerStart), string (markerName.begin (), markerName.end ()), Location::Flags (Location::IsMark));
location = new Location (*_session, timepos_t (markerStart), timepos_t (markerStart), marker->name, Location::Flags (Location::IsMark));
} else {
location = new Location (*_session, timepos_t (markerStart), timepos_t (markerEnd), string (markerName.begin (), markerName.end ()), Location::Flags (Location::IsRangeMarker));
location = new Location (*_session, timepos_t (markerStart), timepos_t (markerEnd), marker->name, Location::Flags (Location::IsRangeMarker));
}
_session->locations ()->add (location, true);
@ -604,8 +681,8 @@ ARDOUR_UI::new_session_from_aaf (string const& aaf, string const& target_dir, st
nominal_sample_rate.numerator = _session->nominal_sample_rate ();
nominal_sample_rate.denominator = 1;
samplepos_t start = samplepos_t (laaf_util_converUnit (aafi->compositionStart, aafi->compositionStart_editRate, &nominal_sample_rate));
samplepos_t end = samplepos_t (laaf_util_converUnit (aafi->compositionLength, aafi->compositionLength_editRate, &nominal_sample_rate)) + start;
samplepos_t start = samplepos_t (aafi_convertUnit (aafi->compositionStart, aafi->compositionStart_editRate, &nominal_sample_rate));
samplepos_t end = samplepos_t (aafi_convertUnit (aafi->compositionLength, aafi->compositionLength_editRate, &nominal_sample_rate)) + start;
_session->maybe_update_session_range (timepos_t (start), timepos_t (end));
/* set timecode */
@ -621,15 +698,6 @@ ARDOUR_UI::new_session_from_aaf (string const& aaf, string const& target_dir, st
_session->save_state ("");
/* clear */
foreachEssence (audioEssence, aafi->Audio->Essences)
{
if (audioEssence && audioEssence->user) {
static_cast<SourceList*> (audioEssence->user)->clear ();
}
}
source_regions.clear ();
PBD::remove_directory (media_cache_path);
@ -637,8 +705,8 @@ ARDOUR_UI::new_session_from_aaf (string const& aaf, string const& target_dir, st
aafi_release (&aafi);
if (!restore_backend.empty ()) {
AudioEngine::instance()->stop ();
AudioEngine::instance()->set_backend (restore_backend, "", "");
AudioEngine::instance ()->stop ();
AudioEngine::instance ()->set_backend (restore_backend, "", "");
}
return 0;
}

View File

@ -64,6 +64,7 @@
#include "editing.h"
#include "enums_convert.h"
#include "actions.h"
#include "meter_patterns.h"
#include "meterbridge.h"
#include "luawindow.h"
#include "mixer_ui.h"
@ -500,6 +501,12 @@ ARDOUR_UI::install_actions ()
act = ActionManager::register_toggle_action (main_actions, X_("ToggleLatencyCompensation"), _("Disable Latency Compensation"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_latency_switch));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_toggle_action (main_actions, X_("ResetAllPeakDisplays"), _("Reset Mixer Meter Peaks"), []() { ArdourMeter::ResetAllPeakDisplays (); });
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_toggle_action (main_actions, X_("ResetMeterPeakHold"), _("Reset All Meter Peak Hold"), []() { ArdourMeter::ResetAllPeakDisplays (); ActionManager::get_action ("Recorder", "reset-input-peak-hold")->activate (); });
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("MonitorMenu"), _("Monitor Section")); /* just the submenu item */
ActionManager::session_sensitive_actions.push_back (act);
@ -783,7 +790,7 @@ ARDOUR_UI::build_menu_bar ()
wall_clock_label.set_name ("WallClock");
wall_clock_label.set_use_markup ();
timecode_format_label.set_name ("WallClock");
timecode_format_label.set_name ("Timecode");
timecode_format_label.set_use_markup ();
peak_thread_work_label.set_name ("PeakThreadWork");
peak_thread_work_label.set_use_markup ();

View File

@ -122,7 +122,6 @@ ARDOUR_UI::create_xrun_marker (samplepos_t where)
void
ARDOUR_UI::halt_on_xrun_message ()
{
cerr << "HALT on xrun\n";
ArdourMessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
msg.run ();
}

View File

@ -50,6 +50,10 @@
#include "pbd/i18n.h"
#ifdef __APPLE__
extern void use_cocoa_invalidation (int); // cocoacarbon.mm
#endif
using namespace Gtk;
using namespace Gtkmm2ext;
using namespace ARDOUR;
@ -242,7 +246,8 @@ ARDOUR_UI::toggle_punch_out ()
void
ARDOUR_UI::show_loop_punch_ruler_and_disallow_hide ()
{
Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Rulers"), "toggle-loop-punch-ruler");
/* XXX FIX ME */
Glib::RefPtr<ToggleAction> tact; // = ActionManager::get_toggle_action (X_("Rulers"), "toggle-loop-punch-ruler");
tact->set_sensitive (false);
@ -255,9 +260,10 @@ ARDOUR_UI::show_loop_punch_ruler_and_disallow_hide ()
void
ARDOUR_UI::reenable_hide_loop_punch_ruler_if_appropriate ()
{
/* XXX FIX ME */
if (!_session->config.get_punch_in() && !_session->config.get_punch_out()) {
/* if punch in/out are now both off, reallow hiding of the loop/punch ruler */
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Rulers"), "toggle-loop-punch-ruler");
Glib::RefPtr<Action> act; // = ActionManager::get_action (X_("Rulers"), "toggle-loop-punch-ruler");
if (act) {
act->set_sensitive (true);
}
@ -501,6 +507,10 @@ ARDOUR_UI::parameter_changed (std::string p)
} else if (p == "no-strobe") {
stop_clocking ();
start_clocking ();
} else if (p == "use-cocoa-invalidation") {
#ifdef __APPLE__
use_cocoa_invalidation (UIConfiguration::instance().get_use_cocoa_invalidation());
#endif
}
}

View File

@ -33,10 +33,12 @@
#include "ardour/audioregion.h"
#include "ardour/session_event.h"
#include "ardour/dB.h"
#include "ardour/region_fx_plugin.h"
#include "audio_region_editor.h"
#include "audio_region_view.h"
#include "gui_thread.h"
#include "public_editor.h"
#include "pbd/i18n.h"
@ -52,11 +54,13 @@ _peak_amplitude_thread (void* arg)
return 0;
}
AudioRegionEditor::AudioRegionEditor (Session* s, std::shared_ptr<AudioRegion> r)
: RegionEditor (s, r)
, _audio_region (r)
AudioRegionEditor::AudioRegionEditor (Session* s, AudioRegionView* arv)
: RegionEditor (s, arv)
, _arv (arv)
, _audio_region (arv->audio_region ())
, gain_adjustment(accurate_coefficient_to_dB(fabsf (_audio_region->scale_amplitude())), -40.0, +40.0, 0.1, 1.0, 0)
, _polarity_toggle (_("Invert"))
, _show_on_touch (_("Show on Touch"))
, _peak_channel (false)
{
@ -87,14 +91,27 @@ AudioRegionEditor::AudioRegionEditor (Session* s, std::shared_ptr<AudioRegion> r
_polarity_label.set_name ("AudioRegionEditorLabel");
_polarity_label.set_text (_("Polarity:"));
_polarity_label.set_alignment (1, 0.5);
_table.attach (_polarity_label, 0, 1, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL);
_table.attach (_polarity_toggle, 1, 2, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL);
++_table_row;
_region_line_label.set_name ("AudioRegionEditorLabel");
_region_line_label.set_text (_("Region Line:"));
_region_line_label.set_alignment (1, 0.5);
_table.attach (_region_line_label, 0, 1, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL);
_table.attach (_region_line, 1, 2, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL);
_table.attach (_show_on_touch, 2, 3, _table_row, _table_row + 1, Gtk::FILL, Gtk::FILL);
++_table_row;
gain_changed ();
refill_region_line ();
gain_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &AudioRegionEditor::gain_adjustment_changed));
_polarity_toggle.signal_toggled().connect (sigc::mem_fun (*this, &AudioRegionEditor::gain_adjustment_changed));
_show_on_touch.signal_toggled().connect (sigc::mem_fun (*this, &AudioRegionEditor::show_on_touch_changed));
arv->region_line_changed.connect ((sigc::mem_fun (*this, &AudioRegionEditor::refill_region_line)));
_peak_amplitude.property_editable() = false;
_peak_amplitude.set_text (_("Calculating..."));
@ -105,6 +122,7 @@ AudioRegionEditor::AudioRegionEditor (Session* s, std::shared_ptr<AudioRegion> r
snprintf (name, 64, "peak amplitude-%p", this);
pthread_create_and_store (name, &_peak_amplitude_thread_handle, _peak_amplitude_thread, this);
signal_peak_thread ();
}
AudioRegionEditor::~AudioRegionEditor ()
@ -128,6 +146,14 @@ AudioRegionEditor::region_changed (const PBD::PropertyChange& what_changed)
signal_peak_thread ();
}
}
void
AudioRegionEditor::region_fx_changed ()
{
RegionEditor::region_fx_changed ();
refill_region_line ();
}
void
AudioRegionEditor::gain_changed ()
{
@ -189,3 +215,118 @@ AudioRegionEditor::peak_amplitude_found (double p)
_peak_amplitude.set_text (s.str ());
}
void
AudioRegionEditor::show_touched_automation (std::weak_ptr<PBD::Controllable> wac)
{
if (!_arv->set_region_fx_line (wac)) {
return;
}
switch (PublicEditor::instance ().current_mouse_mode ()) {
case Editing::MouseObject:
case Editing::MouseTimeFX:
case Editing::MouseGrid:
case Editing::MouseCut:
PublicEditor::instance ().set_mouse_mode (Editing::MouseDraw, false);
break;
default:
break;
}
}
void
AudioRegionEditor::show_on_touch_changed ()
{
if (!_show_on_touch.get_active ()) {
_ctrl_touched_connection.disconnect ();
return;
}
Controllable::ControlTouched.connect (_ctrl_touched_connection, invalidator (*this), boost::bind (&AudioRegionEditor::show_touched_automation, this, _1), gui_context ());
}
void
AudioRegionEditor::refill_region_line ()
{
using namespace Gtk::Menu_Helpers;
_region_line.clear_items ();
MenuList& rm_items (_region_line.items ());
int nth = 0;
PBD::ID rfx_id (0);
uint32_t param_id = 0;
string active_text = _("Gain Envelope");
_arv->get_region_fx_line (rfx_id, param_id);
_arv->set_ignore_line_change (true);
Gtk::RadioMenuItem::Group grp;
AudioRegionView* arv = _arv;
rm_items.push_back (RadioMenuElem (grp, _("Gain Envelope")));
Gtk::CheckMenuItem* cmi = static_cast<Gtk::CheckMenuItem*> (&rm_items.back ());
cmi->set_active (rfx_id == 0 || param_id == UINT32_MAX);
cmi->signal_activate ().connect ([cmi, arv] () { if (cmi->get_active ()) {arv->set_region_gain_line (); }});
_audio_region->foreach_plugin ([&rm_items, arv, &nth, &grp, &active_text, rfx_id, param_id](std::weak_ptr<RegionFxPlugin> wfx)
{
std::shared_ptr<RegionFxPlugin> fx (wfx.lock ());
if (!fx) {
return;
}
std::shared_ptr<Plugin> plugin = fx->plugin ();
Gtk::Menu* acm = manage (new Gtk::Menu);
MenuList& acm_items (acm->items ());
for (size_t i = 0; i < plugin->parameter_count (); ++i) {
if (!plugin->parameter_is_control (i) || !plugin->parameter_is_input (i)) {
continue;
}
const Evoral::Parameter param (PluginAutomation, 0, i);
std::string label = plugin->describe_parameter (param);
if (label == X_("latency") || label == X_("hidden")) {
continue;
}
std::shared_ptr<ARDOUR::AutomationControl> c (std::dynamic_pointer_cast<ARDOUR::AutomationControl> (fx->control (param)));
if (c && c->flags () & (Controllable::HiddenControl | Controllable::NotAutomatable)) {
continue;
}
bool active = fx->id () == rfx_id && param_id == i;
acm_items.push_back (RadioMenuElem (grp, label));
Gtk::CheckMenuItem* cmi = static_cast<Gtk::CheckMenuItem*> (&acm_items.back ());
cmi->set_active (active);
cmi->signal_activate ().connect ([cmi, arv, nth, i] () { if (cmi->get_active ()) {arv->set_region_fx_line (nth, i); }});
if (active) {
active_text = fx->name () + ": " + label;
}
}
if (!acm_items.empty ()) {
rm_items.push_back (MenuElem (fx->name (), *acm));
} else {
delete acm;
}
++nth;
});
if (rm_items.size () > 1) {
_show_on_touch.set_sensitive (true);
} else {
_show_on_touch.set_active (false);
_show_on_touch.set_sensitive (false);
}
_region_line.set_text (active_text);
_arv->set_ignore_line_change (false);
}
void
AudioRegionEditor::on_unmap ()
{
_show_on_touch.set_active (false);
ArdourDialog::on_unmap ();
}

View File

@ -37,6 +37,7 @@
#include <gtkmm/separator.h>
#include <gtkmm/spinbutton.h>
#include "widgets/ardour_dropdown.h"
#include "pbd/signals.h"
#include "pbd/crossthread.h"
@ -55,18 +56,25 @@ class AudioRegionView;
class AudioRegionEditor : public RegionEditor
{
public:
AudioRegionEditor (ARDOUR::Session*, std::shared_ptr<ARDOUR::AudioRegion>);
AudioRegionEditor (ARDOUR::Session*, AudioRegionView*);
~AudioRegionEditor ();
void peak_amplitude_thread ();
void on_unmap ();
private:
void region_changed (PBD::PropertyChange const &);
void region_fx_changed ();
void gain_changed ();
void gain_adjustment_changed ();
void refill_region_line ();
void show_on_touch_changed ();
void show_touched_automation (std::weak_ptr<PBD::Controllable>);
AudioRegionView* _arv;
std::shared_ptr<ARDOUR::AudioRegion> _audio_region;
Gtk::Label gain_label;
@ -79,6 +87,12 @@ private:
Gtk::Label _peak_amplitude_label;
Gtk::Entry _peak_amplitude;
Gtk::Label _region_line_label;
ArdourWidgets::ArdourDropdown _region_line;
Gtk::CheckButton _show_on_touch;
PBD::ScopedConnection _ctrl_touched_connection;
void signal_peak_thread ();
pthread_t _peak_amplitude_thread_handle;
void peak_amplitude_found (double);

View File

@ -36,6 +36,7 @@
#include "ardour/audioregion.h"
#include "ardour/audiosource.h"
#include "ardour/profile.h"
#include "ardour/region_fx_plugin.h"
#include "ardour/session.h"
#include "pbd/memento_command.h"
@ -112,8 +113,7 @@ static Cairo::RefPtr<Cairo::Pattern> create_pending_peak_pattern() {
return p;
}
AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxisView &tv, std::shared_ptr<AudioRegion> r, double spu,
uint32_t basic_color)
AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxisView &tv, std::shared_ptr<AudioRegion> r, double spu, uint32_t basic_color)
: RegionView (parent, tv, r, spu, basic_color)
, fade_in_handle(0)
, fade_out_handle(0)
@ -129,6 +129,9 @@ AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxis
, _amplitude_above_axis(1.0)
, trim_fade_in_drag_active(false)
, trim_fade_out_drag_active(false)
, _rfx_id (0)
, _rdx_param (UINT32_MAX)
, _ignore_line_change (false)
{
}
@ -149,6 +152,9 @@ AudioRegionView::AudioRegionView (ArdourCanvas::Container *parent, RouteTimeAxis
, _amplitude_above_axis(1.0)
, trim_fade_in_drag_active(false)
, trim_fade_out_drag_active(false)
, _rfx_id (0)
, _rdx_param (UINT32_MAX)
, _ignore_line_change (false)
{
}
@ -168,6 +174,9 @@ AudioRegionView::AudioRegionView (const AudioRegionView& other, std::shared_ptr<
, _amplitude_above_axis (other._amplitude_above_axis)
, trim_fade_in_drag_active(false)
, trim_fade_out_drag_active(false)
, _rfx_id (0)
, _rdx_param (UINT32_MAX)
, _ignore_line_change (false)
{
init (true);
}
@ -232,12 +241,7 @@ AudioRegionView::init (bool wfd)
set_fade_visibility (false);
}
const string line_name = _region->name() + ":gain";
gain_line.reset (new AudioRegionGainLine (line_name, *this, *group, audio_region()->envelope()));
update_envelope_visibility ();
gain_line->reset ();
set_region_gain_line ();
/* streamview will call set_height() */
//set_height (trackview.current_height()); // XXX not correct for Layered mode, but set_height() will fix later.
@ -278,7 +282,7 @@ AudioRegionView::init (bool wfd)
setup_waveform_visibility ();
get_canvas_frame()->set_data ("linemerger", (LineMerger*) this);
gain_line->canvas_group().raise_to_top ();
_fx_line->canvas_group().raise_to_top ();
/* XXX sync mark drag? */
}
@ -606,15 +610,15 @@ AudioRegionView::set_height (gdouble height)
}
}
if (gain_line) {
if (_fx_line) {
if ((height / nchans) < NAME_HIGHLIGHT_THRESH) {
gain_line->hide ();
_fx_line->hide ();
} else {
update_envelope_visibility ();
}
gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE) - 2);
_fx_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE) - 2);
}
reset_fade_shapes ();
@ -1081,8 +1085,8 @@ AudioRegionView::set_samples_per_pixel (gdouble fpp)
}
}
if (gain_line) {
gain_line->reset ();
if (_fx_line) {
_fx_line->reset ();
}
reset_fade_shapes ();
@ -1101,12 +1105,7 @@ AudioRegionView::set_colors ()
{
RegionView::set_colors();
if (gain_line) {
gain_line->set_line_color (audio_region()->envelope_active() ?
UIConfiguration::instance().color ("gain line") :
UIConfiguration::instance().color_mod ("gain line inactive", "gain line inactive"));
}
set_fx_line_colors ();
set_waveform_colors ();
if (start_xfade_curve) {
@ -1148,8 +1147,8 @@ AudioRegionView::setup_waveform_visibility ()
void
AudioRegionView::temporarily_hide_envelope ()
{
if (gain_line) {
gain_line->hide ();
if (_fx_line) {
_fx_line->hide ();
}
}
@ -1159,21 +1158,121 @@ AudioRegionView::unhide_envelope ()
update_envelope_visibility ();
}
void
AudioRegionView::set_region_gain_line ()
{
if (_ignore_line_change) {
return;
}
const string line_name = _region->name() + ":gain";
_fx_line.reset (new AudioRegionGainLine (line_name, *this, *group, audio_region()->envelope()));
_fx_line->set_height ((uint32_t) rint (height() - NAME_HIGHLIGHT_SIZE) - 2);
_fx_line->reset ();
_region_fx_connection.disconnect ();
bool changed = _rfx_id != PBD::ID (0) || _rdx_param != UINT32_MAX;
_rfx_id = PBD::ID (0);
_rdx_param = UINT32_MAX;
envelope_active_changed ();
if (changed) {
region_line_changed (); /* EMIT SIGNAL */
}
}
void
AudioRegionView::set_region_fx_line (std::shared_ptr<AutomationControl> ac, std::shared_ptr<RegionFxPlugin> rfx, uint32_t param_id)
{
const string line_name = _region->name () + ":" + rfx->describe_parameter (Evoral::Parameter (PluginAutomation, 0, param_id));
_fx_line.reset (new RegionFxLine (line_name, *this, *group, ac));
_fx_line->set_height ((uint32_t) rint (height() - NAME_HIGHLIGHT_SIZE) - 2);
_fx_line->reset ();
rfx->DropReferences.connect (_region_fx_connection, invalidator (*this), boost::bind (&AudioRegionView::set_region_gain_line, this), gui_context ());
bool changed = _rfx_id != rfx->id () || _rdx_param != param_id;
_rfx_id = rfx->id ();
_rdx_param = param_id;
envelope_active_changed ();
if (changed) {
region_line_changed (); /* EMIT SIGNAL */
}
}
bool
AudioRegionView::set_region_fx_line (uint32_t plugin_id, uint32_t param_id)
{
if (_ignore_line_change) {
return false;
}
std::shared_ptr<RegionFxPlugin> rfx = _region->nth_plugin (plugin_id);
if (rfx) {
std::shared_ptr<Evoral::Control> c = rfx->control (Evoral::Parameter (PluginAutomation, 0, param_id));
std::shared_ptr<AutomationControl> ac = std::dynamic_pointer_cast<AutomationControl> (c);
if (ac) {
set_region_fx_line (ac, rfx, param_id);
return true;
}
}
return false;
}
bool
AudioRegionView::set_region_fx_line (std::weak_ptr<PBD::Controllable> wac)
{
if (_ignore_line_change) {
return false;
}
std::shared_ptr<AutomationControl> ac = std::dynamic_pointer_cast<AutomationControl> (wac.lock ());
if (!ac) {
return false;
}
bool found = false;
_region->foreach_plugin ([this, ac, &found](std::weak_ptr<RegionFxPlugin> wfx)
{
std::shared_ptr<RegionFxPlugin> rfx (wfx.lock ());
if (!rfx || found) {
return;
}
std::shared_ptr<Plugin> plugin = rfx->plugin ();
for (size_t i = 0; i < plugin->parameter_count (); ++i) {
if (!plugin->parameter_is_control (i) || !plugin->parameter_is_input (i)) {
continue;
}
const Evoral::Parameter param (PluginAutomation, 0, i);
if (ac == std::dynamic_pointer_cast<ARDOUR::AutomationControl> (rfx->control (param))) {
set_region_fx_line (ac, rfx, i);
found = true;
break;
}
}
});
return found;
}
bool
AudioRegionView::get_region_fx_line (PBD::ID& id, uint32_t& param_id)
{
id = _rfx_id;
param_id = _rdx_param;
return _rdx_param != UINT32_MAX && _rfx_id != 0;
}
void
AudioRegionView::update_envelope_visibility ()
{
if (!gain_line) {
if (!_fx_line) {
return;
}
if (trackview.editor().current_mouse_mode() == Editing::MouseDraw || trackview.editor().current_mouse_mode() == Editing::MouseContent ) {
gain_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::ControlPoints|AutomationLine::Line));
gain_line->canvas_group().raise_to_top ();
_fx_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::ControlPoints|AutomationLine::Line));
_fx_line->canvas_group().raise_to_top ();
} else if (UIConfiguration::instance().get_show_region_gain() || trackview.editor().current_mouse_mode() == Editing::MouseRange ) {
gain_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::Line));
gain_line->canvas_group().raise_to_top ();
_fx_line->set_visibility (AutomationLine::VisibleAspects(AutomationLine::Line));
_fx_line->canvas_group().raise_to_top ();
} else {
gain_line->set_visibility (AutomationLine::VisibleAspects(0));
_fx_line->set_visibility (AutomationLine::VisibleAspects(0));
}
}
@ -1374,7 +1473,7 @@ AudioRegionView::peaks_ready_handler (uint32_t which)
void
AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, bool with_guard_points)
{
if (!gain_line) {
if (!_fx_line) {
return;
}
@ -1386,18 +1485,17 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b
samplecnt_t const sample_within_region = (samplecnt_t) floor (mx * samples_per_pixel);
if (!gain_line->control_points_adjacent (sample_within_region, before_p, after_p)) {
/* no adjacent points */
return;
double y = my;
if (_fx_line->control_points_adjacent (sample_within_region, before_p, after_p)) {
/* y is in item frame */
double const bx = _fx_line->nth (before_p)->get_x();
double const ax = _fx_line->nth (after_p)->get_x();
double const click_ratio = (ax - mx) / (ax - bx);
y = ((_fx_line->nth (before_p)->get_y() * click_ratio) + (_fx_line->nth (after_p)->get_y() * (1 - click_ratio)));
}
/* y is in item frame */
double const bx = gain_line->nth (before_p)->get_x();
double const ax = gain_line->nth (after_p)->get_x();
double const click_ratio = (ax - mx) / (ax - bx);
double y = ((gain_line->nth (before_p)->get_y() * click_ratio) + (gain_line->nth (after_p)->get_y() * (1 - click_ratio)));
/* don't create points that can't be seen */
update_envelope_visibility ();
@ -1412,55 +1510,37 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b
/* compute vertical fractional position */
y = 1.0 - (y / (gain_line->height()));
y = 1.0 - (y / (_fx_line->height()));
/* map using gain line */
gain_line->view_to_model_coord_y (y);
_fx_line->view_to_model_coord_y (y);
/* XXX STATEFUL: can't convert to stateful diff until we
can represent automation data with it.
*/
XMLNode &before = audio_region()->envelope()->get_state();
MementoCommand<AudioRegion>* region_memento = 0;
if (!audio_region()->envelope_active()) {
XMLNode &region_before = audio_region()->get_state();
audio_region()->set_envelope_active(true);
XMLNode &region_after = audio_region()->get_state();
region_memento = new MementoCommand<AudioRegion>(*(audio_region().get()), &region_before, &region_after);
}
if (audio_region()->envelope()->editor_add (timepos_t (fx), y, with_guard_points)) {
XMLNode &after = audio_region()->envelope()->get_state();
XMLNode &before = _fx_line->the_list()->get_state();
if (_fx_line->the_list()->editor_add (timepos_t (fx), y, with_guard_points)) {
XMLNode &after = _fx_line->the_list()->get_state();
std::list<Selectable*> results;
trackview.editor().begin_reversible_command (_("add gain control point"));
if (region_memento) {
trackview.session()->add_command (region_memento);
}
_fx_line->enable_autoation ();
trackview.session()->add_command (new MementoCommand<AutomationList>(*audio_region()->envelope().get(), &before, &after));
trackview.session()->add_command (new MementoCommand<AutomationList>(*_fx_line->the_list(), &before, &after));
gain_line->get_selectables (region ()->position () + timecnt_t (fx), region ()->position () + timecnt_t (fx), 0.0, 1.0, results);
_fx_line->get_selectables (region ()->position () + timecnt_t (fx), region ()->position () + timecnt_t (fx), 0.0, 1.0, results);
trackview.editor ().get_selection ().set (results);
trackview.editor ().commit_reversible_command ();
trackview.session ()->set_dirty ();
} else {
delete region_memento;
delete &before;
}
}
void
AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent* /*ev*/)
{
ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
audio_region()->envelope()->erase (cp->model());
}
GhostRegion*
AudioRegionView::add_ghost (TimeAxisView& tv)
{
@ -1557,10 +1637,6 @@ AudioRegionView::exited ()
trackview.editor().set_current_trimmable (std::shared_ptr<Trimmable>());
trackview.editor().set_current_movable (std::shared_ptr<Movable>());
// if (gain_line) {
// gain_line->remove_visibility (AutomationLine::ControlPoints);
// }
if (fade_in_handle) { fade_in_handle->hide(); }
if (fade_out_handle) { fade_out_handle->hide(); }
if (fade_in_trim_handle) { fade_in_trim_handle->hide(); }
@ -1572,12 +1648,8 @@ AudioRegionView::exited ()
void
AudioRegionView::envelope_active_changed ()
{
if (gain_line) {
gain_line->set_line_color (audio_region()->envelope_active() ?
UIConfiguration::instance().color ("gain line") :
UIConfiguration::instance().color_mod ("gain line inactive", "gain line inactive"));
update_envelope_visibility ();
}
set_fx_line_colors ();
update_envelope_visibility ();
}
void
@ -1595,6 +1667,22 @@ AudioRegionView::color_handler ()
}
void
AudioRegionView::set_fx_line_colors ()
{
if (!_fx_line) {
return;
}
if (_rdx_param != UINT32_MAX && _rfx_id != 0) {
_fx_line->set_line_color ("region automation line");
} else if (audio_region()->envelope_active()) {
_fx_line->set_line_color ("gain line");
} else {
_fx_line->set_line_color ("gain line inactive", "gain line inactive");
}
}
void
AudioRegionView::set_waveform_colors ()
{
@ -1696,7 +1784,7 @@ void
AudioRegionView::show_region_editor ()
{
if (editor == 0) {
editor = new AudioRegionEditor (trackview.session(), audio_region());
editor = new AudioRegionEditor (trackview.session(), this);
}
editor->present ();
@ -1858,7 +1946,7 @@ AudioRegionView::parameter_changed (string const & p)
MergeableLine*
AudioRegionView::make_merger ()
{
return new MergeableLine (gain_line, std::shared_ptr<AutomationControl>(),
return new MergeableLine (_fx_line, std::shared_ptr<AutomationControl>(),
[this](timepos_t const& t) { return timepos_t (_region->position().distance (t)); },
nullptr, nullptr);
}

View File

@ -50,9 +50,9 @@ namespace ARDOUR {
};
class AudioTimeAxisView;
class AudioRegionGainLine;
class GhostRegion;
class AutomationTimeAxisView;
class RegionFxLine;
class RouteTimeAxisView;
class AudioRegionView : public RegionView, public LineMerger
@ -91,12 +91,18 @@ public:
void temporarily_hide_envelope (); ///< Dangerous!
void unhide_envelope (); ///< Dangerous!
void set_region_gain_line ();
void set_ignore_line_change (bool v) { _ignore_line_change = v; };
bool set_region_fx_line (uint32_t, uint32_t);
bool set_region_fx_line (std::weak_ptr<PBD::Controllable>);
bool get_region_fx_line (PBD::ID&, uint32_t&);
void update_envelope_visibility ();
void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event, bool with_guard_points);
void remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event);
sigc::signal<void> region_line_changed;
std::shared_ptr<AudioRegionGainLine> get_gain_line() const { return gain_line; }
void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event, bool with_guard_points);
std::shared_ptr<RegionFxLine> fx_line() const { return _fx_line; }
void region_changed (const PBD::PropertyChange&);
void envelope_active_changed ();
@ -184,7 +190,7 @@ protected:
ArdourCanvas::Rectangle* end_xfade_rect;
bool _end_xfade_visible;
std::shared_ptr<AudioRegionGainLine> gain_line;
std::shared_ptr<RegionFxLine> _fx_line;
double _amplitude_above_axis;
@ -206,6 +212,7 @@ protected:
void set_colors ();
void set_waveform_colors ();
void set_fx_line_colors ();
void reset_width_dependent_items (double pixel_width);
void color_handler ();
@ -234,6 +241,14 @@ private:
bool trim_fade_in_drag_active;
bool trim_fade_out_drag_active;
void set_region_fx_line (std::shared_ptr<ARDOUR::AutomationControl>, std::shared_ptr<ARDOUR::RegionFxPlugin>, uint32_t);
PBD::ID _rfx_id;
uint32_t _rdx_param;
bool _ignore_line_change;
PBD::ScopedConnection _region_fx_connection;
};
#endif /* __gtk_ardour_audio_region_view_h__ */

View File

@ -470,8 +470,8 @@ AudioStreamView::set_selected_points (PointSelection& points)
{
for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv && arv->get_gain_line ()) {
arv->get_gain_line ()->set_selected_points (points);
if (arv && arv->fx_line ()) {
arv->fx_line ()->set_selected_points (points);
}
}
}

View File

@ -87,11 +87,12 @@ using namespace Temporal;
AutomationLine::AutomationLine (const string& name,
TimeAxisView& tv,
ArdourCanvas::Item& parent,
std::shared_ptr<AutomationList> al,
std::shared_ptr<AutomationList> al,
const ParameterDescriptor& desc)
: trackview (tv)
, _name (name)
, _height (0)
, _line_color ("automation line")
, _view_index_offset (0)
, alist (al)
, _visible (Line)
@ -210,6 +211,7 @@ AutomationLine::get_uses_gain_mapping () const
case BusSendLevel:
case EnvelopeAutomation:
case TrimAutomation:
case SurroundSendLevel:
case InsertReturnLevel:
return true;
default:
@ -263,14 +265,23 @@ AutomationLine::set_height (guint32 h)
}
void
AutomationLine::set_line_color (uint32_t color)
AutomationLine::set_line_color (string color_name, std::string color_mod)
{
_line_color = color;
_line_color = color_name;
_line_color_mod = color_mod;
uint32_t color = UIConfiguration::instance().color (color_name);
line->set_outline_color (color);
Gtkmm2ext::SVAModifier mod = UIConfiguration::instance().modifier ("automation line fill");
Gtkmm2ext::SVAModifier mod = UIConfiguration::instance().modifier (color_mod.empty () ? "automation line fill" : color_mod);
line->set_fill_color ((color & 0xffffff00) + mod.a()*255);
line->set_fill_color ((color & 0xffffff00) + mod.a() * 255);
}
uint32_t
AutomationLine::get_line_color() const
{
return UIConfiguration::instance().color (_line_color);
}
ControlPoint*
@ -404,6 +415,7 @@ AutomationLine::string_to_fraction (string const & s) const
case BusSendLevel:
case EnvelopeAutomation:
case TrimAutomation:
case SurroundSendLevel:
case InsertReturnLevel:
if (s == "-inf") { /* translation */
v = 0;
@ -994,7 +1006,7 @@ AutomationLine::set_selected_points (PointSelection const & points)
void
AutomationLine::set_colors ()
{
set_line_color (UIConfiguration::instance().color ("automation line"));
set_line_color (_line_color, _line_color_mod);
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
(*i)->set_color ();
}

View File

@ -68,7 +68,7 @@ public:
AutomationLine (const std::string& name,
TimeAxisView& tv,
ArdourCanvas::Item& parent,
std::shared_ptr<ARDOUR::AutomationList> al,
std::shared_ptr<ARDOUR::AutomationList> al,
const ARDOUR::ParameterDescriptor& desc);
@ -94,6 +94,7 @@ public:
virtual void start_drag_multiple (std::list<ControlPoint*>, float, XMLNode *);
virtual std::pair<float, float> drag_motion (Temporal::timecnt_t const &, float, bool, bool with_push, uint32_t& final_index);
virtual void end_drag (bool with_push, uint32_t final_index);
virtual void end_draw_merge () {}
ControlPoint* nth (uint32_t);
ControlPoint const * nth (uint32_t) const;
@ -103,8 +104,8 @@ public:
bool visible() const { return _visible != VisibleAspects(0); }
guint32 height() const { return _height; }
void set_line_color (uint32_t);
uint32_t get_line_color() const { return _line_color; }
void set_line_color (std::string color, std::string mod = "");
uint32_t get_line_color() const;
void set_visibility (VisibleAspects);
void add_visibility (VisibleAspects);
@ -173,7 +174,8 @@ protected:
std::string _name;
guint32 _height;
uint32_t _line_color;
std::string _line_color;
std::string _line_color_mod;
uint32_t _view_index_offset;
std::shared_ptr<ARDOUR::AutomationList> alist;
@ -247,6 +249,7 @@ private:
const ARDOUR::ParameterDescriptor _desc;
friend class AudioRegionGainLine;
friend class RegionFxLine;
};
#endif /* __ardour_automation_line_h__ */

View File

@ -350,7 +350,7 @@ AutomationTimeAxisView::add_contents (bool show_regions)
)
);
line->set_line_color (UIConfiguration::instance().color ("processor automation line"));
line->set_line_color ("processor automation line");
line->set_fill (true);
line->queue_reset ();
add_line (line);

View File

@ -151,12 +151,15 @@ AxisView::set_name_ellipsize_mode ()
switch (UIConfiguration::instance().get_time_axis_name_ellipsize_mode()) {
case -1:
name_label.set_ellipsize (Pango::ELLIPSIZE_START);
inactive_label.set_ellipsize (Pango::ELLIPSIZE_START);
break;
case 1:
name_label.set_ellipsize (Pango::ELLIPSIZE_END);
inactive_label.set_ellipsize (Pango::ELLIPSIZE_END);
break;
default:
name_label.set_ellipsize (Pango::ELLIPSIZE_MIDDLE);
inactive_label.set_ellipsize (Pango::ELLIPSIZE_MIDDLE);
break;
}
}

View File

@ -201,3 +201,10 @@ query_darwin_version ()
}
return -1;
}
void
use_cocoa_invalidation (int yn)
{
gdk_quartz_set_use_cocoa_invalidation (yn);
std::cerr << "cocoa invalidation: " << yn << std::endl;
}

View File

@ -289,8 +289,6 @@ Editor::Editor ()
, meter_group (0)
, marker_group (0)
, range_marker_group (0)
, transport_marker_group (0)
, cd_marker_group (0)
, section_marker_group (0)
, _time_markers_group (0)
, _selection_marker_group (0)
@ -326,10 +324,7 @@ Editor::Editor ()
, meter_bar (0)
, marker_bar (0)
, range_marker_bar (0)
, transport_marker_bar (0)
, cd_marker_bar (0)
, section_marker_bar (0)
, cue_marker_bar (0)
, ruler_separator (0)
, minsec_label (_("Mins:Secs"))
, bbt_label (_("Bars:Beats"))
@ -339,8 +334,6 @@ Editor::Editor ()
, meter_label (_("Time Signature"))
, mark_label (_("Location Markers"))
, range_mark_label (_("Range Markers"))
, transport_mark_label (_("Loop/Punch Ranges"))
, cd_mark_label (_("CD Markers"))
, section_mark_label (_("Arrangement"))
, cue_mark_label (_("Cue Markers"))
, videotl_label (_("Video Timeline"))
@ -411,11 +404,7 @@ Editor::Editor ()
, _section_box (0)
, _playhead_cursor (0)
, _snapped_cursor (0)
, cd_marker_bar_drag_rect (0)
, cue_marker_bar_drag_rect (0)
, range_bar_drag_rect (0)
, transport_bar_drag_rect (0)
, transport_bar_range_rect (0)
, transport_bar_preroll_rect (0)
, transport_bar_postroll_rect (0)
, transport_loop_range_rect (0)
@ -473,6 +462,9 @@ Editor::Editor ()
, quantize_dialog (0)
, _main_menu_disabler (0)
, domain_bounce_info (nullptr)
, track_drag (nullptr)
, _visible_marker_types (all_marker_types)
, _visible_range_types (all_range_types)
{
/* we are a singleton */
@ -555,13 +547,6 @@ Editor::Editor ()
mark_label.hide();
mark_label.set_no_show_all();
cd_mark_label.set_name ("EditorRulerLabel");
cd_mark_label.set_size_request (-1, (int)timebar_height);
cd_mark_label.set_alignment (1.0, 0.5);
cd_mark_label.set_padding (5,0);
cd_mark_label.hide();
cd_mark_label.set_no_show_all();
section_mark_label.set_name ("EditorRulerLabel");
section_mark_label.set_size_request (-1, (int)timebar_height);
section_mark_label.set_alignment (1.0, 0.5);
@ -569,13 +554,6 @@ Editor::Editor ()
section_mark_label.hide();
section_mark_label.set_no_show_all();
cue_mark_label.set_name ("EditorRulerLabel");
cue_mark_label.set_size_request (-1, (int)timebar_height);
cue_mark_label.set_alignment (1.0, 0.5);
cue_mark_label.set_padding (5,0);
cue_mark_label.hide();
cue_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);
@ -591,13 +569,6 @@ Editor::Editor ()
range_mark_label.hide();
range_mark_label.set_no_show_all();
transport_mark_label.set_name ("EditorRulerLabel");
transport_mark_label.set_size_request (-1, (int)timebar_height);
transport_mark_label.set_alignment (1.0, 0.5);
transport_mark_label.set_padding (5,0);
transport_mark_label.hide();
transport_mark_label.set_no_show_all();
initialize_canvas ();
CairoWidget::set_focus_handler (sigc::mem_fun (ARDOUR_UI::instance(), &ARDOUR_UI::reset_focus));
@ -640,7 +611,6 @@ Editor::Editor ()
_cursors = new MouseCursors;
_cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
cerr << "Set cursor set to " << UIConfiguration::instance().get_icon_set() << endl;
/* Push default cursor to ever-present bottom of cursor stack. */
push_canvas_cursor(_cursors->grabber);
@ -2289,7 +2259,6 @@ Editor::show_rulers_for_grid ()
ruler_samples_action->set_active(false);
}
} else if (_grid_type == GridTypeCDFrame) {
ruler_cd_marker_action->set_active(true);
ruler_minsec_action->set_active(true);
if (UIConfiguration::instance().get_rulers_follow_grid()) {
@ -2606,11 +2575,10 @@ Editor::set_state (const XMLNode& node, int version)
yn = false;
node.get_property ("join-object-range", yn);
{
RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
/* do it twice to force the change */
tact->set_active (!yn);
tact->set_active (yn);
set_mouse_mode(mouse_mode, true);
smart_mode_action->set_active (!yn);
smart_mode_action->set_active (yn);
set_mouse_mode (mouse_mode, true);
}
EditPoint ep;
@ -2821,7 +2789,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 ();
}
}
}
@ -3045,22 +3015,7 @@ Editor::_snap_to_bbt (timepos_t const & presnap, Temporal::RoundMode direction,
*/
if (grid_type == GridTypeBar) {
TempoMetric m (tmap->metric_at (presnap));
BBT_Argument bbt (m.bbt_at (presnap));
switch (direction) {
case RoundDownAlways:
bbt = BBT_Argument (bbt.reference(), bbt.round_down_to_bar ());
break;
case RoundUpAlways:
bbt = BBT_Argument (bbt.reference(), bbt.round_up_to_bar ());
break;
case RoundNearest:
bbt = BBT_Argument (bbt.reference(), m.round_to_bar (bbt));
break;
default:
break;
}
return timepos_t (tmap->quarters_at (bbt));
return timepos_t (tmap->quarters_at (presnap).round_to_subdivision (get_grid_beat_divisions(_grid_type), direction));
}
if (gpref != SnapToGrid_Unscaled) { // use the visual grid lines which are limited by the zoom scale that the user selected
@ -4056,6 +4011,7 @@ void
Editor::grid_type_selection_done (GridType gridtype)
{
RefPtr<RadioAction> ract = grid_type_action (gridtype);
if (ract && ract->get_active()) { /*radio-action is already set*/
set_grid_to(gridtype); /*so we must set internal state here*/
} else {
@ -4295,6 +4251,11 @@ Editor::override_visible_track_count ()
bool
Editor::edit_controls_button_event (GdkEventButton* ev)
{
if (ev->type == GDK_BUTTON_RELEASE && track_dragging()) {
end_track_drag ();
return true;
}
if ((ev->type == GDK_2BUTTON_PRESS && ev->button == 1) || (ev->type == GDK_BUTTON_RELEASE && Keyboard::is_context_menu_event (ev))) {
ARDOUR_UI::instance()->add_route ();
} else if (ev->button == 1 && ev->type == GDK_BUTTON_PRESS) {
@ -6183,6 +6144,54 @@ struct TrackViewStripableSorter
}
};
static const int track_drag_spacer_height = 25;
void
Editor::maybe_move_tracks ()
{
for (auto & tv : track_views) {
if (!tv->marked_for_display () || (tv == track_drag->track)) {
continue;
}
/* find the track the mouse pointer is within, and if
* we're in the upper or lower half of it (depending on
* drag direction, move the spacer.
*/
if (track_drag->current >= tv->y_position() && track_drag->current < (tv->y_position() + tv->effective_height())) {
if (track_drag->bump_track == tv) {
/* already bumped for this track */
break;
}
if (track_drag->direction < 0) {
/* dragging up */
if (track_drag->current < (tv->y_position() + (tv->effective_height() / 2))) {
/* in top half of this track, move spacer */
track_drag->bump_track = tv;
move_selected_tracks (true);
}
} else if (track_drag->direction > 0) {
/* dragging down */
if (track_drag->current > (tv->y_position() + (tv->effective_height() / 2))) {
track_drag->bump_track = tv;
move_selected_tracks (false);
}
}
break;
}
}
}
bool
Editor::redisplay_track_views ()
{
@ -6199,21 +6208,24 @@ Editor::redisplay_track_views ()
track_views.sort (TrackViewStripableSorter ());
uint32_t position;
TrackViewList::const_iterator i;
if (track_drag) { // && track_drag->spacer) {
maybe_move_tracks ();
}
/* n will be the count of tracks plus children (updated by TimeAxisView::show_at),
* so we will use that to know where to put things.
*/
int n;
for (n = 0, position = 0, i = track_views.begin(); i != track_views.end(); ++i) {
TimeAxisView *tv = (*i);
int n = 0;
uint32_t position = 0;
for (auto & tv : track_views) {
if (tv->marked_for_display ()) {
position += tv->show_at (position, n, &edit_controls_vbox);
} else {
tv->hide ();
}
n++;
}
@ -6529,12 +6541,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 */
@ -7011,3 +7027,74 @@ Editor::default_time_domain () const
}
return BeatTime;
}
void
Editor::start_track_drag (TimeAxisView& tav, int y, Gtk::Widget& w)
{
track_drag = new TrackDrag (dynamic_cast<RouteTimeAxisView*> (&tav));
track_drag->drag_cursor = _cursors->move->gobj();
track_drag->predrag_cursor = gdk_window_get_cursor (edit_controls_vbox.get_window()->gobj());
gdk_window_set_cursor (edit_controls_vbox.get_toplevel()->get_window()->gobj(), track_drag->drag_cursor);
int xo, yo;
w.translate_coordinates (edit_controls_vbox, 0, y, xo, yo);
track_drag->have_predrag_cursor = true;
track_drag->bump_track = nullptr;
track_drag->previous = yo;
track_drag->start = yo;
}
void
Editor::mid_track_drag (GdkEventMotion* ev, Gtk::Widget& w)
{
int xo, yo;
w.translate_coordinates (edit_controls_vbox, ev->x, ev->y, xo, yo);
if (track_drag->first_move) {
if (!track_drag->track->selected()) {
set_selected_track (*track_drag->track, Selection::Set, false);
}
track_drag->first_move = false;
}
track_drag->current = yo;
if (track_drag->current > track_drag->previous) {
if (track_drag->direction != 1) {
track_drag->bump_track = nullptr;
track_drag->direction = 1;
}
} else if (track_drag->current < track_drag->previous) {
if (track_drag->direction != -1) {
track_drag->bump_track = nullptr;
track_drag->direction = -1;
}
}
if (track_drag->current == track_drag->previous) {
return;
}
redisplay_track_views ();
track_drag->previous = yo;
}
void
Editor::end_track_drag ()
{
if (track_drag->have_predrag_cursor) {
gdk_window_set_cursor (edit_controls_vbox.get_toplevel()->get_window()->gobj(), track_drag->predrag_cursor);
}
delete track_drag;
track_drag = nullptr;
}
bool
Editor::track_dragging() const
{
return (bool) track_drag;
}

View File

@ -935,10 +935,7 @@ private:
ArdourCanvas::Container* meter_group;
ArdourCanvas::Container* marker_group;
ArdourCanvas::Container* range_marker_group;
ArdourCanvas::Container* transport_marker_group;
ArdourCanvas::Container* cd_marker_group;
ArdourCanvas::Container* section_marker_group;
ArdourCanvas::Container* cue_marker_group;
/* parent for groups which themselves contain time markers */
ArdourCanvas::Container* _time_markers_group;
@ -987,13 +984,22 @@ private:
Glib::RefPtr<Gtk::ToggleAction> ruler_meter_action;
Glib::RefPtr<Gtk::ToggleAction> ruler_tempo_action;
Glib::RefPtr<Gtk::ToggleAction> ruler_range_action;
Glib::RefPtr<Gtk::ToggleAction> ruler_loop_punch_action;
Glib::RefPtr<Gtk::ToggleAction> ruler_cd_marker_action;
Glib::RefPtr<Gtk::ToggleAction> ruler_section_action;
Glib::RefPtr<Gtk::ToggleAction> ruler_marker_action;
Glib::RefPtr<Gtk::ToggleAction> ruler_cue_marker_action;
bool no_ruler_shown_update;
Glib::RefPtr<Gtk::RadioAction> all_marker_action;
Glib::RefPtr<Gtk::RadioAction> cd_marker_action;
Glib::RefPtr<Gtk::RadioAction> scene_marker_action;
Glib::RefPtr<Gtk::RadioAction> cue_marker_action;
Glib::RefPtr<Gtk::RadioAction> location_marker_action;
Glib::RefPtr<Gtk::RadioAction> all_range_action;
Glib::RefPtr<Gtk::RadioAction> punch_range_action;
Glib::RefPtr<Gtk::RadioAction> loop_range_action;
Glib::RefPtr<Gtk::RadioAction> session_range_action;
Glib::RefPtr<Gtk::RadioAction> other_range_action;
Gtk::Widget* ruler_grabbed_widget;
RulerDialog* ruler_dialog;
@ -1079,10 +1085,7 @@ private:
ArdourCanvas::Rectangle* meter_bar;
ArdourCanvas::Rectangle* marker_bar;
ArdourCanvas::Rectangle* range_marker_bar;
ArdourCanvas::Rectangle* transport_marker_bar;
ArdourCanvas::Rectangle* cd_marker_bar;
ArdourCanvas::Rectangle* section_marker_bar;
ArdourCanvas::Rectangle* cue_marker_bar;
ArdourCanvas::Line* ruler_separator;
void toggle_cue_behavior ();
@ -1095,8 +1098,6 @@ private:
Gtk::Label meter_label;
Gtk::Label mark_label;
Gtk::Label range_mark_label;
Gtk::Label transport_mark_label;
Gtk::Label cd_mark_label;
Gtk::Label section_mark_label;
Gtk::Label cue_mark_label;
@ -1409,6 +1410,11 @@ private:
void insert_patch_change (bool from_context);
void fork_selected_regions ();
void fork_regions_from_unselected ();
void start_track_drag (TimeAxisView&, int y, Gtk::Widget& w);
void mid_track_drag (GdkEventMotion*, Gtk::Widget& e);
void end_track_drag ();
void maybe_move_tracks ();
bool track_dragging() const;
void do_insert_time ();
void insert_time (Temporal::timepos_t const &, Temporal::timecnt_t const &, Editing::InsertTimeOption, bool, bool, bool, bool);
@ -1593,6 +1599,7 @@ private:
void clear_xrun_markers ();
void clear_ranges ();
void clear_cues ();
void clear_scenes ();
void clear_locations ();
void unhide_markers ();
void unhide_ranges ();
@ -1789,6 +1796,29 @@ private:
Editing::EditPoint edit_point() const { return _edit_point; }
enum MarkerBarType {
CueMarks = 0x1,
SceneMarks = 0x2,
CDMarks = 0x4,
LocationMarks = 0x8
};
enum RangeBarType {
PunchRange = 0x1,
LoopRange = 0x2,
SessionRange = 0x4,
OtherRange = 0x8
};
static const MarkerBarType all_marker_types = MarkerBarType (CueMarks|SceneMarks|CDMarks|LocationMarks);
static const RangeBarType all_range_types = RangeBarType (PunchRange|LoopRange|SessionRange|OtherRange);
MarkerBarType visible_marker_types () const;
RangeBarType visible_range_types () const;
void set_visible_marker_types (MarkerBarType);
void set_visible_range_types (RangeBarType);
protected:
void _commit_tempo_map_edit (Temporal::TempoMap::WritableSharedPtr&, bool with_update = false);
@ -2127,11 +2157,7 @@ private:
/* transport range select process */
ArdourCanvas::Rectangle* cd_marker_bar_drag_rect;
ArdourCanvas::Rectangle* cue_marker_bar_drag_rect;
ArdourCanvas::Rectangle* range_bar_drag_rect;
ArdourCanvas::Rectangle* transport_bar_drag_rect;
ArdourCanvas::Rectangle* transport_bar_range_rect;
ArdourCanvas::Rectangle* transport_bar_preroll_rect;
ArdourCanvas::Rectangle* transport_bar_postroll_rect;
ArdourCanvas::Rectangle* transport_loop_range_rect;
@ -2593,6 +2619,43 @@ private:
friend class Drag;
friend class RegionCutDrag;
friend class RegionDrag;
struct TrackDrag {
RouteTimeAxisView* track;
GdkCursor* drag_cursor;
GdkCursor* predrag_cursor;
TimeAxisView* bump_track;
double start;
double current;
double previous;
bool have_predrag_cursor;
int direction;
bool first_move;
TrackDrag (RouteTimeAxisView* rtav)
: track (rtav)
, drag_cursor (nullptr)
, predrag_cursor (nullptr)
, bump_track (nullptr)
, start (-1.)
, current (0.)
, previous (0.)
, have_predrag_cursor (false)
, direction (0)
, first_move (true)
{}
};
TrackDrag* track_drag;
MarkerBarType _visible_marker_types;
RangeBarType _visible_range_types;
void update_mark_and_range_visibility ();
void show_marker_type (MarkerBarType);
void show_range_type (RangeBarType);
PBD::Signal0<void> VisibleMarkersChanged;
PBD::Signal0<void> VisibleRangesChanged;
friend class RegionMoveDrag;
friend class TrimDrag;
friend class MappingTwistDrag;

View File

@ -693,11 +693,23 @@ Editor::register_actions ()
ruler_meter_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-meter-ruler"), _("Time Signature"), sigc::mem_fun(*this, &Editor::toggle_ruler_visibility)));
ruler_tempo_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-tempo-ruler"), _("Tempo"), sigc::mem_fun(*this, &Editor::toggle_ruler_visibility)));
ruler_range_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-range-ruler"), _("Range Markers"), sigc::mem_fun(*this, &Editor::toggle_ruler_visibility)));
ruler_loop_punch_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-loop-punch-ruler"), _("Loop/Punch Ranges"), sigc::mem_fun(*this, &Editor::toggle_ruler_visibility)));
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_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)));
RadioAction::Group marker_choice_group;
RadioAction::Group range_choice_group;
all_marker_action = Glib::RefPtr<RadioAction>::cast_static (ActionManager::register_radio_action (ruler_actions, marker_choice_group, X_("show-all-markers"), _("All Markers"), sigc::bind (sigc::mem_fun(*this, &Editor::show_marker_type), all_marker_types)));
cd_marker_action = Glib::RefPtr<RadioAction>::cast_static (ActionManager::register_radio_action (ruler_actions, marker_choice_group, X_("show-cd-markers"), _("CD Markers"), sigc::bind (sigc::mem_fun(*this, &Editor::show_marker_type), CDMarks)));
scene_marker_action = Glib::RefPtr<RadioAction>::cast_static (ActionManager::register_radio_action (ruler_actions, marker_choice_group, X_("show-cue-markers"), _("Cue Markers"), sigc::bind (sigc::mem_fun(*this, &Editor::show_marker_type), SceneMarks)));
cue_marker_action = Glib::RefPtr<RadioAction>::cast_static (ActionManager::register_radio_action (ruler_actions, marker_choice_group, X_("show-scene-markers"), _("Scene Markers"), sigc::bind (sigc::mem_fun(*this, &Editor::show_marker_type), CueMarks)));
location_marker_action = Glib::RefPtr<RadioAction>::cast_static (ActionManager::register_radio_action (ruler_actions, marker_choice_group, X_("show-location-markers"), _("Location Markers"), sigc::bind (sigc::mem_fun(*this, &Editor::show_marker_type), LocationMarks)));
all_range_action = Glib::RefPtr<RadioAction>::cast_static (ActionManager::register_radio_action (ruler_actions, range_choice_group, X_("show-all-ranges"), _("All Ranges"), sigc::bind (sigc::mem_fun(*this, &Editor::show_range_type), all_range_types)));
session_range_action = Glib::RefPtr<RadioAction>::cast_static (ActionManager::register_radio_action (ruler_actions, range_choice_group, X_("show-session-range"), _("Session Range"), sigc::bind (sigc::mem_fun(*this, &Editor::show_range_type), SessionRange)));
punch_range_action = Glib::RefPtr<RadioAction>::cast_static (ActionManager::register_radio_action (ruler_actions, range_choice_group, X_("show-punch-range"), _("Punch Range"), sigc::bind (sigc::mem_fun(*this, &Editor::show_range_type), PunchRange)));
loop_range_action = Glib::RefPtr<RadioAction>::cast_static (ActionManager::register_radio_action (ruler_actions, range_choice_group, X_("show-loop-range"), _("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::show_range_type), LoopRange)));
other_range_action = Glib::RefPtr<RadioAction>::cast_static (ActionManager::register_radio_action (ruler_actions, range_choice_group, X_("show-other-ranges"), _("Other Ranges"), sigc::bind (sigc::mem_fun(*this, &Editor::show_range_type), OtherRange)));
ActionManager::register_action (editor_menu_actions, X_("VideoMonitorMenu"), _("Video Monitor"));
@ -723,10 +735,7 @@ Editor::register_actions ()
ruler_meter_action->set_active (true);
ruler_tempo_action->set_active (true);
ruler_range_action->set_active (true);
ruler_loop_punch_action->set_active (true);
ruler_cd_marker_action->set_active (true);
ruler_marker_action->set_active (true);
ruler_cue_marker_action->set_active (true);
ruler_video_action->set_active (false);
xjadeo_proc_action->set_active (false);
@ -892,7 +901,7 @@ Editor::register_midi_actions (Bindings* midi_bindings)
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-bar"), grid_type_strings[(int)GridTypeBar].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBar)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-auto"), _("Auto"), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), DRAW_LEN_AUTO)));
Glib::RefPtr<ActionGroup> velocity_actions = ActionManager::create_action_group (midi_bindings, _("Draw Velocity"));
Glib::RefPtr<ActionGroup> velocity_actions = ActionManager::create_action_group (midi_bindings, X_("DrawVelocity"));
RadioAction::Group draw_velocity_group;
ActionManager::register_radio_action (velocity_actions, draw_velocity_group, X_("draw-velocity-auto"), _("Auto"), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_velocity_chosen), DRAW_VEL_AUTO)));
for (int i = 1; i <= 127; i++) {
@ -903,7 +912,7 @@ Editor::register_midi_actions (Bindings* midi_bindings)
ActionManager::register_radio_action (velocity_actions, draw_velocity_group, buf, vel, (sigc::bind (sigc::mem_fun(*this, &Editor::draw_velocity_chosen), i)));
}
Glib::RefPtr<ActionGroup> channel_actions = ActionManager::create_action_group (midi_bindings, _("Draw Channel"));
Glib::RefPtr<ActionGroup> channel_actions = ActionManager::create_action_group (midi_bindings, X_("DrawChannel"));
RadioAction::Group draw_channel_group;
ActionManager::register_radio_action (channel_actions, draw_channel_group, X_("draw-channel-auto"), _("Auto"), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_channel_chosen), DRAW_CHAN_AUTO)));
for (int i = 0; i <= 15; i++) {
@ -1186,7 +1195,7 @@ Editor::draw_velocity_action (int v)
action = buf;
}
act = ActionManager::get_action (_("Draw Velocity"), action);
act = ActionManager::get_action (X_("DrawVelocity"), action);
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
return ract;
@ -1210,7 +1219,7 @@ Editor::draw_channel_action (int c)
action = buf;
}
act = ActionManager::get_action (_("Draw Channel"), action);
act = ActionManager::get_action (X_("DrawChannel"), action);
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
return ract;

View File

@ -83,6 +83,11 @@ 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.
@ -149,17 +154,13 @@ Editor::initialize_canvas ()
* ::update_ruler_visibility()
*/
cd_marker_group = new ArdourCanvas::Container (_time_markers_group, ArdourCanvas::Duple (0.0, 0.0));
CANVAS_DEBUG_NAME (cd_marker_group, "cd marker group");
/* the video ruler is temporarily placed a the same location as the
cd_marker_group, but is moved later.
previous marker group, but is moved later.
*/
videotl_group = new ArdourCanvas::Container (_time_markers_group, ArdourCanvas::Duple(0.0, 0.0));
CANVAS_DEBUG_NAME (videotl_group, "videotl group");
marker_group = new ArdourCanvas::Container (_time_markers_group, ArdourCanvas::Duple (0.0, timebar_height + 1.0));
CANVAS_DEBUG_NAME (marker_group, "marker group");
transport_marker_group = new ArdourCanvas::Container (_time_markers_group, ArdourCanvas::Duple (0.0, (timebar_height * 2.0) + 1.0));
CANVAS_DEBUG_NAME (transport_marker_group, "transport marker group");
range_marker_group = new ArdourCanvas::Container (_time_markers_group, ArdourCanvas::Duple (0.0, (timebar_height * 3.0) + 1.0));
CANVAS_DEBUG_NAME (range_marker_group, "range marker group");
tempo_group = new ArdourCanvas::Container (_time_markers_group, ArdourCanvas::Duple (0.0, (timebar_height * 4.0) + 1.0));
@ -186,22 +187,12 @@ Editor::initialize_canvas ()
range_marker_bar = new ArdourCanvas::Rectangle (range_marker_group, ArdourCanvas::Rect (0.0, timebar_top, ArdourCanvas::COORD_MAX, timebar_btm));
CANVAS_DEBUG_NAME (range_marker_bar, "Range Marker Bar");
transport_marker_bar = new ArdourCanvas::Rectangle (transport_marker_group, ArdourCanvas::Rect (0.0, timebar_top, ArdourCanvas::COORD_MAX, timebar_btm));
CANVAS_DEBUG_NAME (transport_marker_bar, "transport Marker Bar");
marker_bar = new ArdourCanvas::Rectangle (marker_group, ArdourCanvas::Rect (0.0, timebar_top, ArdourCanvas::COORD_MAX, timebar_btm));
CANVAS_DEBUG_NAME (marker_bar, "Marker Bar");
cd_marker_bar = new ArdourCanvas::Rectangle (cd_marker_group, ArdourCanvas::Rect (0.0, timebar_top, ArdourCanvas::COORD_MAX, timebar_btm));
CANVAS_DEBUG_NAME (cd_marker_bar, "CD Marker Bar");
section_marker_bar = new ArdourCanvas::Rectangle (section_marker_group, ArdourCanvas::Rect (0.0, timebar_top, ArdourCanvas::COORD_MAX, timebar_btm));
CANVAS_DEBUG_NAME (section_marker_bar, "Arranger Marker Bar");
cue_marker_group = new ArdourCanvas::Container (_time_markers_group, ArdourCanvas::Duple (0.0, 0.0));
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");
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));
@ -211,26 +202,11 @@ Editor::initialize_canvas ()
ARDOUR_UI::instance()->video_timeline = new VideoTimeLine(this, videotl_group, (timebar_height * videotl_bar_height));
cd_marker_bar_drag_rect = new ArdourCanvas::Rectangle (cd_marker_group, ArdourCanvas::Rect (0.0, 0.0, 100, timebar_height));
CANVAS_DEBUG_NAME (cd_marker_bar_drag_rect, "cd marker drag");
cd_marker_bar_drag_rect->set_outline (false);
cd_marker_bar_drag_rect->hide ();
cue_marker_bar_drag_rect = new ArdourCanvas::Rectangle (cue_marker_group, ArdourCanvas::Rect (0.0, 0.0, 100, timebar_height));
CANVAS_DEBUG_NAME (cd_marker_bar_drag_rect, "cd marker drag");
cue_marker_bar_drag_rect->set_outline (false);
cue_marker_bar_drag_rect->hide ();
range_bar_drag_rect = new ArdourCanvas::Rectangle (range_marker_group, ArdourCanvas::Rect (0.0, 0.0, 100, timebar_height));
CANVAS_DEBUG_NAME (range_bar_drag_rect, "range drag");
range_bar_drag_rect->set_outline (false);
range_bar_drag_rect->hide ();
transport_bar_drag_rect = new ArdourCanvas::Rectangle (transport_marker_group, ArdourCanvas::Rect (0.0, 0.0, 100, timebar_height));
CANVAS_DEBUG_NAME (transport_bar_drag_rect, "transport drag");
transport_bar_drag_rect->set_outline (false);
transport_bar_drag_rect->hide ();
transport_punchin_line = new ArdourCanvas::Line (hv_scroll_group);
transport_punchin_line->set_x0 (0);
transport_punchin_line->set_y0 (0);
@ -248,12 +224,9 @@ Editor::initialize_canvas ()
tempo_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_bar_event), tempo_bar, TempoBarItem, "tempo bar"));
meter_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_bar_event), meter_bar, MeterBarItem, "meter bar"));
marker_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_bar_event), marker_bar, MarkerBarItem, "marker bar"));
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"));
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"));
_playhead_cursor = new EditorCursor (*this, &Editor::canvas_playhead_cursor_event, X_("playhead"));
_playhead_cursor->set_sensitive (UIConfiguration::instance().get_sensitize_playhead());
@ -1080,30 +1053,15 @@ Editor::color_handler()
marker_bar->set_fill_color (UIConfiguration::instance().color_mod ("marker bar", "marker bar"));
marker_bar->set_outline_color (UIConfiguration::instance().color ("marker bar separator"));
cd_marker_bar->set_fill_color (UIConfiguration::instance().color_mod ("cd marker bar", "marker bar"));
cd_marker_bar->set_outline_color (UIConfiguration::instance().color ("marker bar separator"));
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"));
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"));
range_marker_bar->set_fill_color (UIConfiguration::instance().color_mod ("range marker bar", "marker bar"));
range_marker_bar->set_outline_color (UIConfiguration::instance().color ("marker bar separator"));
transport_marker_bar->set_fill_color (UIConfiguration::instance().color_mod ("transport marker bar", "marker bar"));
transport_marker_bar->set_outline_color (UIConfiguration::instance().color ("marker bar separator"));
cd_marker_bar_drag_rect->set_fill_color (UIConfiguration::instance().color ("range drag bar rect"));
cd_marker_bar_drag_rect->set_outline_color (UIConfiguration::instance().color ("range drag bar rect"));
range_bar_drag_rect->set_fill_color (UIConfiguration::instance().color ("range drag bar rect"));
range_bar_drag_rect->set_outline_color (UIConfiguration::instance().color ("range drag bar rect"));
transport_bar_drag_rect->set_fill_color (UIConfiguration::instance().color ("transport drag rect"));
transport_bar_drag_rect->set_outline_color (UIConfiguration::instance().color ("transport drag rect"));
transport_loop_range_rect->set_fill_color (UIConfiguration::instance().color_mod ("transport loop rect", "loop rectangle"));
transport_loop_range_rect->set_outline_color (UIConfiguration::instance().color ("transport loop rect"));
@ -1490,11 +1448,8 @@ Editor::which_canvas_cursor(ItemType type) const
case MarkerItem:
case MarkerBarItem:
case RangeMarkerBarItem:
case CdMarkerBarItem:
case SectionMarkerBarItem:
case CueMarkerBarItem:
case VideoBarItem:
case TransportMarkerBarItem:
case DropZoneItem:
case GridZoneItem:
case SelectionMarkerItem:

View File

@ -707,11 +707,11 @@ bool
Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
{
ItemType type;
AudioRegionGainLine* gl;
if ((gl = dynamic_cast<AudioRegionGainLine*> (al)) != 0) {
RegionFxLine* rfl;
if ((rfl = dynamic_cast<RegionFxLine*> (al)) != 0) {
type = GainLineItem;
if (event->type == GDK_BUTTON_PRESS) {
clicked_regionview = &gl->region_view ();
clicked_regionview = &rfl->region_view ();
}
} else {
type = AutomationLineItem;

View File

@ -5039,7 +5039,7 @@ LineDrag::finished (GdkEvent* event, bool movement_occurred)
AudioRegionView* arv;
if ((arv = dynamic_cast<AudioRegionView*> (_editor->clicked_regionview)) != 0) {
arv->add_gain_point_event (&arv->get_gain_line ()->grab_item (), event, false);
arv->add_gain_point_event (&arv->fx_line ()->grab_item (), event, false);
}
}
}
@ -5957,16 +5957,10 @@ RangeMarkerBarDrag::motion (GdkEvent* event, bool first_move)
switch (_operation) {
case CreateSkipMarker:
crect = _editor->range_bar_drag_rect;
break;
case CreateRangeMarker:
crect = _editor->range_bar_drag_rect;
break;
case CreateTransportMarker:
crect = _editor->transport_bar_drag_rect;
break;
case CreateCDMarker:
crect = _editor->cd_marker_bar_drag_rect;
crect = _editor->range_bar_drag_rect;
break;
default:
error << string_compose (_("programming_error: %1"), "Error: unknown range marker op passed to Editor::drag_range_markerbar_op ()") << endmsg;
@ -6042,9 +6036,9 @@ RangeMarkerBarDrag::finished (GdkEvent* event, bool movement_occurred)
_editor->session ()->locations ()->next_available_name (rangename, _("CD"));
_editor->begin_reversible_command (_("new CD marker"));
flags = Location::Flags (Location::IsRangeMarker | Location::IsCDMarker);
_editor->cd_marker_bar_drag_rect->hide ();
_editor->range_bar_drag_rect->hide ();
} else {
_editor->begin_reversible_command (_("new skip marker"));
_editor->begin_reversible_command (_("new range marker"));
_editor->session ()->locations ()->next_available_name (rangename, _("unnamed"));
flags = Location::IsRangeMarker;
_editor->range_bar_drag_rect->hide ();
@ -6367,7 +6361,7 @@ AutomationRangeDrag::AutomationRangeDrag (Editor* editor, list<RegionView*> cons
for (list<RegionView*>::const_iterator i = v.begin (); i != v.end (); ++i) {
if (AudioRegionView* audio_view = dynamic_cast<AudioRegionView*> (*i)) {
lines.push_back (audio_view->get_gain_line ());
lines.push_back (audio_view->fx_line ());
} else if (AutomationRegionView* automation_view = dynamic_cast<AutomationRegionView*> (*i)) {
lines.push_back (automation_view->line ());
_integral = true;
@ -6394,8 +6388,8 @@ AutomationRangeDrag::setup (list<std::shared_ptr<AutomationLine>> const& lines)
/* need a special detection for automation lanes (not region gain line) */
// TODO: if we implement automation regions, this check can probably be removed
AudioRegionGainLine* argl = dynamic_cast<AudioRegionGainLine*> ((*i).get ());
if (!argl) {
RegionFxLine* fxl = dynamic_cast<RegionFxLine*> ((*i).get ());
if (!fxl) {
/* in automation lanes, the EFFECTIVE range should be considered 0->max_position (even if there is no line) */
r.first = Temporal::timepos_t ((*i)->the_list ()->time_domain ());
r.second = Temporal::timepos_t::max ((*i)->the_list ()->time_domain ());
@ -7267,7 +7261,7 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::motion (GdkEvent* ev, bool firs
dragging_line = new ArdourCanvas::PolyLine (parent ? parent : item());
dragging_line->set_ignore_events (true);
dragging_line->set_outline_width (2.0);
dragging_line->set_outline_color (UIConfiguration::instance().color ("automation line"));
dragging_line->set_outline_color (UIConfiguration::instance().color ("automation line")); // XXX -> get color from AutomationLine
dragging_line->raise_to_top ();
/* for freehand drawing, we only support left->right direction, for now. */

View File

@ -184,10 +184,11 @@ Editor::measure_master_loudness (samplepos_t start, samplepos_t end, bool is_ran
ARDOUR::TimelineRange ar (timepos_t (start), timepos_t (end), 0);
LoudnessDialog ld (_session, ar, is_range_selection);
#ifndef __APPLE__
if (own_window ()) {
ld.set_transient_for (*own_window ());
}
#endif
ld.run ();
}

View File

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

View File

@ -131,6 +131,8 @@ Editor::add_new_location_internal (Location* location)
{
LocationMarkers *lam = new LocationMarkers;
std::string color;
MarkerBarType mark_type = MarkerBarType (0);
RangeBarType range_type = RangeBarType (0);
/* make a note here of which group this marker ends up in */
ArdourCanvas::Container* group = 0;
@ -145,6 +147,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");
}
@ -152,18 +156,25 @@ Editor::add_new_location_internal (Location* location)
if (location->is_mark()) {
if (location->is_cd_marker()) {
lam->start = new ArdourMarker (*this, *cd_marker_group, color, location->name(), marker_type (location), location->start());
group = cd_marker_group;
} else if (location->is_cue_marker()) {
lam->start = new ArdourMarker (*this, *cue_marker_group, color, location->name(), marker_type (location), location->start());
lam->start->set_cue_index(location->cue_id());
group = cue_marker_group;
} 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 {
lam->start = new ArdourMarker (*this, *marker_group, color, location->name(), marker_type (location), location->start());
group = marker_group;
mark_type = CDMarks;
lam->start = new ArdourMarker (*this, *group, color, location->name(), marker_type (location), location->start());
} else if (location->is_cue_marker()) {
group = marker_group;
mark_type = CueMarks;
lam->start = new ArdourMarker (*this, *group, color, location->name(), marker_type (location), location->start());
lam->start->set_cue_index(location->cue_id());
} else if (location->is_section()) {
group = section_marker_group;
lam->start = new ArdourMarker (*this, *group, color, location->name(), marker_type (location), location->start());
} else if (location->is_scene()) {
mark_type = CueMarks;
group = marker_group;
lam->start = new ArdourMarker (*this, *group, color, location->name(), marker_type (location), location->start());
} else {
group = marker_group;
mark_type = LocationMarks;
lam->start = new ArdourMarker (*this, *group, color, location->name(), marker_type (location), location->start());
}
lam->end = 0;
@ -171,43 +182,39 @@ Editor::add_new_location_internal (Location* location)
} else if (location->is_auto_loop()) {
// transport marker
lam->start = new ArdourMarker (*this, *transport_marker_group, color,
group = range_marker_group;
range_type = LoopRange;
lam->start = new ArdourMarker (*this, *group, color,
location->name(), marker_type (location), location->start());
lam->end = new ArdourMarker (*this, *transport_marker_group, color,
lam->end = new ArdourMarker (*this, *group, color,
location->name(), marker_type (location, false), location->end());
group = transport_marker_group;
} else if (location->is_auto_punch()) {
// transport marker
lam->start = new ArdourMarker (*this, *transport_marker_group, color,
group = range_marker_group;
range_type = PunchRange;
lam->start = new ArdourMarker (*this, *group, color,
location->name(), marker_type (location), location->start());
lam->end = new ArdourMarker (*this, *transport_marker_group, color,
lam->end = new ArdourMarker (*this, *group, color,
location->name(), marker_type (location, false), location->end());
group = transport_marker_group;
} else if (location->is_session_range()) {
// session range
lam->start = new ArdourMarker (*this, *marker_group, color, _("start"), marker_type (location), location->start());
lam->end = new ArdourMarker (*this, *marker_group, color, _("end"), marker_type (location, false), location->end());
group = marker_group;
group = range_marker_group;
range_type = SessionRange;
lam->start = new ArdourMarker (*this, *group, color, _("start"), marker_type (location), location->start());
lam->end = new ArdourMarker (*this, *group, color, _("end"), marker_type (location, false), location->end());
} else {
// range marker
if (location->is_cd_marker()) {
lam->start = new ArdourMarker (*this, *cd_marker_group, color,
location->name(), marker_type (location), location->start());
lam->end = new ArdourMarker (*this, *cd_marker_group, color,
location->name(), marker_type (location, false), location->end());
group = cd_marker_group;
} else {
lam->start = new ArdourMarker (*this, *range_marker_group, color,
location->name(), marker_type (location), location->start());
lam->end = new ArdourMarker (*this, *range_marker_group, color,
location->name(), marker_type (location, false), location->end());
group = range_marker_group;
}
group = range_marker_group;
range_type = OtherRange;
lam->start = new ArdourMarker (*this, *group, color,
location->name(), marker_type (location), location->start());
lam->end = new ArdourMarker (*this, *group, color,
location->name(), marker_type (location, false), location->end());
}
#if 0
@ -219,7 +226,21 @@ Editor::add_new_location_internal (Location* location)
if (location->is_hidden ()) {
lam->hide();
} else {
lam->show ();
if (mark_type) {
if (!(_visible_marker_types & mark_type)) {
lam->hide ();
} else {
lam->show ();
}
} else if (range_type) {
if (!(_visible_range_types & range_type)) {
lam->hide ();
} else {
lam->show ();
}
} else {
lam->show ();
}
}
location->NameChanged.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, location), gui_context());
@ -301,7 +322,10 @@ Editor::check_marker_label (ArdourMarker* m)
list<ArdourMarker*>::iterator prev = sorted.end ();
list<ArdourMarker*>::iterator next = i;
++next;
if (next != sorted.end()) {
++next;
}
/* Look to see if the previous marker is still behind `m' in time */
if (i != sorted.begin()) {
@ -309,7 +333,7 @@ Editor::check_marker_label (ArdourMarker* m)
prev = i;
--prev;
if ((*prev)->position() > m->position()) {
if ((*prev)->position() >= m->position()) {
/* This marker is no longer in the correct order with the previous one, so
* update all the markers in this group.
*/
@ -346,8 +370,11 @@ Editor::check_marker_label (ArdourMarker* m)
}
}
if (next != sorted.end()) {
while (next != sorted.end() && (*next)->position () == m->position ()) {
++next;
}
if (next != sorted.end()) {
/* Update just the available space between this marker and the next */
double const p = sample_to_pixel (m->position().distance ((*next)->position()).samples());
@ -368,6 +395,9 @@ Editor::check_marker_label (ArdourMarker* m)
struct MarkerComparator {
bool operator() (ArdourMarker const * a, ArdourMarker const * b) {
if (a->position() == b->position()) {
return a->label_on_left ();
}
return a->position() < b->position();
}
};
@ -415,14 +445,29 @@ Editor::update_marker_labels (ArdourCanvas::Item* group)
while (i != sorted.end()) {
if (prev != sorted.end()) {
double const p = sample_to_pixel ((*prev)->position().distance ((*i)->position()).samples());
list<ArdourMarker*>::iterator pi = prev;
while (pi != sorted.begin () && (*pi)->position () == (*i)->position()) {
--pi;
}
double p = sample_to_pixel ((*pi)->position().distance ((*i)->position()).samples());
if (p == 0) {
p = DBL_MAX;
}
if ((*prev)->label_on_left()) {
(*i)->set_left_label_limit (p);
} else {
(*i)->set_left_label_limit (p / 2);
}
} else {
(*i)->set_left_label_limit (DBL_MAX);
}
while (next != sorted.end() && (*next)->position () == (*i)->position ()) {
++next;
}
if (next != sorted.end()) {
@ -435,6 +480,8 @@ Editor::update_marker_labels (ArdourCanvas::Item* group)
}
++next;
} else {
(*i)->set_right_label_limit (DBL_MAX);
}
prev = i;
@ -513,11 +560,13 @@ Editor::reparent_location_markers (LocationMarkers* lam, ArdourCanvas::Item* new
void Editor::ensure_marker_updated (LocationMarkers* lam, Location* location)
{
if (location->is_cd_marker()) {
reparent_location_markers (lam, cd_marker_group);
reparent_location_markers (lam, marker_group);
} else if (location->is_scene()) {
reparent_location_markers (lam, marker_group);
} else if (location->is_section()) {
reparent_location_markers (lam, section_marker_group);
} else if (location->is_cue_marker()) {
reparent_location_markers (lam, cue_marker_group);
reparent_location_markers (lam, marker_group);
} else if (location->is_mark() || location->matches (Location::Flags(0))) {
reparent_location_markers (lam, marker_group);
}
@ -1887,8 +1936,6 @@ void
Editor::new_transport_marker_menu_popdown ()
{
// hide rects
transport_bar_drag_rect->hide();
_drags->abort ();
}
@ -2084,3 +2131,152 @@ Editor::toggle_cue_behavior ()
_session->config.set_cue_behavior (ARDOUR::CueBehavior (cb | ARDOUR::FollowCues));
}
}
void
Editor::set_visible_marker_types (MarkerBarType mbt)
{
_visible_marker_types = mbt;
update_mark_and_range_visibility ();
VisibleMarkersChanged ();
}
void
Editor::set_visible_range_types (RangeBarType rbt)
{
_visible_range_types = rbt;
update_mark_and_range_visibility ();
VisibleRangesChanged ();
}
Editor::MarkerBarType
Editor::visible_marker_types () const
{
return _visible_marker_types;
}
Editor::RangeBarType
Editor::visible_range_types () const
{
return _visible_range_types;
}
void
Editor::update_mark_and_range_visibility ()
{
for (auto & l : location_markers) {
Location* location = l.first;
LocationMarkers* lam = l.second;
MarkerBarType mark_type = MarkerBarType (0);
RangeBarType range_type = RangeBarType (0);
if (location->is_mark()) {
if (location->is_cd_marker()) {
mark_type = CDMarks;
} else if (location->is_cue_marker()) {
mark_type = CueMarks;
} else if (location->is_section()) {
} else if (location->is_scene()) {
mark_type = CueMarks;
} else {
mark_type = LocationMarks;
}
} else if (location->is_auto_loop()) {
range_type = LoopRange;
} else if (location->is_auto_punch()) {
range_type = PunchRange;
} else if (location->is_session_range()) {
range_type = SessionRange;
} else {
range_type = OtherRange;
}
if (location->is_hidden ()) {
lam->hide();
} else {
if (mark_type) {
if (!(_visible_marker_types & mark_type)) {
lam->hide ();
} else {
lam->show ();
}
} else if (range_type) {
if (!(_visible_range_types & range_type)) {
lam->hide ();
} else {
lam->show ();
}
} else {
lam->show ();
}
}
}
}
void
Editor::show_marker_type (MarkerBarType mbt)
{
Glib::RefPtr<Gtk::RadioAction> action;
switch (mbt) {
case CDMarks:
action = cd_marker_action;
break;
case CueMarks:
action = cue_marker_action;
break;
case SceneMarks:
action = scene_marker_action;
break;
case LocationMarks:
action = location_marker_action;
break;
default:
action = all_marker_action;
break;
}
if (action->get_active()) {
/* Only change things for the currently active action, since
this will be called for both the deactivated action, and the
newly activated one.
*/
set_visible_marker_types (mbt);
}
}
void
Editor::show_range_type (RangeBarType rbt)
{
Glib::RefPtr<Gtk::RadioAction> action;
switch (rbt) {
case OtherRange:
action = other_range_action;
break;
case PunchRange:
action = punch_range_action;
break;
case LoopRange:
action = loop_range_action;
break;
case SessionRange:
action = session_range_action;
break;
default:
action = all_range_action;
break;
}
if (action->get_active()) {
/* Only change things for the currently active action, since
this will be called for both the deactivated action, and the
newly activated one.
*/
set_visible_range_types (rbt);
}
}

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)) {
@ -856,33 +859,6 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
return true;
break;
case CdMarkerBarItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_drags->set (new CursorDrag (this, *_playhead_cursor, false), event);
} else {
_drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateCDMarker), event);
}
return true;
break;
case CueMarkerBarItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_drags->set (new CursorDrag (this, *_playhead_cursor, false), event);
} else {
/* no range dragging on this ruler/bar */
}
return true;
break;
case TransportMarkerBarItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_drags->set (new CursorDrag (this, *_playhead_cursor, false), event);
} else {
_drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateTransportMarker), event);
}
return true;
break;
case VelocityItem:
_drags->set (new LollipopDrag (this, item), event);
return true;
@ -1706,8 +1682,6 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case MarkerBarItem:
case RangeMarkerBarItem:
case TransportMarkerBarItem:
case CdMarkerBarItem:
case SectionMarkerBarItem:
case TempoBarItem:
case TempoCurveItem:
@ -1722,12 +1696,11 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
popup_ruler_menu (where, item_type);
break;
case CueMarkerBarItem:
snap_to (where, Temporal::RoundNearest, SnapToGrid_Scaled, true);
popup_ruler_menu (where, item_type);
case MarkerItem:
marker_context_menu (&event->button, item);
break;
case MarkerItem:
case SceneMarkerItem:
marker_context_menu (&event->button, item);
break;
@ -1824,14 +1797,6 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
}
return true;
case CdMarkerBarItem:
if (!_dragging_playhead) {
/* if we get here then a dragged range wasn't done */
snap_to_with_modifier (where, event, Temporal::RoundNearest, SnapToGrid_Scaled);
mouse_add_new_marker (where, Location::IsCDMarker);
}
return true;
case SectionMarkerBarItem:
if (!_dragging_playhead && Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
snap_to_with_modifier (where, event, Temporal::RoundNearest, SnapToGrid_Scaled);
@ -1839,14 +1804,6 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
}
return true;
case CueMarkerBarItem:
if (!_dragging_playhead) {
/* if we get here then a dragged range wasn't done */
snap_to_with_modifier (where, event, Temporal::RoundNearest, SnapToGrid_Scaled); //TODO: force to-measure?
mouse_add_new_marker (where, Location::IsCueMarker);
}
return true;
case GridZoneItem:
return true;
@ -2340,7 +2297,7 @@ Editor::can_remove_control_point (ArdourCanvas::Item* item)
}
AutomationLine& line = control_point->line ();
if (dynamic_cast<AudioRegionGainLine*> (&line)) {
if (dynamic_cast<RegionFxLine*> (&line)) {
/* we shouldn't remove the first or last gain point in region gain lines */
if (line.is_last_point(*control_point) || line.is_first_point(*control_point)) {
return false;

View File

@ -477,6 +477,41 @@ Editor::nudge_forward (bool next, bool force_playhead)
}
}
if (in_command) {
commit_reversible_command ();
}
} else if (!force_playhead && !selection->points.empty()) {
bool in_command = false;
for (auto const& pt : selection->points) {
std::shared_ptr<ARDOUR::AutomationList> alist = pt->line ().the_list ();
AutomationList::iterator m = pt->model ();
AutomationList::iterator n = m;
const timepos_t p = (*m)->when;
distance = get_nudge_distance (p, next_distance);
if (next) {
distance = next_distance;
}
if (++n != alist->end ()) {
if ((*n)->when <= p + distance) {
continue;
}
}
if (!in_command) {
begin_reversible_command (_("nudge automation forward"));
in_command = true;
}
_session->add_command (new MementoCommand<AutomationList> (new SimpleMementoCommandBinder<AutomationList> (*alist.get()), &alist->get_state(), 0));
alist->freeze ();
alist->modify (m, p + distance, (*m)->value);
alist->thaw ();
_session->add_command (new MementoCommand<AutomationList> (new SimpleMementoCommandBinder<AutomationList> (*alist.get()), 0, &alist->get_state()));
if (selection->points.size()==1) {
_session->request_locate (timepos_t (p + distance).samples());
}
}
if (in_command) {
commit_reversible_command ();
}
@ -574,6 +609,42 @@ Editor::nudge_backward (bool next, bool force_playhead)
commit_reversible_command ();
}
} else if (!force_playhead && !selection->points.empty()) {
bool in_command = false;
for (auto const& pt : selection->points) {
std::shared_ptr<ARDOUR::AutomationList> alist = pt->line ().the_list ();
AutomationList::iterator m = pt->model ();
AutomationList::iterator n = m;
const timepos_t p = (*m)->when;
distance = get_nudge_distance (p, next_distance);
if (next) {
distance = next_distance;
}
if (n != alist->begin ()) {
--n;
if ((*n)->when >= p.earlier (distance)) {
continue;
}
}
if (!in_command) {
begin_reversible_command (_("nudge automation backward"));
in_command = true;
}
_session->add_command (new MementoCommand<AutomationList> (new SimpleMementoCommandBinder<AutomationList> (*alist.get()), &alist->get_state(), 0));
alist->freeze ();
alist->modify (m, max (timepos_t (p.time_domain()), p.earlier (distance)), (*m)->value);
alist->thaw ();
_session->add_command (new MementoCommand<AutomationList> (new SimpleMementoCommandBinder<AutomationList> (*alist.get()), 0, &alist->get_state()));
if (selection->points.size()==1) {
_session->request_locate (timepos_t (p.earlier (distance)).samples());
}
}
if (in_command) {
commit_reversible_command ();
}
} else {
distance = get_nudge_distance (timepos_t (playhead_cursor()->current_sample ()), next_distance);
if (_playhead_cursor->current_sample () > distance.samples()) {
@ -2612,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 ()
{
@ -4762,7 +4849,7 @@ Editor::cut_copy_points (Editing::CutCopyOp op, timepos_t const & earliest_time)
bool erase = true;
if (dynamic_cast<AudioRegionGainLine*> (&line)) {
if (dynamic_cast<RegionFxLine*> (&line)) {
/* removing of first and last gain point in region gain lines is prohibited*/
if (line.is_last_point (*(*sel_point)) || line.is_first_point (*(*sel_point))) {
erase = false;

View File

@ -176,10 +176,7 @@ Editor::initialize_rulers ()
lab_children.push_back (Element(tempo_label, PACK_SHRINK, PACK_START));
lab_children.push_back (Element(meter_label, PACK_SHRINK, PACK_START));
lab_children.push_back (Element(range_mark_label, PACK_SHRINK, PACK_START));
lab_children.push_back (Element(transport_mark_label, PACK_SHRINK, PACK_START));
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(section_mark_label, PACK_SHRINK, PACK_START));
lab_children.push_back (Element(videotl_label, PACK_SHRINK, PACK_START));
@ -223,40 +220,6 @@ Editor::popup_ruler_menu (timepos_t const & where, ItemType t)
ruler_items.clear();
switch (t) {
case MarkerBarItem:
ruler_items.push_back (MenuElem (_("New Location Marker"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_add_new_marker), where, Location::Flags (0), 0)));
ruler_items.push_back (MenuElem (_("Clear All Locations"), sigc::mem_fun(*this, &Editor::clear_markers)));
ruler_items.push_back (MenuElem (_("Clear All Xruns"), sigc::mem_fun(*this, &Editor::clear_xrun_markers)));
ruler_items.push_back (MenuElem (_("Unhide Locations"), sigc::mem_fun(*this, &Editor::unhide_markers)));
break;
case RangeMarkerBarItem:
ruler_items.push_back (MenuElem (_("New Range"), sigc::bind (sigc::mem_fun (*this, &Editor::mouse_add_new_range), where)));
ruler_items.push_back (MenuElem (_("Clear All Ranges"), sigc::mem_fun(*this, &Editor::clear_ranges)));
ruler_items.push_back (MenuElem (_("Unhide Ranges"), sigc::mem_fun(*this, &Editor::unhide_ranges)));
break;
case TransportMarkerBarItem:
ruler_items.push_back (MenuElem (_("New Loop Range"), sigc::bind (sigc::mem_fun (*this, &Editor::mouse_add_new_loop), where)));
ruler_items.push_back (MenuElem (_("New Punch Range"), sigc::bind (sigc::mem_fun (*this, &Editor::mouse_add_new_punch), where)));
break;
case CdMarkerBarItem:
ruler_items.push_back (MenuElem (_("New CD Track Marker"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_add_new_marker), where, Location::Flags(Location::IsMark |Location::IsCDMarker), 0)));
break;
case SectionMarkerBarItem:
ruler_items.push_back (MenuElem (_("New Arrangement Marker"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_add_new_marker), where, Location::Flags(Location::IsMark | Location::IsSection), 0)));
break;
case CueMarkerBarItem:
ruler_items.push_back (MenuElem (_("Stop All Cues"), sigc::bind (sigc::mem_fun (*this, &Editor::mouse_add_new_marker), where, Location::IsCueMarker, CueRecord::stop_all)));
ruler_items.push_back (MenuElem (_("Clear All Cues"), sigc::mem_fun (*this, &Editor::clear_cues)));
for (int32_t n = 0; n < TriggerBox::default_triggers_per_box; ++n) {
ruler_items.push_back (MenuElem (string_compose (_("Cue %1"), cue_marker_name (n)), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_add_new_marker), where, Location::IsCueMarker, n)));
}
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)));
@ -318,10 +281,76 @@ Editor::popup_ruler_menu (timepos_t const & where, ItemType t)
ruler_items.push_back (MenuElem (_("Add BBT Marker"), sigc::bind (sigc::mem_fun (*this, &Editor::mouse_add_bbt_marker_event), where)));
break;
default:
default: {
ruler_items.push_back (MenuElem ("Add..."));
Gtk::MenuItem& add_menu = ruler_items.back();
Gtk::Menu* a_menu = new Gtk::Menu;
MenuList& add_items = a_menu->items();
add_items.push_back (MenuElem (_("Location Marker"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_add_new_marker), where, Location::Flags (0), 0)));
add_items.push_back (MenuElem (_("Range"), sigc::bind (sigc::mem_fun (*this, &Editor::mouse_add_new_range), where)));
add_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun (*this, &Editor::mouse_add_new_loop), where)));
add_items.push_back (MenuElem (_("Punch Range"), sigc::bind (sigc::mem_fun (*this, &Editor::mouse_add_new_punch), where)));
add_items.push_back (MenuElem (_("CD Track Marker"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_add_new_marker), where, Location::Flags(Location::IsMark |Location::IsCDMarker), 0)));
add_items.push_back (MenuElem (_("Arrangement Marker"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_add_new_marker), where, Location::Flags(Location::IsMark | Location::IsSection), 0)));
for (int32_t n = 0; n < TriggerBox::default_triggers_per_box; ++n) {
add_items.push_back (MenuElem (string_compose (_("Cue %1"), cue_marker_name (n)), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_add_new_marker), where, Location::IsCueMarker, n)));
}
add_menu.set_submenu (*a_menu);
ruler_items.push_back (MenuElem ("Remove..."));
Gtk::MenuItem& clear_menu = ruler_items.back();
Gtk::Menu* c_menu = new Gtk::Menu;
MenuList& clear_items = c_menu->items();
clear_items.push_back (MenuElem (_("All Locations"), sigc::mem_fun(*this, &Editor::clear_markers)));
clear_items.push_back (MenuElem (_("All Ranges"), sigc::mem_fun(*this, &Editor::clear_ranges)));
clear_items.push_back (MenuElem (_("All Cues"), sigc::mem_fun (*this, &Editor::clear_cues)));
clear_items.push_back (MenuElem (_("All Xruns"), sigc::mem_fun(*this, &Editor::clear_xrun_markers)));
clear_items.push_back (MenuElem (_("All (MIDI) Scenes"), sigc::mem_fun (*this, &Editor::clear_scenes)));
clear_menu.set_submenu (*c_menu);
ruler_items.push_back (MenuElem (_("Stop All Cues"), sigc::bind (sigc::mem_fun (*this, &Editor::mouse_add_new_marker), where, Location::IsCueMarker, CueRecord::stop_all)));
}
break;
}
/* Gtkmm does not expose the ::set_related_action() API for
* Gtk::Activatable, so we have to drop to C to create menu items
* directly from actions.
*/
#define MAKE_ACTION_ITEM(menu,item,action_group,action_name) \
(item) = new (Gtk::CheckMenuItem); \
gtk_activatable_set_related_action (GTK_ACTIVATABLE((item)->gobj()), ActionManager::get_action (action_group, action_name)->gobj()); \
(item)->set_draw_as_radio (); \
(menu)->append (*(item));
Gtk::Menu* ms_menu = new (Gtk::Menu);
Gtk::CheckMenuItem* ms_item;
MAKE_ACTION_ITEM (ms_menu, ms_item, X_("Rulers"), X_("show-all-markers"));
MAKE_ACTION_ITEM (ms_menu, ms_item, X_("Rulers"), X_("show-cue-markers"));
MAKE_ACTION_ITEM (ms_menu, ms_item, X_("Rulers"), X_("show-cd-markers"));
MAKE_ACTION_ITEM (ms_menu, ms_item, X_("Rulers"), X_("show-scene-markers"));
MAKE_ACTION_ITEM (ms_menu, ms_item, X_("Rulers"), X_("show-location-markers"));
ruler_items.push_back (MenuElem (_("Show Locations...")));
Gtk::MenuItem& marker_show_menu = ruler_items.back();
marker_show_menu.set_submenu (*ms_menu);
Gtk::Menu* rs_menu = new (Gtk::Menu);
Gtk::CheckMenuItem* rs_item;
MAKE_ACTION_ITEM (rs_menu, rs_item, X_("Rulers"), X_("show-all-ranges"));
MAKE_ACTION_ITEM (rs_menu, rs_item, X_("Rulers"), X_("show-punch-range"));
MAKE_ACTION_ITEM (rs_menu, rs_item, X_("Rulers"), X_("show-loop-range"));
MAKE_ACTION_ITEM (rs_menu, rs_item, X_("Rulers"), X_("show-session-range"));
MAKE_ACTION_ITEM (rs_menu, rs_item, X_("Rulers"), X_("show-location-markers"));
ruler_items.push_back (MenuElem (_("Show Ranges...")));
Gtk::MenuItem& range_show_menu = ruler_items.back();
range_show_menu.set_submenu (*rs_menu);
#undef MAKE_ACTION_ITEM
if (!ruler_items.empty()) {
editor_ruler_menu->popup (1, gtk_get_current_event_time());
}
@ -341,11 +370,8 @@ Editor::store_ruler_visibility ()
node->set_property (X_("meter"), ruler_meter_action->get_active());
node->set_property (X_("tempo"), ruler_tempo_action->get_active());
node->set_property (X_("rangemarker"), ruler_range_action->get_active());
node->set_property (X_("transportmarker"), ruler_loop_punch_action->get_active());
node->set_property (X_("cdmarker"), ruler_cd_marker_action->get_active());
node->set_property (X_("arrangement"), ruler_section_action->get_active());
node->set_property (X_("marker"), ruler_marker_action->get_active());
node->set_property (X_("cuemarker"), ruler_cue_marker_action->get_active());
node->set_property (X_("arrangement"), ruler_section_action->get_active());
node->set_property (X_("videotl"), ruler_video_action->get_active());
_session->add_extra_xml (*node);
@ -384,48 +410,12 @@ Editor::restore_ruler_visibility ()
if (node->get_property ("rangemarker", yn)) {
ruler_range_action->set_active (yn);
}
if (node->get_property ("transportmarker", yn)) {
ruler_loop_punch_action->set_active (yn);
}
if (node->get_property ("cdmarker", yn)) {
ruler_cd_marker_action->set_active (yn);
} else {
// this _session doesn't yet know about the cdmarker ruler
// as a benefit to the user who doesn't know the feature exists, show the ruler if
// any cd marks exist
ruler_cd_marker_action->set_active (false);
const Locations::LocationList & locs = _session->locations()->list();
for (Locations::LocationList::const_iterator i = locs.begin(); i != locs.end(); ++i) {
if ((*i)->is_cd_marker()) {
ruler_cd_marker_action->set_active (true);
break;
}
}
}
if (node->get_property ("arrangement", yn)) {
ruler_section_action->set_active (yn);
} else {
ruler_section_action->set_active (true);
}
if (node->get_property ("cuemarker", yn)) {
ruler_cue_marker_action->set_active (yn);
} else {
// this _session doesn't yet know about the cue marker ruler
// as a benefit to the user who doesn't know the feature exists, show the ruler if
// any cue marks exist
ruler_cue_marker_action->set_active (false);
const Locations::LocationList & locs = _session->locations()->list();
for (Locations::LocationList::const_iterator i = locs.begin(); i != locs.end(); ++i) {
if ((*i)->is_cue_marker()) {
ruler_cue_marker_action->set_active (true);
break;
}
}
}
if (node->get_property ("videotl", yn)) {
ruler_video_action->set_active (yn);
}
@ -440,10 +430,7 @@ Editor::restore_ruler_visibility ()
ruler_meter_action->set_active (td == Temporal::BeatTime);
ruler_tempo_action->set_active (td == Temporal::BeatTime);
ruler_range_action->set_active (true);
ruler_loop_punch_action->set_active (td == Temporal::BeatTime);
ruler_cd_marker_action->set_active (td == Temporal::AudioTime);
ruler_marker_action->set_active (true);
ruler_cue_marker_action->set_active (td == Temporal::BeatTime);
ruler_section_action->set_active (td == Temporal::BeatTime);
}
@ -477,8 +464,6 @@ Editor::update_ruler_visibility ()
meter_label.hide();
tempo_label.hide();
range_mark_label.hide();
transport_mark_label.hide();
cd_mark_label.hide();
section_mark_label.hide();
cue_mark_label.hide();
mark_label.hide();
@ -597,46 +582,6 @@ Editor::update_ruler_visibility ()
range_mark_label.hide();
}
if (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));
}
transport_marker_group->show();
transport_mark_label.show();
transport_marker_bar->set_outline(false);
tbpos += timebar_height;
tbgpos += timebar_height;
visible_timebars++;
} else {
transport_marker_group->hide();
transport_mark_label.hide();
}
if (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));
}
cd_marker_group->show();
cd_mark_label.show();
cd_marker_bar->set_outline(false);
tbpos += timebar_height;
tbgpos += timebar_height;
visible_timebars++;
// make sure all cd markers show up in their respective places
update_marker_display();
} else {
cd_marker_group->hide();
cd_mark_label.hide();
// make sure all cd markers show up in their respective places
update_marker_display();
}
if (ruler_marker_action->get_active()) {
old_unit_pos = marker_group->position().y;
if (tbpos != old_unit_pos) {
@ -655,25 +600,7 @@ Editor::update_ruler_visibility ()
mark_label.hide();
}
if (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));
}
cue_marker_group->show();
cue_mark_label.show();
cue_marker_bar->set_outline(false);
tbpos += timebar_height;
tbgpos += timebar_height;
visible_timebars++;
} else {
cue_marker_group->hide();
cue_mark_label.hide();
}
if (ruler_section_action->get_active()) {
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));
@ -1240,7 +1167,7 @@ Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, int64_t l
#if 0 // DEBUG GRID
for (auto const& g : grid) {
std::cout << "Grid " << g.time() << " Beats: " << g.beats() << " BBT: " << g.bbt() << " sample: " << g.sample(_session->nominal_sample_rate ()) << "\n";
std::cout << "Grid " << g.time() << " Beats: " << g.beats() << " BBT: " << g.bbt() << " sample: " << g.sample(_session->nominal_sample_rate ()) << "\n";
}
#endif

View File

@ -228,6 +228,10 @@ EditorSections::scroll_row_timeout ()
void
EditorSections::update_time_selection ()
{
if (!_session) {
return;
}
_view.get_selection ()->unselect_all ();
Selection& selection (PublicEditor::instance ().get_selection ());
@ -256,6 +260,10 @@ EditorSections::update_time_selection ()
void
EditorSections::selection_changed ()
{
if (!_session) {
return;
}
TreeView::Selection::ListHandle_Path rows = _view.get_selection ()->get_selected_rows ();
if (rows.empty ()) {
return;
@ -354,7 +362,14 @@ EditorSections::drag_motion (Glib::RefPtr<Gdk::DragContext> const& context, int
path.push_back (_model->children ().size () - 1);
}
context->drag_status (context->get_suggested_action (), time);
Gdk::DragAction suggested_action = context->get_suggested_action ();
/* default to move, unless the user hold ctrl */
if (context->get_actions () & Gdk::ACTION_MOVE) {
suggested_action = Gdk::ACTION_MOVE;
}
context->drag_status (suggested_action, time);
_view.set_drag_dest_row (path, pos);
_view.drag_highlight ();
@ -386,7 +401,7 @@ EditorSections::drag_data_received (Glib::RefPtr<Gdk::DragContext> const& contex
SectionOperation op = CopyPasteSection;
timepos_t to (0);
if ((context->get_suggested_action () == Gdk::ACTION_MOVE)) {
if ((context->get_selected_action () == Gdk::ACTION_MOVE)) {
op = CutPasteSection;
}

View File

@ -2398,6 +2398,20 @@ Editor::move_selected_tracks (bool up)
sl.sort (Stripable::Sorter());
/* Check if the selected tracks are already at the beginning or end of
* the ordering, depending on direction.
*/
for (auto & s : sl) {
if (s->is_selected()) {
if (up && (s->presentation_info().order() <= 1)) {
return;
} else if (!up && (s->presentation_info().order() >= sl.size() - 1)) {
return;
}
}
}
std::list<ViewStripable> view_stripables;
/* build a list that includes time axis view information */

View File

@ -152,13 +152,11 @@ 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 (VideoBarItem);
REGISTER_ENUM (TransportMarkerBarItem);
REGISTER_ENUM (SelectionItem);
REGISTER_ENUM (ControlPointItem);
REGISTER_ENUM (GainLineItem);

View File

@ -477,7 +477,7 @@ ExportDialog::show_progress ()
if (!status->aborted()) {
hide();
if (!ARDOUR::Profile->get_mixbus()) {
if (!ARDOUR::Profile->get_mixbus () && !ARDOUR::Profile->get_livetrax ()) {
NagScreen* ns = NagScreen::maybe_nag (_("export"));
if (ns) {
ns->nag ();

View File

@ -70,7 +70,7 @@ ExportFormatDialog::ExportFormatDialog (FormatPtr format, bool new_dialog)
, silence_end_checkbox (_("Add silence at end:"))
, silence_end_clock ("silence_end", true, "", true, false, true)
, command_label (_("Command to run post-export\n(%f=file path, %d=directory, %b=basename, see tooltip for more):"), Gtk::ALIGN_START)
, command_label (_("Command to run post-export\n(%f=file path, %d=directory, %b=basename; see tooltip for more,\ndon't add quotes around arguments):"), Gtk::ALIGN_START)
, format_table (3, 4)
, compatibility_label (_("Compatibility"), Gtk::ALIGN_START)

View File

@ -45,6 +45,7 @@
#include "gtkmm2ext/utils.h"
#include "gtkmm2ext/gtk_ui.h"
#include "widgets/slider_controller.h"
#include "widgets/tooltips.h"
#include "pbd/fastlog.h"
@ -315,6 +316,11 @@ GainMeterBase::set_gain_astate (AutoState as)
}
}
CairoWidget&
GainMeterBase::get_gain_slider() const {
return *gain_slider;
}
void
GainMeterBase::setup_gain_adjustment ()
{
@ -374,6 +380,13 @@ GainMeterBase::setup_meters (int len)
meter_channels = route()->shared_peak_meter()->input_streams().n_total();
}
if (len == 0) {
assert (gain_slider);
Gtk::Requisition sz;
sz = gain_slider->size_request ();
len = gain_slider->orientation () == FaderWidget::VERT ? sz.height : sz.width;
}
switch (_width) {
case Wide:
//meter_ticks1_area.show();
@ -676,7 +689,7 @@ void
GainMeterBase::update_gain_sensitive ()
{
bool x = !(_control->alist()->automation_state() & Play);
static_cast<ArdourWidgets::SliderController*>(gain_slider)->set_sensitive (x);
gain_slider->set_sensitive (x);
}
gint

View File

@ -48,7 +48,6 @@
#include "widgets/ardour_button.h"
#include "widgets/focus_entry.h"
#include "widgets/slider_controller.h"
#include "enums.h"
#include "level_meter.h"
@ -70,6 +69,10 @@ namespace Gtk {
class Menu;
}
namespace ArdourWidgets {
class SliderController;
}
enum MeterPointChangeTarget {
MeterPointChangeAll,
MeterPointChangeGroup,
@ -106,7 +109,7 @@ public:
std::shared_ptr<PBD::Controllable> get_controllable();
LevelMeterHBox& get_level_meter() const { return *level_meter; }
ArdourWidgets::SliderController& get_gain_slider() const { return *gain_slider; }
CairoWidget& get_gain_slider() const;
/** Emitted in the GUI thread when a button is pressed over the level meter;
* return true if the event is handled.

View File

@ -1015,7 +1015,10 @@ GenericPluginUI::build_control_ui (const Evoral::Parameter& param,
}
if (!_pi || mcontrol->flags () & Controllable::NotAutomatable) {
if (!_pi) {
control_ui->automate_button.set_no_show_all ();
control_ui->automate_button.hide ();
} else if (mcontrol->flags () & Controllable::NotAutomatable) {
control_ui->automate_button.set_sensitive (false);
set_tooltip(control_ui->automate_button, _("This control cannot be automated"));
} else {

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

@ -42,6 +42,7 @@
#include "mixer_ui.h"
#include "plugin_selector.h"
#include "plugin_ui.h"
#include "plugin_window_proxy.h"
#include "ui_config.h"
#include "pbd/i18n.h"
@ -299,7 +300,7 @@ IOPluginWindow::IOPlugUI::IOPlugUI (std::shared_ptr<ARDOUR::IOPlug> iop)
_window_proxy = dynamic_cast<PluginWindowProxy*> (iop->window_proxy ());
assert (_window_proxy);
} else {
_window_proxy = new PluginWindowProxy (string_compose ("IOP-%1", _iop->id ()), _iop);
_window_proxy = new PluginWindowProxy (string_compose ("IOP-%1", _iop->id ()), "I/O", _iop);
const XMLNode* ui_xml = _iop->session ().extra_xml (X_("UI"));
if (ui_xml) {
@ -373,113 +374,6 @@ IOPluginWindow::IOPlugUI::button_resized (Gtk::Allocation& alloc)
_btn_ioplug.set_layout_ellipsize_width (alloc.get_width () * PANGO_SCALE);
}
/* ****************************************************************************/
IOPluginWindow::PluginWindowProxy::PluginWindowProxy (std::string const& name, std::weak_ptr<PlugInsertBase> plugin)
: WM::ProxyBase (name, std::string ())
, _pib (plugin)
, _is_custom (true)
, _want_custom (true)
{
std::shared_ptr<PlugInsertBase> p = _pib.lock ();
if (!p) {
return;
}
p->DropReferences.connect (_going_away_connection, MISSING_INVALIDATOR, boost::bind (&IOPluginWindow::PluginWindowProxy::plugin_going_away, this), gui_context ());
}
IOPluginWindow::PluginWindowProxy::~PluginWindowProxy ()
{
_window = 0;
}
Gtk::Window*
IOPluginWindow::PluginWindowProxy::get (bool create)
{
std::shared_ptr<PlugInsertBase> p = _pib.lock ();
if (!p) {
return 0;
}
if (_window && (_is_custom != _want_custom)) {
set_state_mask (WindowProxy::StateMask (state_mask () & ~WindowProxy::Size));
drop_window ();
}
if (!_window) {
if (!create) {
return 0;
}
_is_custom = _want_custom;
_window = new PluginUIWindow (p, false, _is_custom);
if (_window) {
std::shared_ptr<ARDOUR::IOPlug> iop = std::dynamic_pointer_cast<ARDOUR::IOPlug> (p);
assert (iop);
_window->set_title (iop->name ());
setup ();
_window->show_all ();
}
}
return _window;
}
void
IOPluginWindow::PluginWindowProxy::show_the_right_window ()
{
if (_window && (_is_custom != _want_custom)) {
set_state_mask (WindowProxy::StateMask (state_mask () & ~WindowProxy::Size));
drop_window ();
}
if (_window) {
_window->unset_transient_for ();
}
toggle ();
}
int
IOPluginWindow::PluginWindowProxy::set_state (const XMLNode& node, int)
{
XMLNodeList children = node.children ();
XMLNodeList::const_iterator i = children.begin ();
while (i != children.end ()) {
std::string name;
if ((*i)->name () == X_("Window") && (*i)->get_property (X_("name"), name) && name == _name) {
break;
}
++i;
}
if (i != children.end ()) {
(*i)->get_property (X_("custom-ui"), _want_custom);
}
return ProxyBase::set_state (node, 0);
}
XMLNode&
IOPluginWindow::PluginWindowProxy::get_state () const
{
XMLNode* node;
node = &ProxyBase::get_state ();
node->set_property (X_("custom-ui"), _is_custom);
return *node;
}
void
IOPluginWindow::PluginWindowProxy::plugin_going_away ()
{
delete _window;
_window = 0;
WM::Manager::instance ().remove (this);
_going_away_connection.disconnect ();
delete this;
}
/* ****************************************************************************/
IOPluginWindow::IOButton::IOButton (std::shared_ptr<ARDOUR::IO> io, bool pre)
: _io (io)
, _pre (pre)

View File

@ -35,11 +35,11 @@ namespace ARDOUR
{
class IO;
class IOPlug;
class PlugInsertBase;
class Port;
}
class IOSelectorWindow;
class PluginWindowProxy;
class IOPluginWindow : public ArdourWindow
{
@ -48,39 +48,6 @@ public:
void set_session (ARDOUR::Session*);
class PluginWindowProxy : public WM::ProxyBase
{
public:
PluginWindowProxy (std::string const&, std::weak_ptr<ARDOUR::PlugInsertBase>);
~PluginWindowProxy ();
Gtk::Window* get (bool create = false);
void show_the_right_window ();
ARDOUR::SessionHandlePtr* session_handle ()
{
return 0;
}
void set_custom_ui_mode (bool use_custom)
{
_want_custom = use_custom;
}
int set_state (const XMLNode&, int);
XMLNode& get_state () const;
private:
void plugin_going_away ();
std::weak_ptr<ARDOUR::PlugInsertBase> _pib;
bool _is_custom;
bool _want_custom;
PBD::ScopedConnection _going_away_connection;
};
protected:
void on_show ();
void on_hide ();
@ -147,7 +114,7 @@ private:
IOButton _btn_output;
ArdourWidgets::ArdourButton _btn_ioplug;
PluginWindowProxy* _window_proxy;
std::shared_ptr<ARDOUR::IOPlug> _iop;
std::shared_ptr<ARDOUR::IOPlug> _iop;
PBD::ScopedConnection _going_away_connection;
};

View File

@ -37,8 +37,6 @@
#include "ardour/session_handle.h"
#include "widgets/fastmeter.h"
#include "widgets/focus_entry.h"
#include "widgets/slider_controller.h"
#include "enums.h"

View File

@ -42,6 +42,7 @@
#include "ardour_http.h"
#include "ardour_ui.h"
#include "audio_region_view.h"
#include "public_editor.h"
#include "region_selection.h"
#include "luadialog.h"
@ -826,6 +827,14 @@ LuaInstance::register_classes (lua_State* L, bool sandbox)
.endClass ()
.deriveClass <RegionView, TimeAxisViewItem> ("RegionView")
.addCast<AudioRegionView> ("to_audioregionview")
.addFunction ("show_region_editor", &RegionView::show_region_editor)
.addFunction ("hide_region_editor", &RegionView::hide_region_editor)
.endClass ()
.deriveClass <AudioRegionView, RegionView> ("RegionView")
.addFunction ("set_region_gain_line", &AudioRegionView::set_region_gain_line)
.addFunction ("set_region_fx_line", (bool (AudioRegionView::*)(uint32_t, uint32_t))&AudioRegionView::set_region_fx_line)
.endClass ()
.deriveClass <RouteUI, Selectable> ("RouteUI")
@ -1197,9 +1206,27 @@ LuaInstance::~LuaInstance ()
_callbacks.clear();
}
static std::string
lua_read_script (std::string const& fn)
{
if (!UIConfiguration::instance().get_update_action_scripts ()) {
return "";
}
try {
return Glib::file_get_contents (fn);
} catch (...) { }
return "";
}
void
LuaInstance::init ()
{
luabridge::getGlobalNamespace (lua.getState())
.beginNamespace ("Internal")
.addFunction ("get_factory_bytecode", &LuaScripting::get_factory_bytecode)
.addFunction ("read_script", &lua_read_script)
.endNamespace ();
lua.do_command (
"function ScriptManager ()"
" local self = { scripts = {}, instances = {}, icons = {} }"
@ -1302,10 +1329,20 @@ LuaInstance::init ()
" collectgarbage()"
" end"
""
" local get_factory_bytecode = Internal.get_factory_bytecode"
" local read_script = Internal.read_script"
" local restore = function (state)"
" clear()"
" load (state)()"
" for i, s in pairs (scripts) do"
" if s['a']['x-script-origin'] then"
" local sc = read_script (s['a']['x-script-origin'])"
" if sc ~= '' then"
" fnc = nil load (get_factory_bytecode (sc, 'factory', 'fnc'))()"
" icn = nil load (get_factory_bytecode (sc, 'icon', 'icn'))()"
" if fnc ~= '' and type(fnc) == 'string' then s['f'] = fnc s['c'] = icn s['s'] = sc end "
" end"
" end"
" addinternal (i, s['n'], s['s'], load(s['f']), type (s['c']) ~= \"string\" or s['c'] == '' or load (s['c']), s['a'])"
" end"
" collectgarbage()"
@ -1323,6 +1360,7 @@ LuaInstance::init ()
try {
luabridge::LuaRef lua_mgr = luabridge::getGlobal (L, "manager");
lua.do_command ("manager = nil"); // hide it.
lua.do_command ("Internal = nil");
lua.do_command ("collectgarbage()");
_lua_add_action = new luabridge::LuaRef(lua_mgr["add"]);
@ -1546,9 +1584,6 @@ LuaInstance::pre_seed_scripts ()
int id = 0;
pre_seed_script ("Mixer Screenshot", id);
pre_seed_script ("List Plugins", id);
#if defined MIXBUS && !defined PLATFORM_WINDOWS
pre_seed_script ("Import ADM BWF File", id);
#endif
}
bool

View File

@ -367,7 +367,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

View File

@ -103,6 +103,8 @@ MergeableLine::merge_drawn_line (Editor& e, Session& s, Evoral::ControlList::Ord
e.begin_reversible_command (_("draw automation"));
s.add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after));
_line->end_draw_merge ();
_line->get_selectables (earliest, latest, 0.0, 1.0, results);
e.get_selection ().set (results);

View File

@ -2548,13 +2548,13 @@ MidiRegionView::update_drag_selection(timepos_t const & start, timepos_t const &
/* Add control points to selection. */
const ATracks& atracks = midi_view()->automation_tracks();
Selectables selectables;
editor.get_selection().clear_points();
timepos_t st (start);
timepos_t et (end);
for (ATracks::const_iterator a = atracks.begin(); a != atracks.end(); ++a) {
Selectables selectables;
a->second->get_selectables (st, et, gy0, gy1, selectables);
for (Selectables::const_iterator s = selectables.begin(); s != selectables.end(); ++s) {
ControlPoint* cp = dynamic_cast<ControlPoint*>(*s);
@ -4751,8 +4751,6 @@ MidiRegionView::note_to_y(uint8_t note) const
void
MidiRegionView::quantize_selected_notes ()
{
std::cerr << "QSN!\n";
RegionSelection rs;
rs.push_back (this);

View File

@ -338,9 +338,9 @@ MidiTracer::tracer (Parser&, MIDI::byte* msg, size_t len, samplecnt_t now)
case polypress:
if (show_hex) {
s += snprintf (&buf[s], bufsize, "%16s chn %2d %02x\n", "PolyPressure", (msg[0]&0xf)+1, (int) msg[1]);
s += snprintf (&buf[s], bufsize, "%16s chn %2d %02x %02x\n", "PolyPressure", (msg[0]&0xf)+1, (int) msg[1], msg[2]);
} else {
s += snprintf (&buf[s], bufsize, "%16s chn %2d %-3d\n", "PolyPressure", (msg[0]&0xf)+1, (int) msg[1]);
s += snprintf (&buf[s], bufsize, "%16s chn %2d %-3d %-3d\n", "PolyPressure", (msg[0]&0xf)+1, (int) msg[1], msg[2]);
}
break;
@ -362,9 +362,9 @@ MidiTracer::tracer (Parser&, MIDI::byte* msg, size_t len, samplecnt_t now)
case chanpress:
if (show_hex) {
s += snprintf (&buf[s], bufsize, "%16s chn %2d %02x/%-3d\n", "Channel Pressure", (msg[0]&0xf)+1, (int) msg[1], (int) msg[1]);
s += snprintf (&buf[s], bufsize, "%16s chn %2d %02x\n", "Channel Pressure", (msg[0]&0xf)+1, (int) msg[1]);
} else {
s += snprintf (&buf[s], bufsize, "%16s chn %2d %02x/%-3d\n", "Channel Pressure", (msg[0]&0xf)+1, (int) msg[1], (int) msg[1]);
s += snprintf (&buf[s], bufsize, "%16s chn %2d %-3d\n", "Channel Pressure", (msg[0]&0xf)+1, (int) msg[1]);
}
break;

View File

@ -378,6 +378,7 @@ MixerStrip::init ()
number_label.signal_button_press_event().connect (sigc::mem_fun(*this, &MixerStrip::number_button_button_press), false);
name_button.set_fallthrough_to_parent (true);
name_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MixerStrip::name_button_button_press), false);
group_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MixerStrip::select_route_group), false);
@ -1208,7 +1209,21 @@ MixerStrip::build_route_ops_menu ()
gboolean
MixerStrip::name_button_button_press (GdkEventButton* ev)
{
if (ev->button == 1 || ev->button == 3) {
if (ev->button == 1 && ev->type == GDK_BUTTON_PRESS) {
/* fall thru to mixer */
return false;
}
if (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS) {
route_rename ();
return true;
}
if (ev->button == 3 && ARDOUR::Profile->get_livetrax() && _route && _route->is_singleton ()) {
return true;
}
if (ev->button == 3) {
list_route_operations ();
if (ev->button == 1) {

View File

@ -112,6 +112,13 @@ using namespace std;
using PBD::atoi;
using PBD::Unwinder;
static const gchar *_plugin_list_mode_strings[] = {
N_("Favorite Plugins"),
N_("Recent Plugins"),
N_("Top-10 Plugins"),
0
};
Mixer_UI* Mixer_UI::_instance = 0;
Mixer_UI*
@ -126,7 +133,7 @@ Mixer_UI::instance ()
Mixer_UI::Mixer_UI ()
: Tabbable (_content, _("Mixer"), X_("mixer"))
, plugin_search_clear_button (Stock::CLEAR)
, plugin_search_clear_button (X_("Clear"))
, _mixer_scene_release (0)
, no_track_list_redisplay (false)
, in_group_row_change (false)
@ -146,6 +153,9 @@ Mixer_UI::Mixer_UI ()
, _strip_selection_change_without_scroll (false)
, _selection (*this, *this)
{
plugin_list_mode_strings = I18N (_plugin_list_mode_strings);
load_bindings ();
register_actions ();
Glib::RefPtr<ToggleAction> fb_act = ActionManager::get_toggle_action ("Mixer", "ToggleFoldbackStrip");
@ -268,14 +278,14 @@ Mixer_UI::Mixer_UI ()
favorite_plugins_model->signal_row_has_child_toggled().connect (sigc::mem_fun (*this, &Mixer_UI::sync_treeview_favorite_ui_state));
favorite_plugins_model->signal_row_deleted().connect (sigc::mem_fun (*this, &Mixer_UI::favorite_plugins_deleted));
favorite_plugins_mode_combo.append (_("Favorite Plugins"));
favorite_plugins_mode_combo.append (_("Recent Plugins"));
favorite_plugins_mode_combo.append (_("Top-10 Plugins"));
favorite_plugins_mode_combo.set_active_text (_("Favorite Plugins"));
favorite_plugins_mode_combo.signal_changed().connect (sigc::mem_fun (*this, &Mixer_UI::plugin_list_mode_changed));
favorite_plugins_mode_combo.AddMenuElem (Menu_Helpers::MenuElem (_("Favorite Plugins"), sigc::bind(sigc::mem_fun(*this, &Mixer_UI::set_plugin_list_mode), PLM_Favorite)));
favorite_plugins_mode_combo.AddMenuElem (Menu_Helpers::MenuElem (_("Recent Plugins"), sigc::bind(sigc::mem_fun(*this, &Mixer_UI::set_plugin_list_mode), PLM_Recent)));
favorite_plugins_mode_combo.AddMenuElem (Menu_Helpers::MenuElem (_("Top-10 Plugins"), sigc::bind(sigc::mem_fun(*this, &Mixer_UI::set_plugin_list_mode), PLM_TopHits)));
favorite_plugins_mode_combo.set_size_request(-1, 24);
set_plugin_list_mode(PLM_Favorite);
plugin_search_entry.signal_changed().connect (sigc::mem_fun (*this, &Mixer_UI::plugin_search_entry_changed));
plugin_search_clear_button.signal_clicked().connect (sigc::mem_fun (*this, &Mixer_UI::plugin_search_clear_button_clicked));
plugin_search_clear_button.signal_clicked.connect (sigc::mem_fun (*this, &Mixer_UI::plugin_search_clear_button_clicked));
favorite_plugins_scroller.add (favorite_plugins_display);
favorite_plugins_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
@ -588,6 +598,8 @@ Mixer_UI::add_stripables (StripableList& slist)
nroutes++;
// XXX what does this special case do?
// A: it inserts the new track at the correct point in the model
// uness it's the the first (after master-bus, which is not in Mixbus track-model)
if (s->presentation_info().order() == (slist.front()->presentation_info().order() + slist.size())) {
insert_iter = it;
break;
@ -716,7 +728,7 @@ Mixer_UI::add_stripables (StripableList& slist)
track_display.set_model (track_model);
if (!from_scratch) {
sync_presentation_info_from_treeview ();
sync_treeview_from_presentation_info (Properties::order);
}
redisplay_track_list ();
@ -2893,8 +2905,12 @@ Mixer_UI::parameter_changed (string const & p)
bool const s = _session ? _session->config.get_show_group_tabs () : true;
if (s) {
_group_tabs->show ();
vca_label_bar.show ();
Gtk::Requisition group_size = _group_tabs->size_request();
vca_label_bar.set_size_request (-1, group_size.height + 1);
} else {
_group_tabs->hide ();
vca_label_bar.hide ();
}
} else if (p == "default-narrow_ms") {
bool const s = UIConfiguration::instance().get_default_narrow_ms ();
@ -3122,22 +3138,10 @@ Mixer_UI::monitor_section_detached ()
act->set_sensitive (false);
}
Mixer_UI::PluginListMode
Mixer_UI::plugin_list_mode () const
{
if (favorite_plugins_mode_combo.get_active_text() == _("Top-10 Plugins")) {
return PLM_TopHits;
} else if (favorite_plugins_mode_combo.get_active_text() == _("Recent Plugins")) {
return PLM_Recent;
} else {
return PLM_Favorite;
}
}
void
Mixer_UI::store_current_favorite_order ()
{
if (plugin_list_mode () != PLM_Favorite || !plugin_search_entry.get_text ().empty()) {
if (plugin_list_mode != PLM_Favorite || !plugin_search_entry.get_text ().empty()) {
return;
}
@ -3163,9 +3167,16 @@ Mixer_UI::save_favorite_ui_state (const TreeModel::iterator& iter, const TreeMod
}
void
Mixer_UI::plugin_list_mode_changed ()
Mixer_UI::set_plugin_list_mode (PluginListMode plm)
{
if (plugin_list_mode () == PLM_Favorite) {
plugin_list_mode = plm;
string str = plugin_list_mode_strings[(int)plm];
if (str != favorite_plugins_mode_combo.get_text ()) {
favorite_plugins_mode_combo.set_text (str);
}
if (plugin_list_mode == PLM_Favorite) {
PBD::Unwinder<bool> uw (ignore_plugin_refill, true);
favorite_plugins_search_hbox.show ();
plugin_search_entry.set_text ("");
@ -3178,7 +3189,7 @@ Mixer_UI::plugin_list_mode_changed ()
void
Mixer_UI::plugin_search_entry_changed ()
{
if (plugin_list_mode () == PLM_Favorite) {
if (plugin_list_mode == PLM_Favorite) {
refill_favorite_plugins ();
}
}
@ -3193,7 +3204,7 @@ void
Mixer_UI::refiller (PluginInfoList& result, const PluginInfoList& plugs)
{
PluginManager& manager (PluginManager::instance());
PluginListMode plm = plugin_list_mode ();
PluginListMode plm = plugin_list_mode;
std::string searchstr = plugin_search_entry.get_text ();
setup_search_string (searchstr);
@ -3264,7 +3275,7 @@ Mixer_UI::refill_favorite_plugins ()
refiller (plugs, mgr.lv2_plugin_info ());
refiller (plugs, mgr.lua_plugin_info ());
switch (plugin_list_mode ()) {
switch (plugin_list_mode) {
default:
/* use favorites as-is */
break;
@ -3295,12 +3306,12 @@ Mixer_UI::maybe_refill_favorite_plugins (PluginListMode plm)
{
switch (plm) {
case PLM_Favorite:
if (plugin_list_mode () == PLM_Favorite) {
if (plugin_list_mode == PLM_Favorite) {
refill_favorite_plugins();
}
break;
default:
if (plugin_list_mode () != PLM_Favorite) {
if (plugin_list_mode != PLM_Favorite) {
refill_favorite_plugins();
}
break;
@ -3330,7 +3341,7 @@ void
Mixer_UI::sync_treeview_from_favorite_order ()
{
PBD::Unwinder<bool> uw (ignore_plugin_reorder, true);
switch (plugin_list_mode ()) {
switch (plugin_list_mode) {
case PLM_Favorite:
{
PluginUIOrderSorter cmp (favorite_ui_order);
@ -3594,14 +3605,14 @@ Mixer_UI::plugin_drag_motion (const Glib::RefPtr<Gdk::DragContext>& ctx, int x,
}
if (target == "GTK_TREE_MODEL_ROW") {
if (plugin_list_mode () == PLM_Favorite && plugin_search_entry.get_text ().empty()) {
if (plugin_list_mode == PLM_Favorite && plugin_search_entry.get_text ().empty()) {
/* re-order rows */
ctx->drag_status (Gdk::ACTION_MOVE, time);
return true;
}
} else if (target == "x-ardour/plugin.preset") {
ctx->drag_status (Gdk::ACTION_COPY, time);
//favorite_plugins_mode_combo.set_active_text (_("Favorite Plugins"));
//favorite_plugins_mode_combo.set_text (_("Favorite Plugins"));
return true;
}

View File

@ -54,6 +54,7 @@
#include "widgets/pane.h"
#include "widgets/tabbable.h"
#include "widgets/ardour_dropdown.h"
#include "axis_provider.h"
#include "enums.h"
@ -194,9 +195,9 @@ private:
Gtk::Frame favorite_plugins_frame;
Gtk::VBox favorite_plugins_vbox;
Gtk::HBox favorite_plugins_search_hbox;
Gtk::ComboBoxText favorite_plugins_mode_combo;
ArdourWidgets::ArdourDropdown favorite_plugins_mode_combo;
Gtk::Entry plugin_search_entry;
Gtk::Button plugin_search_clear_button;
ArdourWidgets::ArdourButton plugin_search_clear_button;
ArdourWidgets::VPane rhs_pane1;
ArdourWidgets::VPane rhs_pane2;
ArdourWidgets::HPane inner_pane;
@ -443,13 +444,15 @@ private:
PLM_Recent,
PLM_TopHits
};
enum PluginListMode plugin_list_mode;
void set_plugin_list_mode (PluginListMode plm);
std::vector<std::string> plugin_list_mode_strings;
void refiller (ARDOUR::PluginInfoList& result, const ARDOUR::PluginInfoList& plugs);
void refill_favorite_plugins ();
void maybe_refill_favorite_plugins (PluginListMode);
void store_current_favorite_order();
enum PluginListMode plugin_list_mode () const;
void plugin_list_mode_changed ();
void plugin_search_entry_changed ();
void plugin_search_clear_button_clicked ();
void favorite_plugins_deleted (const Gtk::TreeModel::Path&);

View File

@ -293,6 +293,14 @@ NoteBase::event_handler (GdkEvent* ev)
return false;
}
if (_region.get_time_axis_view ().layer_display () == Stacked) {
/* only allow edting notes in the topmost layer */
if (_region.region()->layer() != _region.region()->playlist()->top_layer ()) {
/* this stll allows the draw tool to work, and edit cursor is updated */
return false;
}
}
switch (ev->type) {
case GDK_ENTER_NOTIFY:
_region.note_entered (this);

View File

@ -45,6 +45,7 @@
#include "pbd/strsplit.h"
#include "widgets/frame.h"
#include "widgets/slider_controller.h"
#include "gui_thread.h"
#include "option_editor.h"
@ -678,6 +679,11 @@ FaderOption::add_to_page (OptionEditorPage* p)
add_widgets_to_page (p, _label, &_box);
}
Gtk::Widget&
FaderOption::tip_widget() {
return *_db_slider;
}
/*--------------------------*/
ClockOption::ClockOption (string const & i, string const & n, sigc::slot<std::string> g, sigc::slot<bool, std::string> s)
@ -1107,20 +1113,20 @@ OptionEditor::add_path_to_treeview (std::string const & pn, Gtk::Widget& widget)
}
/** Add a component to a given page.
* @param pn Page name (will be created if it doesn't already exist)
* @param page_name Page name (will be created if it doesn't already exist)
* @param o Component.
*/
void
OptionEditor::add_option (std::string const & pn, OptionEditorComponent* o)
OptionEditor::add_option (std::string const & page_name, OptionEditorComponent* o)
{
if (_pages.find (pn) == _pages.end()) {
OptionEditorPage* oep = new OptionEditorPage (_notebook, pn);
_pages[pn] = oep;
if (_pages.find (page_name) == _pages.end()) {
OptionEditorPage* oep = new OptionEditorPage (_notebook, page_name);
_pages[page_name] = oep;
add_path_to_treeview (pn, oep->box);
add_path_to_treeview (page_name, oep->box);
}
OptionEditorPage* p = _pages[pn];
OptionEditorPage* p = _pages[page_name];
p->components.push_back (o);
o->add_to_page (p);

View File

@ -39,8 +39,6 @@
#include "pbd/configuration.h"
#include "widgets/slider_controller.h"
#include "actions.h"
#include "ardour_window.h"
#include "audio_clock.h"
@ -64,6 +62,7 @@
namespace ArdourWidgets {
class Frame;
class HSliderController;
}
class OptionEditorPage;
@ -601,7 +600,7 @@ public:
void set_state_from_config ();
void add_to_page (OptionEditorPage *);
Gtk::Widget& tip_widget() { return *_db_slider; }
Gtk::Widget& tip_widget();
private:
void db_changed ();

View File

@ -674,9 +674,8 @@ PianoRollHeader::on_button_press_event (GdkEventButton* ev)
_adj.set_page_size (127.0);
_adj.value_changed ();
queue_draw ();
return false;
}
return false;
return true;
} else if (ev->button == 2 && Keyboard::no_modifiers_active (ev->state)) {
SetNoteSelection (note); // EMIT SIGNAL
return true;

View File

@ -1710,6 +1710,17 @@ PluginPinWidget::add_remove_port_clicked (bool add, ARDOUR::DataType dt)
ChanCount ins, outs, src;
_pi->configured_io (ins, outs);
src = _pi->natural_output_streams ();
if (src.get (dt) == 0) {
if (!add || ins.get (dt) < out.get (dt)) {
return;
}
int pn = out.get (dt);
assert (pn > 0);
ChanMapping map (_pi->thru_map ());
map.set (dt, pn - 1, pn - 1);
_pi->set_thru_map (map);
return;
}
for (uint32_t i = n_before; i < outs.get (dt); ++i) {
uint32_t pc = i / src.get (dt);
uint32_t pn = i % src.get (dt);

View File

@ -200,9 +200,6 @@ PluginUIWindow::PluginUIWindow (std::shared_ptr<PlugInsertBase> pib,
PluginUIWindow::~PluginUIWindow ()
{
#ifndef NDEBUG
cerr << "PluginWindow deleted for " << this << endl;
#endif
delete _pluginui;
if (the_plugin_window == this) {

View File

@ -0,0 +1,154 @@
/*
* Copyright (C) 2022 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
* 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 "ardour/plug_insert_base.h"
#include "ardour/plugin_manager.h"
#include "gui_thread.h"
#include "plugin_ui.h"
#include "plugin_window_proxy.h"
#include "pbd/i18n.h"
using namespace ARDOUR;
using namespace Gtk;
using namespace Gtkmm2ext;
PluginWindowProxy::PluginWindowProxy (std::string const& name, std::string const& title, std::weak_ptr<PlugInsertBase> plugin)
: WM::ProxyBase (name, std::string ())
, _pib (plugin)
, _title (title)
, _is_custom (true)
, _want_custom (true)
{
std::shared_ptr<PlugInsertBase> p = _pib.lock ();
if (!p) {
return;
}
p->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&PluginWindowProxy::plugin_going_away, this), gui_context ());
}
PluginWindowProxy::~PluginWindowProxy ()
{
_window = 0;
}
Gtk::Window*
PluginWindowProxy::get (bool create)
{
std::shared_ptr<PlugInsertBase> p = _pib.lock ();
if (!p) {
return 0;
}
if (_window && (_is_custom != _want_custom)) {
set_state_mask (WindowProxy::StateMask (state_mask () & ~WindowProxy::Size));
drop_window ();
}
if (!_window) {
if (!create) {
return 0;
}
_is_custom = _want_custom;
_window = new PluginUIWindow (p, false, _is_custom);
if (_window) {
_window->set_title (generate_processor_title (p));
setup ();
_window->show_all ();
}
}
return _window;
}
void
PluginWindowProxy::show_the_right_window ()
{
if (_window && (_is_custom != _want_custom)) {
set_state_mask (WindowProxy::StateMask (state_mask () & ~WindowProxy::Size));
drop_window ();
}
if (_window) {
_window->unset_transient_for ();
}
toggle ();
}
int
PluginWindowProxy::set_state (const XMLNode& node, int)
{
XMLNodeList children = node.children ();
XMLNodeList::const_iterator i = children.begin ();
while (i != children.end ()) {
std::string name;
if ((*i)->name () == X_("Window") && (*i)->get_property (X_("name"), name) && name == _name) {
break;
}
++i;
}
if (i != children.end ()) {
(*i)->get_property (X_("custom-ui"), _want_custom);
}
return ProxyBase::set_state (node, 0);
}
XMLNode&
PluginWindowProxy::get_state () const
{
XMLNode* node;
node = &ProxyBase::get_state ();
node->set_property (X_("custom-ui"), _is_custom);
return *node;
}
void
PluginWindowProxy::plugin_going_away ()
{
delete _window;
_window = 0;
WM::Manager::instance ().remove (this);
drop_connections ();
delete this;
}
std::string
PluginWindowProxy::generate_processor_title (std::shared_ptr<PlugInsertBase> p)
{
std::string maker = p->plugin()->maker() ? p->plugin()->maker() : "";
std::string::size_type email_pos;
if ((email_pos = maker.find_first_of ('<')) != std::string::npos) {
maker = maker.substr (0, email_pos - 1);
}
if (maker.length() > 32) {
maker = maker.substr (0, 32);
maker += " ...";
}
std::string type = PluginManager::plugin_type_name (p->type ());
auto so = std::dynamic_pointer_cast<SessionObject> (p);
assert (so);
return string_compose(_("%1: %2 (by %3) [%4]"), _title, so->name(), maker, type);
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2022,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
* 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 _gtkardour_plugin_window_proxy_h_
#define _gtkardour_plugin_window_proxy_h_
#include "ardour_window.h"
#include "window_manager.h"
#include "pbd/signals.h"
namespace Gtk
{
class Window;
}
namespace ARDOUR
{
class PlugInsertBase;
}
class PluginWindowProxy : public WM::ProxyBase, public PBD::ScopedConnectionList
{
public:
PluginWindowProxy (std::string const&, std::string const&, std::weak_ptr<ARDOUR::PlugInsertBase>);
~PluginWindowProxy ();
Gtk::Window* get (bool create = false);
void show_the_right_window ();
ARDOUR::SessionHandlePtr* session_handle ()
{
return 0;
}
void set_custom_ui_mode (bool use_custom)
{
_want_custom = use_custom;
}
int set_state (const XMLNode&, int);
XMLNode& get_state () const;
std::string generate_processor_title (std::shared_ptr<ARDOUR::PlugInsertBase>);
private:
void plugin_going_away ();
std::weak_ptr<ARDOUR::PlugInsertBase> _pib;
std::string _title;
bool _is_custom;
bool _want_custom;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -5774,7 +5774,7 @@ msgstr "Assistant de sonie"
#: editor_actions.cc:443 rc_option_editor.cc:3347
msgid "Split/Separate"
msgstr "Découper/Séparer"
msgstr "Découper/séparer"
#: editor_actions.cc:448
msgid "Fade Range Selection"
@ -6963,7 +6963,7 @@ msgid ""
"Master bus output gain control is disabled.\n"
"Visit preferences to enable it?"
msgstr ""
"Le contrôle de gain de sortie du bus maître est désactivé.\n"
"Le contrôle de gain de sortie du bus général est désactivé.\n"
"Visiter les préférences pour l'activer ?"
#: editor_export_audio.cc:167
@ -6980,14 +6980,14 @@ msgstr "L'analyse de la sonie nécessite une intervalle-de-session."
msgid "Loudness Analysis is only available for sessions with a master-bus"
msgstr ""
"L'analyse de la sonie n'est disponible que pour les sessions avec un bus-"
"maître"
"général"
#: editor_export_audio.cc:180
msgid ""
"Loudness Analysis is only available for sessions with a stereo master-bus"
msgstr ""
"L'analyse de la sonie n'est disponible que pour les sessions avec un bus-"
"maître stéréo"
"général stéréo"
#: editor_export_audio.cc:222
msgid "Confirm MIDI File Overwrite"
@ -9859,7 +9859,7 @@ msgstr "Créer un nouveau groupe à partir de..."
#: group_tabs.cc:347
msgid "Create New Group with Master From..."
msgstr "Créer un nouveau groupe avec un Master à partir de..."
msgstr "Créer un nouveau groupe avec un général à partir de..."
#: group_tabs.cc:374 route_group_menu.cc:88
msgid "Edit Group..."
@ -10388,13 +10388,13 @@ msgid ""
msgstr ""
"<b>Si coché</b> un processeur d'amplification est utilisé pour appliquer le "
"gain. Cela permet un positionnement personnalisé de l'étage de gain dans le "
"flux de signaux du bus maître, éventuellement suivi d'un limiteur pour se "
"flux de signaux du bus général, éventuellement suivi d'un limiteur pour se "
"conformer aux exigences en matière d'intensité sonore et de crête. En "
"fonction des réglages du limiteur ou du DSP après l'étage de gain, des "
"mesures répétées de l'intensité sonore peuvent produire des résultats "
"différents.\n"
"<b>Si décoché</b>, le gain est appliqué directement à la sortie du bus "
"maître. Cela permet un réglage efficace et fiable du volume."
"général. Cela permet un réglage efficace et fiable du volume."
#: loudness_dialog.cc:286
msgid "<b>Loudness Analysis</b>\n"
@ -10408,7 +10408,7 @@ msgid ""
"profile."
msgstr ""
"Cela permet à l'utilisateur d'analyser et de conformer la sonie du signal à "
"la sortie du bus maître de la session complète, comme s'il était exporté. "
"la sortie du bus général de la session complète, comme s'il était exporté. "
"Lorsque vous utilisez cette fonctionnalité, n'oubliez pas de désactiver la "
"normalisation dans le profil d'exportation de la session."
@ -11606,11 +11606,11 @@ msgstr "Sonie"
#: mixer_strip.cc:648
msgid "Master output volume"
msgstr "Volume de sortie maître"
msgstr "Volume de la sortie générale"
#: mixer_strip.cc:649
msgid "Measure loudness of the session, normalize master output volume"
msgstr "Mesure la sonie de la session, normalise le volume de sortie maître"
msgstr "Mesure la sonie de la session, normalise le volume de la sortie général"
#: mixer_strip.cc:684
msgid "Enable/Disable MIDI input"
@ -12068,13 +12068,12 @@ msgid "(Right-Click to Store)"
msgstr "(Clic-droit pour stocker)"
#: mixer_ui.cc:4415
#, fuzzy
msgid ""
"Disabling surround master will delete all existing surround panner state.\n"
"This cannot be undonoe. Proceed anyway?"
msgstr ""
"La désactivation de l'option \"surround master\" supprimera tous les états "
"existants de l'option \"surround panner\".\n"
"de panneau de surround existants.\n"
"Il n'est pas possible de revenir en arrière. Poursuivre quand même ?"
#: meter_strip.cc:171
@ -12476,7 +12475,7 @@ msgstr ""
"\n"
"Vous pouvez utiliser %1 pour enregistrer un orchestre, créer avec des "
"boucles audios/MIDI, éditer la prise vocale parfaite, mixer un évènement en "
"direct avec des effets , doubler une vidéo et masteriser vos morceaux pour "
"direct avec des effets, doubler une vidéo et masteriser vos pistes pour "
"une diffusion numérique. \n"
"\n"
"Quelques éléments doivent être configurés avant de commencer à utiliser le "
@ -14478,7 +14477,7 @@ msgstr "RàZ vers les recommandations par défaut"
#: rc_option_editor.cc:1110
msgid "GUI and Font scaling"
msgstr "Ajustement d'Interface et Police"
msgstr "Ajustement d'interface et de police "
#: rc_option_editor.cc:1134
msgid ""
@ -14523,12 +14522,14 @@ msgid "Waveform Clip Level (dBFS)"
msgstr "Niveau d'écrêtage de la forme d'onde (dBFS) "
#: rc_option_editor.cc:1206
# extraspace needed to get a space before the semicolon
msgid "Playback (seconds of buffering)"
msgstr "Lecture (secondes en mémoire)"
msgstr "Lecture (secondes en mémoire) "
#: rc_option_editor.cc:1210
# extraspace needed to get a space before the semicolon
msgid "Recording (seconds of buffering)"
msgstr "Enregistrement (secondes en mémoire)"
msgstr "Enregistrement (secondes en mémoire) "
#: rc_option_editor.cc:1219
msgid "Small sessions (4-16 tracks)"
@ -14818,8 +14819,9 @@ msgid "GUI Lock"
msgstr "Verrouillage de l'interface"
#: rc_option_editor.cc:2492
# extraspace needed to get a space before the semicolon
msgid "Lock timeout (seconds)"
msgstr "Délai de temporisation du verrouillage (secondes)"
msgstr "Délai de temporisation du verrouillage (secondes) "
#: rc_option_editor.cc:2500
msgid "Lock GUI after this many idle seconds (zero to never lock)"
@ -14828,8 +14830,9 @@ msgstr ""
"(zéro pour ne jamais verrouiller)"
#: rc_option_editor.cc:2505
# extraspace needed to get a space before the semicolon
msgid "System Screensaver Mode"
msgstr "Fonctionnement de l'écran de veille du système"
msgstr "Fonctionnement de l'écran de veille du système "
#: rc_option_editor.cc:2510
msgid "Never Inhibit"
@ -14864,8 +14867,9 @@ msgid "LED meter style"
msgstr "Style d'afficheur LED"
#: rc_option_editor.cc:2553
# extraspace needed to get a space before the semicolon
msgid "Icon Set"
msgstr "Jeu d'icônes"
msgstr "Jeu d'icônes "
#: rc_option_editor.cc:2564
msgid "Graphical User Interface"
@ -14961,16 +14965,19 @@ msgid "Show Selection Marker"
msgstr "Afficher les repères de sélection"
#: rc_option_editor.cc:2675
# extraspace needed to get a space before the semicolon
msgid "Waveforms color gradient depth"
msgstr "Profondeur de dégradé des couleurs de formes d'onde"
msgstr "Profondeur de dégradé des couleurs de formes d'onde "
#: rc_option_editor.cc:2686
# extraspace needed to get a space before the semicolon
msgid "Timeline item gradient depth"
msgstr "Profondeur de dégradé des éléments de la ligne de temps"
msgstr "Profondeur de dégradé des éléments de la ligne de temps "
#: rc_option_editor.cc:2696
# extraspace needed to get a space before the semicolon
msgid "Track name ellipsize mode"
msgstr "Mode elliptique du nom de la piste"
msgstr "Mode elliptique du nom de la piste "
#: rc_option_editor.cc:2700
msgid "Ellipsize start of name"
@ -14993,8 +15000,9 @@ msgstr ""
"têtes des pistes de l'éditeur"
#: rc_option_editor.cc:2709
# extraspace needed to get a space before the semicolon
msgid "Add a visual gap below Audio Regions"
msgstr "Ajouter un espace visuel sous les régions audio"
msgstr "Ajouter un espace visuel sous les régions audio "
#: rc_option_editor.cc:2718
msgid "Editor Meters"
@ -15030,8 +15038,9 @@ msgid "Use colors to show note velocity"
msgstr "Utiliser des couleurs pour afficher la vélocité des notes"
#: rc_option_editor.cc:2773
# extraspace needed to get a space before the semicolon
msgid "Display note names in MIDI track headers"
msgstr "Affichage des noms de notes dans les en-têtes de pistes MIDI"
msgstr "Affichage des noms de notes dans les en-têtes de pistes MIDI "
#: rc_option_editor.cc:2777
msgid "Always"
@ -15112,8 +15121,9 @@ msgstr ""
"Utiliser par défaut des tranches de console étroites pour les nouvelles voies"
#: rc_option_editor.cc:2878
# extraspace needed to get a space before the semicolon
msgid "Limit inline-mixer-strip controls per plugin"
msgstr "Limiter les contrôles en-ligne dans le mixeur par greffon"
msgstr "Limiter les contrôles en-ligne dans le mixeur par greffon "
#: rc_option_editor.cc:2882 rc_option_editor.cc:4940
msgid "Unlimited"
@ -15168,7 +15178,7 @@ msgstr "Afficher la section info du moniteur"
#: rc_option_editor.cc:2938
msgid "Display Cue Rec/Play Controls"
msgstr "Afficher enr. Cue/Controle lecture"
msgstr "Afficher enr. Cue/Contrôles de lecture"
#: rc_option_editor.cc:2946
msgid "Display Navigation Timeline"
@ -15176,7 +15186,7 @@ msgstr "Afficher la navigation chronologique"
#: rc_option_editor.cc:2954
msgid "Display Master Level Meter"
msgstr "Afficher l'indicateur du niveau Master"
msgstr "Afficher l'indicateur du niveau général"
#: rc_option_editor.cc:2961
msgid "Display Action-Buttons"
@ -15188,7 +15198,7 @@ msgstr "Apparence/Taille et échelle"
#: rc_option_editor.cc:2971
msgid "User Interface Size and Scale"
msgstr "Taille et echelle de l'interface utilisateur"
msgstr "Taille et échelle de l'interface utilisateur"
#: rc_option_editor.cc:2979 rc_option_editor.cc:2980 rc_option_editor.cc:2981
#: rc_option_editor.cc:2993 rc_option_editor.cc:3005 rc_option_editor.cc:3018
@ -15444,8 +15454,9 @@ msgid "Show cue markers in regions"
msgstr "Afficherer les repères cue dans les régions"
#: rc_option_editor.cc:3184
# extraspace needed to get a space before the semicolon
msgid "Show gain envelopes in audio regions"
msgstr "Afficher les enveloppes de gain dans les régions audio"
msgstr "Afficher les enveloppes de gain dans les régions audio "
#: rc_option_editor.cc:3185
msgid "in all modes"
@ -15482,9 +15493,10 @@ msgstr ""
"bords"
#: rc_option_editor.cc:3243
# extraspace needed to get a space before the semicolon
msgid "Auto-scroll speed when dragging playhead"
msgstr ""
"Vitesse de défilement automatique lors du glissement de la tête de lecture"
"Vitesse de défilement automatique lors du glissement de la tête de lecture "
#: rc_option_editor.cc:3247
msgid "5%"
@ -15503,9 +15515,10 @@ msgid "50%"
msgstr "50%"
#: rc_option_editor.cc:3257
# extraspace needed to get a space before the semicolon
msgid "Limit zoom & summary view beyond session extents to"
msgstr ""
"Limiter le zoom et l'affichage du résumé au-delà des limites de la session"
"Limiter le zoom et l'affichage du résumé au-delà des limites de la session "
#: rc_option_editor.cc:3261
msgid "1 minute"
@ -15573,12 +15586,14 @@ msgstr ""
"au toucher\" est utilisée."
#: rc_option_editor.cc:3304
# extraspace needed to get a space before the semicolon
msgid "Default fade shape"
msgstr "Forme du fondu par défaut"
msgstr "Forme du fondu par défaut "
#: rc_option_editor.cc:3323
# extraspace needed to get a space before the semicolon
msgid "Regions in edit groups are edited together"
msgstr "Les régions des groupes d'édition sont éditées ensemble"
msgstr "Les régions des groupes d'édition sont éditées ensemble "
#: rc_option_editor.cc:3328
msgid "whenever they overlap in time"
@ -15597,8 +15612,9 @@ msgid "if they have identical length, position and layer"
msgstr "s'ils ont une longueur, une position et une couche identiques"
#: rc_option_editor.cc:3338
# extraspace needed to get a space before the semicolon
msgid "Layering model"
msgstr "Type d'empilage"
msgstr "Type d'empilage "
#: rc_option_editor.cc:3343
msgid "later is higher"
@ -15609,8 +15625,9 @@ msgid "manual layering"
msgstr "manuel"
#: rc_option_editor.cc:3351
# extraspace needed to get a space before the semicolon
msgid "After a Separate operation, in Range mode"
msgstr "Après une opération de Séparation, en mode Intervalle"
msgstr "Après une opération de séparation, en mode Intervalle "
#: rc_option_editor.cc:3355
msgid "Clear the Range Selection"
@ -15625,8 +15642,9 @@ msgid "Select the regions under the range."
msgstr "Sélectionner les régions dans l'intervalle."
#: rc_option_editor.cc:3363
# extraspace needed to get a space before the semicolon
msgid "After a Split operation, in Object mode"
msgstr "Après une opération de Séparation, en mode Édition"
msgstr "Après une opération de Séparation, en mode Édition "
#: rc_option_editor.cc:3368
msgid "Clear the Region Selection"
@ -15670,12 +15688,14 @@ msgid "General Snap options:"
msgstr "Options générales de l'aimant :"
#: rc_option_editor.cc:3387
# extraspace needed to get a space before the semicolon
msgid "Snap Threshold (pixels)"
msgstr "Seuil de l'aimant (pixels)"
msgstr "Seuil de l'aimant (pixels) "
#: rc_option_editor.cc:3397
# extraspace needed to get a space before the semicolon
msgid "Approximate Grid/Ruler granularity (pixels)"
msgstr "Granularité approximative de la grille/règle (pixels)"
msgstr "Granularité approximative de la grille/règle (pixels) "
#: rc_option_editor.cc:3407
msgid "Show \"snapped cursor\""
@ -15705,8 +15725,9 @@ msgid "Snap Target Mode:"
msgstr "Mode cibles aimantées :"
#: rc_option_editor.cc:3449
# extraspace needed to get a space before the semicolon
msgid "When the Grid is enabled, snap to"
msgstr "Lorsque la grille est activée, aimanter dessus"
msgstr "Lorsque la grille est activée, aimanter dessus "
#: rc_option_editor.cc:3454
msgid "Snap Targets"
@ -15738,7 +15759,7 @@ msgstr "Éditeur/Touches spéciales"
#: rc_option_editor.cc:3500
msgid "Keyboard Modifiers"
msgstr "Touches Spéciales"
msgstr "Touches spéciales"
#: rc_option_editor.cc:3511
msgid "Allow non quarter-note pulse"
@ -15756,8 +15777,9 @@ msgstr ""
"minute"
#: rc_option_editor.cc:3524
# extraspace needed to get a space before the semicolon
msgid "Initial program change"
msgstr "Modifier le programme initial (IPC)"
msgstr "Modifier le programme initial (IPC) "
#: rc_option_editor.cc:3530
msgid "Editing"
@ -15780,8 +15802,9 @@ msgid "Sound MIDI notes as they are selected in the editor"
msgstr "Jouer les notes MIDI lorsqu'elles sont sélectionnées dans l'éditeur"
#: rc_option_editor.cc:3562
# extraspace needed to get a space before the semicolon
msgid "Virtual Keyboard Layout"
msgstr "Agencement du clavier virtuel"
msgstr "Agencement du clavier virtuel "
#: rc_option_editor.cc:3567
msgid "Mouse-only (no keyboard)"
@ -15820,16 +15843,19 @@ msgid "legal characters for MIDI note names|ABCDEFG#1234567890"
msgstr "ABCDEFG#1234567890"
#: rc_option_editor.cc:3581
# extraspace needed to get a space before the semicolon
msgid "Default lower visible MIDI note"
msgstr "Note MIDI inférieure visible par défaut"
msgstr "Note MIDI inférieure visible par défaut "
#: rc_option_editor.cc:3586
# extraspace needed to get a space before the semicolon
msgid "Default upper visible MIDI note"
msgstr "Note MIDI superieure visible par défaut"
msgstr "Note MIDI superieure visible par défaut "
#: rc_option_editor.cc:3591
# extraspace needed to get a space before the semicolon
msgid "Maximum note height"
msgstr "Hauteur maximum de note"
msgstr "Hauteur maximum de note "
#: rc_option_editor.cc:3600
msgid "MIDI Port Options"
@ -15841,7 +15867,7 @@ msgstr "L'entrée MIDI suit la sélection de piste MIDI"
#: rc_option_editor.cc:3610 rc_option_editor.cc:3611
msgid "MIDI/MIDI Port Config"
msgstr "Configuration de Port MIDI/MIDI"
msgstr "MIDI/Configuration de Port MIDI"
#: rc_option_editor.cc:3621
msgid "Prompt for new marker names"
@ -15892,9 +15918,10 @@ msgid ""
"<b>When disabled</b> master record will be disabled when the transport "
"transitions to stop."
msgstr ""
"<b>Si coché</b>, le rouge (master record) restera engagé en stoppant le "
"défilement.\n"
"<b>Si décoché</b>, le rouge sera désengagé en stoppant le défilement."
"<b>Si coché</b>, l'enregistrement général restera engagé lorsque le "
"transport passe à l'arrêt.\n"
"<b>Si décoché</b>, l'enregistrement général sera désengagé lorsque le "
"transport passe à l'arrêt.\n"
#: rc_option_editor.cc:3655
msgid "Reset default speed on stop"
@ -15979,8 +16006,9 @@ msgstr ""
"après les opérations de rembobinage/débobinage."
#: rc_option_editor.cc:3711
# extraspace needed to get a space before the semicolon
msgid "Preroll"
msgstr "Pré-roll"
msgstr "Pré-roll "
#: rc_option_editor.cc:3716
msgid ""
@ -16055,8 +16083,9 @@ msgstr ""
"stoppe puis annule la lecture en boucle"
#: rc_option_editor.cc:3748
# extraspace needed to get a space before the semicolon
msgid "Loop Fades"
msgstr "Fondus de boucle"
msgstr "Fondus de boucle "
#: rc_option_editor.cc:3752
msgid "No fades at loop boundaries"
@ -16118,12 +16147,13 @@ msgid "Respond to MMC commands"
msgstr "Réception des commandes MMC"
#: rc_option_editor.cc:3800
# extraspace needed to get a space before the semicolon
msgid "Inbound MMC device ID"
msgstr "Identifiant de l'appareil MMC en entrée"
msgstr "Identifiant de l'appareil MMC en entrée "
#: rc_option_editor.cc:3809
msgid "Show Transport Masters Window"
msgstr "Afficher la fenêtre du gestionnaire de transport"
msgstr "Afficher la fenêtre du transport général"
#: rc_option_editor.cc:3814
msgid "Match session video frame rate to external timecode"
@ -16221,8 +16251,9 @@ msgstr ""
"(tête) est immobile"
#: rc_option_editor.cc:3865
# extraspace needed to get a space before the semicolon
msgid "LTC generator level [dBFS]"
msgstr "Niveau [dBFS] du générateur LTC"
msgstr "Niveau [dBFS] du générateur LTC "
#: rc_option_editor.cc:3873
msgid ""
@ -16242,7 +16273,7 @@ msgstr "Activer le générateur MTC"
#: rc_option_editor.cc:3892
msgid "Max MTC varispeed (%)"
msgstr ""
msgstr "Varispeed MTC maxi (%s) "
#: rc_option_editor.cc:3897
msgid "Percentage either side of normal transport speed to transmit MTC."
@ -16255,8 +16286,9 @@ msgid "Send MMC commands"
msgstr "Envoi des commandes MMC"
#: rc_option_editor.cc:3913
# extraspace needed to get a space before the semicolon
msgid "Outbound MMC device ID"
msgstr "Identifiant de l'appareil MMC en sortie"
msgstr "Identifiant de l'appareil MMC en sortie "
#: rc_option_editor.cc:3919
msgid "MIDI Beat Clock (Mclk) Generator"
@ -16416,8 +16448,9 @@ msgstr ""
"graphique de greffon visibles est illimité"
#: rc_option_editor.cc:4038
# extraspace needed to get a space before the semicolon
msgid "Closing a Plugin GUI Window"
msgstr "Fermeture de la fenêtre d'interface graphique d'un greffon"
msgstr "Fermeture de la fenêtre d'interface graphique d'un greffon "
#: rc_option_editor.cc:4042
msgid "only hides the window"
@ -16642,22 +16675,22 @@ msgid "Plugin recent list length"
msgstr "Longueur de la liste des greffons récents"
#: rc_option_editor.cc:4310
# extraspace needed to get a space before the semicolon
msgid "Record monitoring handled by"
msgstr "Écoute de contrôle de l'enregistrement géré par"
msgstr "Écoute de contrôle de l'enregistrement géré par "
#: rc_option_editor.cc:4328
msgid "Auto Input does 'talkback'"
msgstr "Toujours écouter l'entrée des pistes"
#: rc_option_editor.cc:4334
#, fuzzy
msgid ""
"<b>When enabled</b>, and Transport -> Auto-Input is enabled, %1 will always "
"monitor audio inputs when transport is stopped, even if tracks aren't armed."
msgstr ""
"<b>Si coché</b>, et le bouton Entrée-auto allumé, %1 écoutera toujours "
"l'entrée des pistes audio à l'arrêt du défilement, même si les pistes ne "
"sont pas armées."
"<b>Si coché</b>, et que le bouton Transport -> Entrée-auto est activé, %1 "
"écoutera toujours les entrées audio lorsque le transport est arrêté, même "
"si les pistes ne sont pas armées."
#: rc_option_editor.cc:4341
msgid "Solo controls are Listen controls"
@ -16676,12 +16709,14 @@ msgid "Soloing overrides muting"
msgstr "Solo surplante muet"
#: rc_option_editor.cc:4375
# extraspace needed to get a space before the semicolon
msgid "Solo-in-place mute cut (dB)"
msgstr "Diminution (en dB) des pistes NON solo-en-place"
msgstr "Diminution (en dB) des pistes NON solo-en-place "
#: rc_option_editor.cc:4382
# extraspace needed to get a space before the semicolon
msgid "Listen Position"
msgstr "Position d'écoute"
msgstr "Position d'écoute "
#: rc_option_editor.cc:4387
msgid "after-fader (AFL)"
@ -16692,8 +16727,9 @@ msgid "pre-fader (PFL)"
msgstr "pré-atténuateur (PFL)"
#: rc_option_editor.cc:4394
# extraspace needed to get a space before the semicolon
msgid "PFL signals come from"
msgstr "Les signaux PFL sont prélevés"
msgstr "Les signaux PFL sont prélevés "
#: rc_option_editor.cc:4399
msgid "before pre-fader processors"
@ -16704,8 +16740,9 @@ msgid "pre-fader but after pre-fader processors"
msgstr "après les traitements pré-atténuateur"
#: rc_option_editor.cc:4406
# extraspace needed to get a space before the semicolon
msgid "AFL signals come from"
msgstr "Les signaux AFL sont prélevés"
msgstr "Les signaux AFL sont prélevés "
#: rc_option_editor.cc:4411
msgid "immediately post-fader"
@ -16721,11 +16758,12 @@ msgstr "Général"
#: rc_option_editor.cc:4422
msgid "Enable master-bus output gain control"
msgstr "Activer le contrôle de gain de sortie du bus maître"
msgstr "Activer le contrôle de gain de sortie du bus général"
#: rc_option_editor.cc:4429
# extraspace needed to get a space before the semicolon
msgid "I/O Resampler (vari-speed) quality"
msgstr "Qualité de rééchantillonage E/S (vari-speed)"
msgstr "Qualité de rééchantillonage E/S (vari-speed) "
#: rc_option_editor.cc:4434
msgid "Off (no vari-speed)"
@ -16832,7 +16870,7 @@ msgstr "Connexions piste et bus"
#: rc_option_editor.cc:4520
msgid "Auto-connect main output (master or monitor) bus to physical ports"
msgstr ""
"Connexion automatique du bus de sortie principal (master ou écoute de "
"Connexion automatique du bus de sortie principal (général ou écoute de "
"contrôle) aux ports physiques"
#: rc_option_editor.cc:4526
@ -16845,11 +16883,12 @@ msgstr ""
"<b>Si coché</b>, le bus de sortie principal est auto-connecté aux N premiers "
"ports physiques. Si la session comporte une section d'écoute de contrôle, "
"son bus de sortie est connecté aux ports matériels d'écoute, sinon c'est la "
"sortie du bus Master qui est directement utilisée pour la lecture."
"sortie du bus général qui est directement utilisée pour la lecture."
#: rc_option_editor.cc:4532
# extraspace needed to get a space before the semicolon
msgid "Connect track inputs"
msgstr "Connecter les entrées des pistes"
msgstr "Connecter les entrées des pistes "
#: rc_option_editor.cc:4537
msgid "automatically to physical inputs"
@ -16860,8 +16899,9 @@ msgid "manually"
msgstr "manuellement"
#: rc_option_editor.cc:4544
# extraspace needed to get a space before the semicolon
msgid "Connect track and bus outputs"
msgstr "Connecter les sorties de pistes et bus"
msgstr "Connecter les sorties de pistes et bus "
#: rc_option_editor.cc:4549
msgid "automatically to physical outputs"
@ -16900,8 +16940,9 @@ msgid "Meterbridge meters"
msgstr "Bandeau de mesure"
#: rc_option_editor.cc:4603
# extraspace needed to get a space before the semicolon
msgid "Peak hold time"
msgstr "Durée de maintien de crête"
msgstr "Durée de maintien de crête "
#: rc_option_editor.cc:4609
msgid "short"
@ -16916,8 +16957,9 @@ msgid "long"
msgstr "long"
#: rc_option_editor.cc:4617
# extraspace needed to get a space before the semicolon
msgid "DPM fall-off"
msgstr "Chute du pic"
msgstr "Chute du pic "
#: rc_option_editor.cc:4623
msgid "slowest [6.6dB/sec]"
@ -16944,8 +16986,9 @@ msgid "very fast [32dB/sec]"
msgstr "très rapide [32dB/sec]"
#: rc_option_editor.cc:4634
# extraspace needed to get a space before the semicolon
msgid "Meter line-up level; 0dBu"
msgstr "Niveau ligne, 0 dBu"
msgstr "Niveau ligne, 0 dBu "
#: rc_option_editor.cc:4639 rc_option_editor.cc:4655
msgid "-24dBFS (SMPTE US: 4dBu = -20dBFS)"
@ -16973,16 +17016,18 @@ msgstr ""
"et VU-mètre."
#: rc_option_editor.cc:4650
# extraspace needed to get a space before the semicolon
msgid "IEC1/DIN Meter line-up level; 0dBu"
msgstr "Niveau ligne IEC1/DIN, 0 dBu"
msgstr "Niveau ligne IEC1/DIN, 0 dBu "
#: rc_option_editor.cc:4660
msgid "Reference level for IEC1/DIN meter."
msgstr "Niveau de référence pour les indicateurs IEC1/DIN."
#: rc_option_editor.cc:4666
# extraspace needed to get a space before the semicolon
msgid "VU Meter standard"
msgstr "VU-mètre standard"
msgstr "VU-mètre standard "
#: rc_option_editor.cc:4671
msgid "0VU = -2dBu (France)"
@ -17001,8 +17046,9 @@ msgid "0VU = +8dBu"
msgstr "0VU = +8dBu"
#: rc_option_editor.cc:4679
# extraspace needed to get a space before the semicolon
msgid "Peak indicator threshold [dBFS]"
msgstr "Seuil de l'indicateur de pic [dBFS]"
msgstr "Seuil de l'indicateur de pic [dBFS] "
#: rc_option_editor.cc:4687
msgid ""
@ -17022,19 +17068,22 @@ msgid ""
"this will be when a new session is created."
msgstr ""
"Ces réglages s'appliquent aux pistes et bus nouvellement créés. Pour le bus "
"Master, ce sera à la création d'une nouvelle session."
"général, ce sera à la création d'une nouvelle session."
#: rc_option_editor.cc:4698
# extraspace needed to get a space before the semicolon
msgid "Default Meter Type for Master Bus"
msgstr "Type d'indicateur par défaut du bus Master"
msgstr "Type d'indicateur par défaut du bus général "
#: rc_option_editor.cc:4716
# extraspace needed to get a space before the semicolon
msgid "Default meter type for busses"
msgstr "Type d'indicateur par défaut des bus"
msgstr "Type d'indicateur par défaut des bus "
#: rc_option_editor.cc:4734
# extraspace needed to get a space before the semicolon
msgid "Default meter type for tracks"
msgstr "Type d'indicateur par défaut des pistes"
msgstr "Type d'indicateur par défaut des pistes "
#: rc_option_editor.cc:4750
msgid "Region Analysis"
@ -17057,8 +17106,9 @@ msgid "DSP CPU Utilization"
msgstr "Utilisation processeur par les traitements audio"
#: rc_option_editor.cc:4770
# extraspace needed to get a space before the semicolon
msgid "Signal processing uses"
msgstr "Le traitement du signal utilise"
msgstr "Le traitement du signal utilise "
#: rc_option_editor.cc:4775
msgid "all but one processor"
@ -17079,8 +17129,9 @@ msgid "This setting will only take effect when %1 is restarted."
msgstr "Cette option ne sera prise en compte qu'après un redémarrage d'%1."
#: rc_option_editor.cc:4792
# extraspace needed to get a space before the semicolon
msgid "Power Management, CPU DMA latency"
msgstr "Gestion de l'énergie, latence DMA du CPU"
msgstr "Gestion de l'énergie, latence DMA du CPU "
#: rc_option_editor.cc:4823
msgid "Lowest (prevent CPU sleep states)"
@ -17113,8 +17164,9 @@ msgid "Use DC bias to protect against denormals"
msgstr "Utiliser un courant polarisé (DC) pour éviter les dénormalisations"
#: rc_option_editor.cc:4853
# extraspace needed to get a space before the semicolon
msgid "Processor handling"
msgstr "Gestion du traitement"
msgstr "Gestion du traitement "
#: rc_option_editor.cc:4859
msgid "no processor handling"
@ -17147,8 +17199,9 @@ msgid "Memory Usage"
msgstr "Utilisation de la mémoire"
#: rc_option_editor.cc:4901
# extraspace needed to get a space before the semicolon
msgid "Waveform image cache size (megabytes)"
msgstr "Taille du cache d'images de signal (Mb)"
msgstr "Taille du cache d'images de signal (Mb) "
#: rc_option_editor.cc:4909
msgid ""
@ -17159,20 +17212,23 @@ msgstr ""
"de signal, ce qui peut impacter les performances graphiques."
#: rc_option_editor.cc:4917
# extraspace needed to get a space before the semicolon
msgid "Thinning factor (larger value => less data)"
msgstr "Facteur d'espacement (plus => moins de données)"
msgstr "Facteur d'espacement (plus => moins de données) "
#: rc_option_editor.cc:4926
# extraspace needed to get a space before the semicolon
msgid "Automation sampling interval (milliseconds)"
msgstr "Intervalle des points d'automation (msec)"
msgstr "Intervalle des points d'automation (msec) "
#: rc_option_editor.cc:4932
msgid "Automatables"
msgstr "Automatisables"
#: rc_option_editor.cc:4936
# extraspace needed to get a space before the semicolon
msgid "Limit automatable parameters per plugin"
msgstr "Limiter les paramètres d'automation par greffon"
msgstr "Limiter les paramètres d'automation par greffon "
#: rc_option_editor.cc:4943
msgid "256 parameters"
@ -17657,7 +17713,6 @@ msgid "Record enable"
msgstr "Armement"
#: route_group_dialog.cc:53
#, fuzzy
msgid "Surround Send enable"
msgstr "Activation du départ Surround"
@ -18004,7 +18059,6 @@ msgid "Main Outs"
msgstr "Sorties principales"
#: route_ui.cc:1479
#, fuzzy
msgid "Surround Send"
msgstr "Départ Surround"
@ -18901,7 +18955,7 @@ msgstr "Afficher les bus"
#: session_option_editor.cc:306
msgid "Include Master Bus"
msgstr "Inclure le bus Master"
msgstr "Inclure le bus général"
#: session_option_editor.cc:311
msgid "Button Area"
@ -19372,7 +19426,7 @@ msgstr "<b>Noms de pistes MIDI :</b>"
#: sfdb_ui.cc:1961
msgid "<b>Audio conversion quality:</b>"
msgstr "<b>Qualité de conversion ausio :</b>"
msgstr "<b>Qualité de conversion audio :</b>"
#: sfdb_ui.cc:1982 sfdb_ui.cc:2101
msgid "Best"
@ -19446,7 +19500,6 @@ msgid "> %+2d st"
msgstr "> %+2d st"
#: simple_export_dialog.cc:47
#, fuzzy
msgid "Surround Master Export"
msgstr "Exportation Surround Master"
@ -21717,7 +21770,7 @@ msgstr "Audio :"
#: export_video_dialog.cc:132
msgid "Master Bus"
msgstr "Bus master"
msgstr "Bus général"
#: export_video_dialog.cc:142
msgid "(default for codec)"
@ -21838,7 +21891,7 @@ msgstr ""
#: export_video_dialog.cc:608
msgid "Export Video: No Master Out Ports to Connect for Audio Export"
msgstr ""
"Export vidéo : aucun port de sortie principal auquel se connecter pour "
"Export vidéo : aucun port de sortie générale auquel se connecter pour "
"l'export audio"
#: export_video_dialog.cc:655
@ -22617,9 +22670,6 @@ msgstr "Fichier vidéo d'entrée"
#~ "\n"
#~ "Nous allons configurer le logiciel avant que vous ne l'utilisiez.</span> "
#~ msgid "GUI and Font scaling:"
#~ msgstr "Ajustement d'interface et de police : "
#~ msgid ""
#~ "Each project that you work on with %1 has its own folder.\n"
#~ "These can require a lot of disk space if you are recording audio.\n"
@ -23094,10 +23144,6 @@ msgstr "Fichier vidéo d'entrée"
#~ msgid "Transcoding Video.."
#~ msgstr "Transcodage vidéo.."
#, fuzzy
#~ msgid "Scale Video (W x H):"
#~ msgstr "Taille de vidéo (L x H) :"
#~ msgid "Retain Aspect"
#~ msgstr "Conserver l'aspect"
@ -23113,9 +23159,6 @@ msgstr "Fichier vidéo d'entrée"
#~ msgid "Codec Optimizations:"
#~ msgstr "Optimisations du codec :"
#~ msgid "Deinterlace"
#~ msgstr "Désentrelacer"
#~ msgid "Use [2] B-frames (MPEG 2 or 4 only)"
#~ msgstr "Choisir [2] B-frames (MPEG 2 ou 4 uniquement)"
@ -23469,26 +23512,6 @@ msgstr "Fichier vidéo d'entrée"
#~ "la boucle quand %1 atteint la fin, ce qui peut souvent causer un léger "
#~ "clic ou délai."
#~ msgid ""
#~ "Rules for closing, minimizing, maximizing, and stay-on-top can vary with "
#~ "each version of your OS, and the preferences that you've set in your OS.\n"
#~ "\n"
#~ "You can adjust the options, below, to change how %1's windows and dialogs "
#~ "behave.\n"
#~ "\n"
#~ "These settings will only take effect after %1 is restarted.\n"
#~ "\t"
#~ msgstr ""
#~ "Les règles pour fermer, minimiser, maximiser, and rester au-dessus "
#~ "varient selon la version de votre SO, et les préférences que vous avez "
#~ "réglées dans votre SO.\n"
#~ "\n"
#~ "Vous pouvez ajuster les options, ci-dessous, pour modifier le "
#~ "comportement des fenêtres et boites de dialogue d'%1.\n"
#~ "\n"
#~ "Ces réglages ne prendront effet qu'après un redémarrage d'%1.\n"
#~ "\t"
#~ msgid "destructive-xfade-seconds"
#~ msgstr "Secondes-de-fondu-destructif"

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

@ -588,6 +588,11 @@ public:
virtual void set_tempo_curve_range (double& max, double& min) const = 0;
virtual void start_track_drag (TimeAxisView&, int y, Gtk::Widget&) = 0;
virtual void mid_track_drag (GdkEventMotion*, Gtk::Widget&) = 0;
virtual void end_track_drag () = 0;
virtual bool track_dragging() const = 0;
/// Singleton instance, set up by Editor::Editor()
static PublicEditor* _instance;

View File

@ -3096,6 +3096,18 @@ These settings will only take effect after %1 is restarted.\n\
add_option (_("Appearance/Quirks"), bo);
#endif
#ifdef __APPLE__
BoolOption* bco = new BoolOption (
"use-cocoa-invalidation",
_("Use macOS to determine GUI redraw areas"),
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_cocoa_invalidation),
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_cocoa_invalidation)
);
Gtkmm2ext::UI::instance()->set_tip (bco->tip_widget(), string_compose (_("When enabled, macOS is in charge of what areas of the GUI are redrawn.\nWhen disabled, %1 manages this by itself"), PROGRAM_NAME));
add_option (_("Appearance/Quirks"), bco);
#endif
add_option (_("Appearance/Quirks"), new OptionEditorBlank ());
#if (!defined USE_CAIRO_IMAGE_SURFACE || defined CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE || defined __APPLE__)
add_option (_("Appearance"), new OptionEditorHeading (_("Graphics Acceleration")));
@ -4894,6 +4906,27 @@ These settings will only take effect after %1 is restarted.\n\
add_option (_("Performance"), new BufferingOptions (_rc_config));
if (hwcpus > 1) {
ComboOption<int32_t>* procs = new ComboOption<int32_t> (
"io-thread-count",
_("Disk I/O threads"),
sigc::mem_fun (*_rc_config, &RCConfiguration::get_io_thread_count),
sigc::mem_fun (*_rc_config, &RCConfiguration::set_io_thread_count)
);
procs->add (-2, _("all but two processor"));
procs->add (-1, _("all but one processor"));
procs->add (0, _("all available processors"));
for (uint32_t i = 1; i <= hwcpus; ++i) {
procs->add (i, string_compose (P_("%1 processor", "%1 processors", i), i));
}
procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
add_option (_("Performance"), procs);
}
/* Image cache size */
add_option (_("Performance"), new OptionEditorHeading (_("Memory Usage")));

View File

@ -340,20 +340,23 @@ RemainInfoBox::render (Cairo::RefPtr<Cairo::Context> const& cr, cairo_rectangle_
float remain_sec = samples / (float)sample_rate;
char buf[32];
bool at_least = FLAC == _session->config.get_native_file_header_format ();
const char* prefix = at_least ? u8"\u2265" : ""; // Greater-Than or Equal To
if (remain_sec > 86400) {
_layout_value->set_text (_(">24h"));
} else if (remain_sec > 32400 /* 9 hours */) {
snprintf (buf, sizeof (buf), "%.0f", remain_sec / 3600.f);
snprintf (buf, sizeof (buf), "%s%.0f", prefix, remain_sec / 3600.f);
_layout_value->set_text (std::string (buf) + S_("hours|h"));
} else if (remain_sec > 5940 /* 99 mins */) {
snprintf (buf, sizeof (buf), "%.1f", remain_sec / 3600.f);
snprintf (buf, sizeof (buf), "%s%.1f", prefix, remain_sec / 3600.f);
_layout_value->set_text (std::string (buf) + S_("hours|h"));
} else if (remain_sec > 60*3 /* 3 mins */) {
snprintf (buf, sizeof (buf), "%.0f", remain_sec / 60.f);
snprintf (buf, sizeof (buf), "%s%.0f", prefix, remain_sec / 60.f);
_layout_value->set_text (std::string (buf) + S_("minutes|m"));
} else {
Gtkmm2ext::set_source_rgb_a (cr, UIConfiguration::instance ().color ("alert:red"), .7);
snprintf (buf, sizeof (buf), "%.0f", remain_sec / 60.f);
snprintf (buf, sizeof (buf), "%s%.0f", prefix, remain_sec / 60.f);
_layout_value->set_text (std::string (buf) + S_("minutes|m"));
}
}

View File

@ -28,18 +28,31 @@
#include "pbd/memento_command.h"
#include "pbd/stateful_diff_command.h"
#include "pbd/unwind.h"
#include "gtkmm2ext/dndtreeview.h"
#include "widgets/tooltips.h"
#include "ardour/plugin_manager.h"
#include "ardour/region.h"
#include "ardour/region_fx_plugin.h"
#include "ardour/session.h"
#include "ardour/source.h"
#include "ardour_message.h"
#include "ardour_ui.h"
#include "clock_group.h"
#include "main_clock.h"
#include "context_menu_helper.h"
#include "gui_thread.h"
#include "keyboard.h"
#include "main_clock.h"
#include "mixer_ui.h"
#include "new_plugin_preset_dialog.h"
#include "region_editor.h"
#include "region_view.h"
#include "plugin_selector.h"
#include "plugin_window_proxy.h"
#include "public_editor.h"
#include "pbd/i18n.h"
@ -49,11 +62,11 @@ using namespace PBD;
using namespace std;
using namespace Gtkmm2ext;
RegionEditor::RegionEditor (Session* s, std::shared_ptr<Region> r)
RegionEditor::RegionEditor (Session* s, RegionView* rv)
: ArdourDialog (_("Region"))
, _table (9, 2)
, _table (9, 3)
, _table_row (0)
, _region (r)
, _region (rv->region ())
, name_label (_("Name:"))
, audition_button (_("Audition"))
, _clock_group (new ClockGroup)
@ -64,11 +77,12 @@ RegionEditor::RegionEditor (Session* s, std::shared_ptr<Region> r)
, sync_offset_absolute_clock (X_("regionsyncoffsetabsolute"), true, "", true, false)
/* XXX cannot file start yet */
, start_clock (X_("regionstart"), true, "", false, false)
, _region_fx_box (_region)
, _sources (1)
{
set_session (s);
switch (r->time_domain()) {
switch (_region->time_domain()) {
case Temporal::AudioTime:
/* XXX check length of region and choose samples or minsec */
_clock_group->set_clock_mode (AudioClock::MinSec);
@ -113,6 +127,8 @@ RegionEditor::RegionEditor (Session* s, std::shared_ptr<Region> r)
start_label.set_name ("RegionEditorLabel");
start_label.set_text (_("File start:"));
_sources_label.set_name ("RegionEditorLabel");
region_fx_label.set_text (_("Region Effects"));
region_fx_label.set_name ("RegionEditorLabel");
if (_region->sources().size() > 1) {
_sources_label.set_text (_("Sources:"));
@ -170,6 +186,9 @@ RegionEditor::RegionEditor (Session* s, std::shared_ptr<Region> r)
_table.attach (_sources, 1, 2, _table_row, _table_row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
++_table_row;
_table.attach (region_fx_label, 2, 3, 0, 1, Gtk::FILL, Gtk::FILL);
_table.attach (_region_fx_box, 2, 3, 1, _table_row + 2, Gtk::FILL, Gtk::FILL);
get_vbox()->pack_start (_table, true, true);
add_button (Gtk::Stock::CLOSE, Gtk::RESPONSE_ACCEPT);
@ -190,6 +209,9 @@ RegionEditor::RegionEditor (Session* s, std::shared_ptr<Region> r)
assert (t);
t->property_ellipsize() = Pango::ELLIPSIZE_END;
region_fx_label.set_no_show_all ();
_region_fx_box.set_no_show_all ();
show_all();
name_changed ();
@ -203,9 +225,16 @@ RegionEditor::RegionEditor (Session* s, std::shared_ptr<Region> r)
bounds_changed (change);
_region->PropertyChanged.connect (state_connection, invalidator (*this), boost::bind (&RegionEditor::region_changed, this, _1), gui_context());
_region->RegionFxChanged.connect (region_connection, invalidator (*this), boost::bind (&RegionEditor::region_fx_changed, this), gui_context ());
spin_arrow_grab = false;
/* for now only audio region effects are supported */
if (std::dynamic_pointer_cast<AudioRegion> (_region)) {
region_fx_label.show ();
_region_fx_box.show ();
}
connect_editor_events ();
}
@ -238,6 +267,12 @@ RegionEditor::region_changed (const PBD::PropertyChange& what_changed)
}
}
void
RegionEditor::region_fx_changed ()
{
_region_fx_box.redisplay_plugins ();
}
gint
RegionEditor::bpressed (GdkEventButton* ev, Gtk::SpinButton* /*but*/, void (RegionEditor::*/*pmf*/)())
{
@ -469,3 +504,541 @@ RegionEditor::handle_response (int)
{
hide ();
}
/* ****************************************************************************/
static std::list<Gtk::TargetEntry>
drop_targets ()
{
std::list<Gtk::TargetEntry> tmp;
tmp.push_back (Gtk::TargetEntry ("x-ardour/region-fx", Gtk::TARGET_SAME_APP)); // re-order
tmp.push_back (Gtk::TargetEntry ("x-ardour/plugin.info", Gtk::TARGET_SAME_APP)); // from plugin-manager
tmp.push_back (Gtk::TargetEntry ("x-ardour/plugin.favorite", Gtk::TARGET_SAME_APP)); // from sidebar
return tmp;
}
static std::list<Gtk::TargetEntry>
drag_targets ()
{
std::list<Gtk::TargetEntry> tmp;
tmp.push_back (Gtk::TargetEntry ("x-ardour/region-fx", Gtk::TARGET_SAME_APP)); // re-order
tmp.push_back (Gtk::TargetEntry ("x-ardour/plugin.preset", Gtk::TARGET_SAME_APP)); // to sidebar (optional preset)
return tmp;
}
RegionEditor::RegionFxBox::RegionFxBox (std::shared_ptr<ARDOUR::Region> r)
: _region (r)
, _display (drop_targets ())
, _no_redisplay (false)
, _placement (-1)
{
_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
_scroller.set_name ("ProcessorScroller");
_scroller.add (_display);
pack_start (_scroller, true, true);
_display.set_can_focus ();
_display.set_name ("ProcessorList");
_display.set_data ("regionfxbox", this);
_display.set_size_request (104, -1); // TODO UI scale
_display.set_spacing (0);
_display.ButtonPress.connect (sigc::mem_fun (*this, &RegionFxBox::fxe_button_press_event));
_display.ButtonRelease.connect (sigc::mem_fun (*this, &RegionFxBox::fxe_button_release_event));
_display.Reordered.connect (sigc::mem_fun (*this, &RegionFxBox::reordered));
_display.DropFromAnotherBox.connect (sigc::mem_fun (*this, &RegionFxBox::object_drop));
_display.DropFromExternal.connect (sigc::mem_fun (*this, &RegionFxBox::plugin_drop));
_display.signal_key_press_event ().connect (sigc::mem_fun (*this, &RegionFxBox::on_key_press), false);
_scroller.show ();
_display.show ();
redisplay_plugins ();
}
bool
RegionEditor::RegionFxBox::use_plugins (SelectedPlugins const& plugins)
{
int errors = 0;
{
PBD::Unwinder<bool> uw (_no_redisplay, true);
for (auto const& p : plugins) {
std::shared_ptr<RegionFxPlugin> pos;
if (_placement >= 0) {
pos = _region->nth_plugin (_placement++);
}
if (!_region->add_plugin (std::shared_ptr<RegionFxPlugin> (new RegionFxPlugin (_region->session (), _region->time_domain (), p)), pos)) {
++errors;
}
}
}
redisplay_plugins ();
if (errors) {
notify_plugin_load_fail (errors);
}
return false;
}
void
RegionEditor::RegionFxBox::redisplay_plugins ()
{
if (_no_redisplay) {
return;
}
_display.clear ();
_region->foreach_plugin (sigc::mem_fun (*this, &RegionFxBox::add_fx_to_display));
}
void
RegionEditor::RegionFxBox::add_fx_to_display (std::weak_ptr<RegionFxPlugin> wfx)
{
std::shared_ptr<RegionFxPlugin> fx (wfx.lock ());
if (!fx) {
return;
}
RegionFxEntry* e = new RegionFxEntry (fx);
_display.add_child (e, drag_targets ());
}
bool
RegionEditor::RegionFxBox::fxe_button_press_event (GdkEventButton* ev, RegionFxEntry* child)
{
if (child) {
std::weak_ptr<RegionFxPlugin> wfx (std::weak_ptr<RegionFxPlugin> (child->region_fx_plugin ()));
if (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS)) {
if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
show_plugin_gui (wfx, false);
} else {
show_plugin_gui (wfx, true);
}
return true;
}
if (Keyboard::is_context_menu_event (ev)) {
using namespace Gtk::Menu_Helpers;
PluginSelector* ps = Mixer_UI::instance ()->plugin_selector ();
ps->set_interested_object (*this);
Gtk::Menu* m = ARDOUR_UI_UTILS::shared_popup_menu ();
MenuList& items = m->items ();
items.push_back (MenuElem (_("New Plugin")));
Gtk::MenuItem& npm = items.back ();
npm.set_submenu (*ps->plugin_menu ());
std::shared_ptr<Plugin> plugin = child->region_fx_plugin ()->plugin ();
items.push_back (SeparatorElem ());
items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &RegionFxBox::show_plugin_gui), wfx, true)));
items.back ().set_sensitive (plugin->has_editor ());
items.push_back (MenuElem (_("Edit with generic controls..."), sigc::bind (sigc::mem_fun (*this, &RegionFxBox::show_plugin_gui), wfx, false)));
Gtk::Menu* automation_menu = manage (new Gtk::Menu);
MenuList& ac_items (automation_menu->items ());
for (size_t i = 0; i < plugin->parameter_count (); ++i) {
if (!plugin->parameter_is_control (i) || !plugin->parameter_is_input (i)) {
continue;
}
const Evoral::Parameter param (PluginAutomation, 0, i);
std::string label = plugin->describe_parameter (param);
if (label == X_("latency") || label == X_("hidden")) {
continue;
}
std::shared_ptr<ARDOUR::AutomationControl> c (std::dynamic_pointer_cast<ARDOUR::AutomationControl> (child->region_fx_plugin ()->control (param)));
if (c && c->flags () & (Controllable::HiddenControl | Controllable::NotAutomatable)) {
continue;
}
std::weak_ptr<ARDOUR::AutomationControl> wac (c);
bool play = c->automation_state () == Play;
ac_items.push_back (CheckMenuElem (label));
Gtk::CheckMenuItem* cmi = static_cast<Gtk::CheckMenuItem*> (&ac_items.back ());
cmi->set_active (play);
cmi->signal_activate ().connect ([wac, play] () {
std::shared_ptr<ARDOUR::AutomationControl> ac = wac.lock ();
if (ac) {
ac->set_automation_state (play ? ARDOUR::Off : Play);
}
});
}
if (!ac_items.empty ()) {
items.push_back (SeparatorElem ());
items.push_back (MenuElem ("Automation Enable", *automation_menu));
} else {
delete automation_menu;
}
items.push_back (SeparatorElem ());
items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &RegionFxBox::queue_delete_region_fx), wfx)));
m->signal_unmap ().connect ([this, &npm] () { npm.remove_submenu (); _display.remove_placeholder (); });
m->popup (ev->button, ev->time);
int x, y;
_display.get_pointer (x, y);
_placement = _display.add_placeholder (y);
return true;
}
return false;
}
if (Keyboard::is_context_menu_event (ev)) {
_placement = -1;
using namespace Gtk::Menu_Helpers;
PluginSelector* ps = Mixer_UI::instance ()->plugin_selector ();
ps->set_interested_object (*this);
Gtk::Menu* m = ARDOUR_UI_UTILS::shared_popup_menu ();
MenuList& items = m->items ();
items.push_back (MenuElem (_("New Plugin")));
Gtk::MenuItem& npm = items.back ();
npm.set_submenu (*ps->plugin_menu ());
m->signal_unmap ().connect ([&npm] () { npm.remove_submenu (); });
m->popup (ev->button, ev->time);
return true;
} else if (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS) {
_placement = -1;
PluginSelector* ps = Mixer_UI::instance ()->plugin_selector ();
ps->set_interested_object (*this);
ps->show_manager ();
return true;
}
return false;
}
bool
RegionEditor::RegionFxBox::fxe_button_release_event (GdkEventButton* ev, RegionFxEntry* child)
{
if (child && Keyboard::is_delete_event (ev)) {
queue_delete_region_fx (std::weak_ptr<RegionFxPlugin> (child->region_fx_plugin ()));
}
return false;
}
bool
RegionEditor::RegionFxBox::on_key_press (GdkEventKey* ev)
{
switch (ev->keyval) {
case GDK_KEY_Delete:
break;
case GDK_KEY_BackSpace:
break;
default:
return false;
}
for (auto const& i : _display.selection (true)) {
queue_delete_region_fx (std::weak_ptr<RegionFxPlugin> (i->region_fx_plugin ()));
}
return true;
}
void
RegionEditor::RegionFxBox::reordered ()
{
Region::RegionFxList fxl;
for (auto const& i : _display.children ()) {
fxl.push_back (i->region_fx_plugin ());
}
_region->reorder_plugins (fxl);
}
void
RegionEditor::RegionFxBox::queue_delete_region_fx (std::weak_ptr<ARDOUR::RegionFxPlugin> wfx)
{
Glib::signal_idle ().connect (sigc::bind (sigc::mem_fun (*this, &RegionFxBox::idle_delete_region_fx), wfx));
}
bool
RegionEditor::RegionFxBox::idle_delete_region_fx (std::weak_ptr<RegionFxPlugin> wfx)
{
std::shared_ptr<RegionFxPlugin> fx (wfx.lock ());
if (!fx) {
return false;
}
_region->remove_plugin (fx);
return false;
}
void
RegionEditor::RegionFxBox::notify_plugin_load_fail (uint32_t cnt)
{
assert (cnt > 0);
ArdourMessageDialog (_("Failed to load Region Effect Plugin"), false, Gtk::MESSAGE_ERROR).run ();
}
std::shared_ptr<RegionFxPlugin>
RegionEditor::RegionFxBox::find_drop_position (RegionFxEntry* pos)
{
std::shared_ptr<RegionFxPlugin> rv;
if (pos) {
rv = pos->region_fx_plugin ();
if (!rv) {
rv = _display.children ().front ()->region_fx_plugin ();
}
}
return rv;
}
void
RegionEditor::RegionFxBox::plugin_drop (Gtk::SelectionData const& data, RegionFxEntry* pos, Glib::RefPtr<Gdk::DragContext> const& context)
{
uint32_t errors = 0;
std::shared_ptr<RegionFxPlugin> at = find_drop_position (pos);
if (data.get_target () == "x-ardour/plugin.info") {
const void* d = data.get_data ();
const Gtkmm2ext::DnDTreeView<ARDOUR::PluginInfoPtr>* tv = reinterpret_cast<const Gtkmm2ext::DnDTreeView<ARDOUR::PluginInfoPtr>*> (d);
PluginInfoList nfos;
Gtk::TreeView* source;
tv->get_object_drag_data (nfos, &source);
for (auto const& i : nfos) {
PluginPtr p = (i)->load (_region->session ());
if (!_region->add_plugin (std::shared_ptr<RegionFxPlugin> (new RegionFxPlugin (_region->session (), _region->time_domain (), p)), at)) {
++errors;
}
}
} else if (data.get_target () == "x-ardour/plugin.favorite") {
const void* d = data.get_data ();
const Gtkmm2ext::DnDTreeView<ARDOUR::PluginPresetPtr>* tv = reinterpret_cast<const Gtkmm2ext::DnDTreeView<ARDOUR::PluginPresetPtr>*> (d);
PluginPresetList nfos;
Gtk::TreeView* source;
tv->get_object_drag_data (nfos, &source);
for (auto const& i : nfos) {
PluginPresetPtr ppp (i);
PluginInfoPtr pip = ppp->_pip;
PluginPtr p = pip->load (_region->session ());
if (!p) {
continue;
}
if (ppp->_preset.valid) {
p->load_preset (ppp->_preset);
}
if (!_region->add_plugin (std::shared_ptr<RegionFxPlugin> (new RegionFxPlugin (_region->session (), _region->time_domain (), p)), at)) {
++errors;
}
}
}
if (errors) {
notify_plugin_load_fail (errors);
}
}
void
RegionEditor::RegionFxBox::delete_dragged_plugins (Region::RegionFxList const& fxl)
{
{
PBD::Unwinder<bool> uw (_no_redisplay, true);
for (auto const& fx : fxl) {
_region->remove_plugin (fx);
}
}
redisplay_plugins ();
}
void
RegionEditor::RegionFxBox::object_drop (Gtkmm2ext::DnDVBox<RegionFxEntry>* source, RegionFxEntry* pos, Glib::RefPtr<Gdk::DragContext> const& context)
{
if (Gdk::ACTION_LINK == context->get_selected_action ()) {
std::list<RegionFxEntry*> children = source->selection ();
assert (children.size () == 1);
RegionFxEntry* other = *children.begin ();
assert (other->can_copy_state (pos));
std::shared_ptr<ARDOUR::RegionFxPlugin> othr = other->region_fx_plugin ();
std::shared_ptr<ARDOUR::RegionFxPlugin> self = pos->region_fx_plugin ();
PBD::ID id = self->id ();
XMLNode& state = othr->get_state ();
state.remove_property ("count");
/* Controllable and automation IDs should not be copied */
PBD::Stateful::ForceIDRegeneration force_ids;
self->set_state (state, Stateful::current_state_version);
self->update_id (id);
return;
}
std::shared_ptr<RegionFxPlugin> at = find_drop_position (pos);
uint32_t errors = 0;
Region::RegionFxList fxl;
for (auto const& i : source->selection (true)) {
fxl.push_back (i->region_fx_plugin ());
}
for (auto const& i : fxl) {
XMLNode& state = i->get_state ();
state.remove_property ("count");
PBD::Stateful::ForceIDRegeneration force_ids;
std::shared_ptr<RegionFxPlugin> rfx (new RegionFxPlugin (_region->session (), _region->time_domain ()));
rfx->set_state (state, Stateful::current_state_version);
if (!_region->add_plugin (rfx, at)) {
++errors;
}
delete &state;
}
if ((context->get_suggested_action () == Gdk::ACTION_MOVE) && source) {
RegionFxBox* other = reinterpret_cast<RegionFxBox*> (source->get_data ("regionfxbox"));
if (other) {
other->delete_dragged_plugins (fxl);
}
}
if (errors) {
notify_plugin_load_fail (errors);
}
}
void
RegionEditor::RegionFxBox::show_plugin_gui (std::weak_ptr<RegionFxPlugin> wfx, bool custom_ui)
{
std::shared_ptr<RegionFxPlugin> rfx (wfx.lock ());
if (!rfx) {
return;
}
PluginWindowProxy* pwp;
if (rfx->window_proxy ()) {
pwp = dynamic_cast<PluginWindowProxy*> (rfx->window_proxy ());
} else {
pwp = new PluginWindowProxy (string_compose ("RFX-%1", rfx->id ()), _region->name (), rfx);
const XMLNode* ui_xml = rfx->session ().extra_xml (X_("UI"));
if (ui_xml) {
pwp->set_state (*ui_xml, 0);
}
rfx->set_window_proxy (pwp);
WM::Manager::instance ().register_window (pwp);
RegionView* rv = PublicEditor::instance ().regionview_from_region (_region);
rv->RegionViewGoingAway.connect_same_thread (*pwp, [pwp] (RegionView*) { pwp->hide (); });
}
pwp->set_custom_ui_mode (custom_ui);
pwp->show_the_right_window ();
Gtk::Window* tlw = PublicEditor::instance ().current_toplevel ();
if (tlw) {
pwp->set_transient_for (*tlw);
}
}
/* ****************************************************************************/
RegionEditor::RegionFxEntry::RegionFxEntry (std::shared_ptr<RegionFxPlugin> rfx)
: _fx_btn (ArdourWidgets::ArdourButton::default_elements)
, _rfx (rfx)
{
_box.pack_start (_fx_btn, true, true);
_plugin_preset_pointer = PluginPresetPtr (new PluginPreset (rfx->plugin ()->get_info ()));
_fx_btn.set_fallthrough_to_parent (true);
_fx_btn.set_text (name ());
_fx_btn.set_active (true);
_fx_btn.set_name ("processor postfader");
if (rfx->plugin ()->has_editor ()) {
set_tooltip (_fx_btn, string_compose (_("<b>%1</b>\nDouble-click to show GUI.\n%2+double-click to show generic GUI."), name (), Keyboard::secondary_modifier_name ()));
} else {
set_tooltip (_fx_btn, string_compose (_("<b>%1</b>\nDouble-click to show generic GUI."), name ()));
}
_box.show ();
_fx_btn.show ();
}
std::string
RegionEditor::RegionFxEntry::name () const
{
return _rfx->name ();
}
bool
RegionEditor::RegionFxEntry::can_copy_state (Gtkmm2ext::DnDVBoxChild* o) const
{
RegionFxEntry* other = dynamic_cast<RegionFxEntry*> (o);
if (!other) {
return false;
}
std::shared_ptr<ARDOUR::RegionFxPlugin> othr = other->region_fx_plugin ();
std::shared_ptr<ARDOUR::RegionFxPlugin> self = region_fx_plugin ();
if (self->type () != othr->type ()) {
return false;
}
std::shared_ptr<Plugin> my_p = self->plugin ();
std::shared_ptr<Plugin> ot_p = othr->plugin ();
return my_p->unique_id () == ot_p->unique_id ();
}
void
RegionEditor::RegionFxEntry::set_visual_state (Gtkmm2ext::VisualState s, bool yn)
{
if (yn) {
_fx_btn.set_visual_state (Gtkmm2ext::VisualState (_fx_btn.visual_state () | s));
} else {
_fx_btn.set_visual_state (Gtkmm2ext::VisualState (_fx_btn.visual_state () & ~s));
}
}
bool
RegionEditor::RegionFxEntry::drag_data_get (Glib::RefPtr<Gdk::DragContext> const, Gtk::SelectionData& data)
{
/* compare to ProcessorEntry::drag_data_get */
if (data.get_target () != "x-ardour/plugin.preset") {
return false;
}
std::shared_ptr<Plugin> plugin = _rfx->plugin ();
assert (plugin);
PluginManager& manager (PluginManager::instance ());
bool fav = manager.get_status (_plugin_preset_pointer->_pip) == PluginManager::Favorite;
NewPluginPresetDialog d (plugin, string_compose (_("New Favorite Preset for \"%1\""), _plugin_preset_pointer->_pip->name), !fav);
_plugin_preset_pointer->_preset.valid = false;
switch (d.run ()) {
default:
case Gtk::RESPONSE_CANCEL:
data.set (data.get_target (), 8, NULL, 0);
return true;
break;
case Gtk::RESPONSE_NO:
break;
case Gtk::RESPONSE_ACCEPT:
if (d.name ().empty ()) {
break;
}
if (d.replace ()) {
plugin->remove_preset (d.name ());
}
Plugin::PresetRecord const r = plugin->save_preset (d.name ());
if (!r.uri.empty ()) {
_plugin_preset_pointer->_preset.uri = r.uri;
_plugin_preset_pointer->_preset.label = r.label;
_plugin_preset_pointer->_preset.user = r.user;
_plugin_preset_pointer->_preset.valid = r.valid;
}
}
data.set (data.get_target (), 8, (const guchar*)&_plugin_preset_pointer, sizeof (PluginPresetPtr));
return true;
}

View File

@ -27,6 +27,7 @@
#include <gtkmm/label.h>
#include <gtkmm/entry.h>
#include <gtkmm/box.h>
#include <gtkmm/eventbox.h>
#include <gtkmm/togglebutton.h>
#include <gtkmm/button.h>
#include <gtkmm/arrow.h>
@ -36,34 +37,100 @@
#include <gtkmm/separator.h>
#include <gtkmm/spinbutton.h>
#include <gtkmm/listviewtext.h>
#include <gtkmm/scrolledwindow.h>
#include "gtkmm2ext/dndtreeview.h"
#include "gtkmm2ext/dndvbox.h"
#include "pbd/signals.h"
#include "audio_clock.h"
#include "ardour_dialog.h"
#include "plugin_interest.h"
#include "region_editor.h"
namespace ARDOUR {
class Region;
class Session;
class RegionFxPlugin;
}
class RegionView;
class ClockGroup;
class RegionEditor : public ArdourDialog
{
public:
RegionEditor (ARDOUR::Session*, std::shared_ptr<ARDOUR::Region>);
RegionEditor (ARDOUR::Session*, RegionView*);
virtual ~RegionEditor ();
protected:
virtual void region_changed (const PBD::PropertyChange&);
virtual void region_fx_changed ();
Gtk::Table _table;
int _table_row;
private:
class RegionFxEntry : public Gtkmm2ext::DnDVBoxChild, public sigc::trackable
{
public:
RegionFxEntry (std::shared_ptr<ARDOUR::RegionFxPlugin>);
Gtk::EventBox& action_widget () { return _fx_btn; }
Gtk::Widget& widget () { return _box; }
std::string drag_text () const { return name (); }
bool is_selectable() const { return true; }
bool can_copy_state (Gtkmm2ext::DnDVBoxChild*) const;
void set_visual_state (Gtkmm2ext::VisualState, bool);
bool drag_data_get (Glib::RefPtr<Gdk::DragContext> const, Gtk::SelectionData &);
std::shared_ptr<ARDOUR::RegionFxPlugin> region_fx_plugin () const { return _rfx; }
private:
std::string name () const;
Gtk::VBox _box;
ArdourWidgets::ArdourButton _fx_btn;
std::shared_ptr<ARDOUR::RegionFxPlugin> _rfx;
ARDOUR::PluginPresetPtr _plugin_preset_pointer;
};
class RegionFxBox : public Gtk::VBox, public PluginInterestedObject //, public ARDOUR::SessionHandlePtr
{
public:
RegionFxBox (std::shared_ptr<ARDOUR::Region>);
void redisplay_plugins ();
private:
void add_fx_to_display (std::weak_ptr<ARDOUR::RegionFxPlugin>);
void show_plugin_gui (std::weak_ptr<ARDOUR::RegionFxPlugin>, bool custom_ui = true);
void queue_delete_region_fx (std::weak_ptr<ARDOUR::RegionFxPlugin>);
bool idle_delete_region_fx (std::weak_ptr<ARDOUR::RegionFxPlugin>);
void notify_plugin_load_fail (uint32_t cnt = 1);
bool on_key_press (GdkEventKey*);
/* PluginInterestedObject */
bool use_plugins (SelectedPlugins const&);
/* DNDVbox signal handlers */
bool fxe_button_press_event (GdkEventButton*, RegionFxEntry*);
bool fxe_button_release_event (GdkEventButton*, RegionFxEntry*);
void reordered ();
void plugin_drop (Gtk::SelectionData const&, RegionFxEntry*, Glib::RefPtr<Gdk::DragContext> const&);
void object_drop (Gtkmm2ext::DnDVBox<RegionFxEntry>*, RegionFxEntry*, Glib::RefPtr<Gdk::DragContext> const&);
void delete_dragged_plugins (std::list<std::shared_ptr<ARDOUR::RegionFxPlugin>> const&);
std::shared_ptr<ARDOUR::RegionFxPlugin> find_drop_position (RegionFxEntry*);
std::shared_ptr<ARDOUR::Region> _region;
Gtkmm2ext::DnDVBox<RegionFxEntry> _display;
Gtk::ScrolledWindow _scroller;
Gtk::EventBox _base;
bool _no_redisplay;
int _placement;
};
std::shared_ptr<ARDOUR::Region> _region;
void connect_editor_events ();
@ -78,6 +145,7 @@ private:
Gtk::Label sync_relative_label;
Gtk::Label sync_absolute_label;
Gtk::Label start_label;
Gtk::Label region_fx_label;
ClockGroup* _clock_group;
@ -88,8 +156,11 @@ private:
AudioClock sync_offset_absolute_clock; ///< sync offset relative to the start of the timeline
AudioClock start_clock;
RegionFxBox _region_fx_box;
PBD::ScopedConnection state_connection;
PBD::ScopedConnection audition_connection;
PBD::ScopedConnection region_connection;
void bounds_changed (const PBD::PropertyChange&);
void name_changed ();

View File

@ -0,0 +1,92 @@
/*
* 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
* 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 "ardour/automation_control.h"
#include "audio_region_view.h"
#include "gui_thread.h"
#include "region_fx_line.h"
#include "pbd/i18n.h"
using namespace ARDOUR;
RegionFxLine::RegionFxLine (std::string const& name, RegionView& r, ArdourCanvas::Container& parent, std::shared_ptr<AutomationList> l, ParameterDescriptor const& d)
: AutomationLine (name, r.get_time_axis_view(), parent, l, d)
, _rv (r)
{
init ();
}
RegionFxLine::RegionFxLine (std::string const& name, RegionView& r, ArdourCanvas::Container& parent, std::shared_ptr<ARDOUR::AutomationControl> ac)
: AutomationLine (name, r.get_time_axis_view(), parent, ac->alist (), ac->desc ())
, _rv (r)
, _ac (ac)
{
init ();
}
void
RegionFxLine::init ()
{
_rv.region()->PropertyChanged.connect (_region_changed_connection, invalidator (*this), boost::bind (&RegionFxLine::region_changed, this, _1), gui_context());
group->raise_to_top ();
group->set_y_position (2);
}
Temporal::timepos_t
RegionFxLine::get_origin() const
{
return _rv.region()->position();
}
void
RegionFxLine::enable_autoation ()
{
std::shared_ptr<AutomationControl> ac = _ac.lock ();
if (ac) {
ac->set_automation_state (Play);
}
}
void
RegionFxLine::end_drag (bool with_push, uint32_t final_index)
{
enable_autoation ();
AutomationLine::end_drag (with_push, final_index);
}
void
RegionFxLine::end_draw_merge ()
{
enable_autoation ();
AutomationLine::end_draw_merge ();
}
void
RegionFxLine::region_changed (PBD::PropertyChange const& what_changed)
{
PBD::PropertyChange interesting_stuff;
interesting_stuff.add (ARDOUR::Properties::start);
interesting_stuff.add (ARDOUR::Properties::length);
if (what_changed.contains (interesting_stuff)) {
reset ();
}
}

View File

@ -0,0 +1,50 @@
/*
* 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
* 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 __ardour_gtk_region_fx_line_h__
#define __ardour_gtk_region_fx_line_h__
#include "automation_line.h"
class RegionView;
class RegionFxLine : public AutomationLine
{
public:
RegionFxLine (std::string const&, RegionView&, ArdourCanvas::Container&, std::shared_ptr<ARDOUR::AutomationList>, ARDOUR::ParameterDescriptor const&);
RegionFxLine (std::string const&, RegionView&, ArdourCanvas::Container&, std::shared_ptr<ARDOUR::AutomationControl>);
Temporal::timepos_t get_origin() const;
RegionView& region_view () { return _rv; }
void end_drag (bool with_push, uint32_t final_index);
void end_draw_merge ();
virtual void enable_autoation ();
private:
void init ();
void region_changed (PBD::PropertyChange const&);
RegionView& _rv;
std::weak_ptr<ARDOUR::AutomationControl> _ac;
PBD::ScopedConnection _region_changed_connection;
};
#endif

View File

@ -35,45 +35,52 @@
#include "time_axis_view.h"
#include "editor.h"
#include "gui_thread.h"
#include "pbd/i18n.h"
using namespace std;
using namespace ARDOUR;
using namespace PBD;
AudioRegionGainLine::AudioRegionGainLine (const string & name, AudioRegionView& r, ArdourCanvas::Container& parent, std::shared_ptr<AutomationList> l)
: AutomationLine (name, r.get_time_axis_view(), parent, l, l->parameter())
, rv (r)
: RegionFxLine (name, r, parent, l, l->parameter ())
, arv (r)
{
// If this isn't true something is horribly wrong, and we'll get catastrophic gain values
assert(l->parameter().type() == EnvelopeAutomation);
r.region()->PropertyChanged.connect (_region_changed_connection, invalidator (*this), boost::bind (&AudioRegionGainLine::region_changed, this, _1), gui_context());
group->raise_to_top ();
group->set_y_position (2);
terminal_points_can_slide = false;
}
timepos_t
AudioRegionGainLine::get_origin() const
{
return rv.region()->position();
}
void
AudioRegionGainLine::start_drag_single (ControlPoint* cp, double x, float fraction)
{
AutomationLine::start_drag_single (cp, x, fraction);
RegionFxLine::start_drag_single (cp, x, fraction);
// XXX Stateful need to capture automation curve data
if (!rv.audio_region()->envelope_active()) {
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0));
rv.audio_region()->set_envelope_active(false);
if (!arv.audio_region()->envelope_active()) {
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(arv.audio_region().get()), &arv.audio_region()->get_state(), 0));
arv.audio_region()->set_envelope_active(false);
}
}
void
AudioRegionGainLine::start_drag_line (uint32_t i1, uint32_t i2, float fraction)
{
RegionFxLine::start_drag_line (i1, i2, fraction);
if (!arv.audio_region()->envelope_active()) {
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(arv.audio_region().get()), &arv.audio_region()->get_state(), 0));
arv.audio_region()->set_envelope_active(false);
}
}
void
AudioRegionGainLine::start_drag_multiple (list<ControlPoint*> cp, float fraction, XMLNode* state)
{
RegionFxLine::start_drag_multiple (cp, fraction, state);
if (!arv.audio_region()->envelope_active()) {
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(arv.audio_region().get()), &arv.audio_region()->get_state(), 0));
arv.audio_region()->set_envelope_active(false);
}
}
@ -84,10 +91,10 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
trackview.editor().begin_reversible_command (_("remove control point"));
XMLNode &before = alist->get_state();
if (!rv.audio_region()->envelope_active()) {
rv.audio_region()->clear_changes ();
rv.audio_region()->set_envelope_active(true);
trackview.session()->add_command(new StatefulDiffCommand (rv.audio_region()));
if (!arv.audio_region()->envelope_active()) {
arv.audio_region()->clear_changes ();
arv.audio_region()->set_envelope_active(true);
trackview.session()->add_command(new PBD::StatefulDiffCommand (arv.audio_region()));
}
trackview.editor ().get_selection ().clear_points ();
@ -101,23 +108,27 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
void
AudioRegionGainLine::end_drag (bool with_push, uint32_t final_index)
{
if (!rv.audio_region()->envelope_active()) {
rv.audio_region()->set_envelope_active(true);
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(rv.audio_region().get()), 0, &rv.audio_region()->get_state()));
if (!arv.audio_region()->envelope_active()) {
arv.audio_region()->set_envelope_active(true);
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(arv.audio_region().get()), 0, &arv.audio_region()->get_state()));
}
AutomationLine::end_drag (with_push, final_index);
RegionFxLine::end_drag (with_push, final_index);
}
void
AudioRegionGainLine::region_changed (const PropertyChange& what_changed)
AudioRegionGainLine::end_draw_merge ()
{
PropertyChange interesting_stuff;
enable_autoation ();
RegionFxLine::end_draw_merge ();
}
interesting_stuff.add (ARDOUR::Properties::start);
interesting_stuff.add (ARDOUR::Properties::length);
if (what_changed.contains (interesting_stuff)) {
reset ();
void
AudioRegionGainLine::enable_autoation ()
{
if (!arv.audio_region()->envelope_active()) {
XMLNode& before = arv.audio_region()->get_state();
arv.audio_region()->set_envelope_active(true);
trackview.session()->add_command(new MementoCommand<AudioRegion>(*(arv.audio_region().get()), &before, &arv.audio_region()->get_state()));
}
}

View File

@ -27,8 +27,7 @@
#include "ardour/ardour.h"
#include "automation_line.h"
#include "region_fx_line.h"
namespace ARDOUR {
class Session;
@ -37,23 +36,21 @@ namespace ARDOUR {
class TimeAxisView;
class AudioRegionView;
class AudioRegionGainLine : public AutomationLine
class AudioRegionGainLine : public RegionFxLine
{
public:
AudioRegionGainLine (const std::string & name, AudioRegionView&, ArdourCanvas::Container& parent, std::shared_ptr<ARDOUR::AutomationList>);
Temporal::timepos_t get_origin() const;
void start_drag_single (ControlPoint*, double, float);
void start_drag_line (uint32_t, uint32_t, float);
void start_drag_multiple (std::list<ControlPoint*>, float, XMLNode*);
void end_drag (bool with_push, uint32_t final_index);
void end_draw_merge ();
void enable_autoation ();
void remove_point (ControlPoint&);
AudioRegionView& region_view () { return rv; }
private:
PBD::ScopedConnection _region_changed_connection;
void region_changed (const PBD::PropertyChange& what_changed);
AudioRegionView& rv;
AudioRegionView& arv;
};
#endif /* __ardour_gtk_region_gain_line_h__ */

View File

@ -237,6 +237,7 @@ RegionView::init (bool wfd)
//set_height (trackview.current_height());
_region->PropertyChanged.connect (*this, invalidator (*this), boost::bind (&RegionView::region_changed, this, _1), gui_context());
_region->RegionFxChanged.connect (*this, invalidator (*this), boost::bind (&RegionView::region_renamed, this), gui_context());
/* derived class calls set_colors () including RegionView::set_colors() in ::init() */
//set_colors ();
@ -749,7 +750,7 @@ void
RegionView::show_region_editor ()
{
if (!editor) {
editor = new RegionEditor (trackview.session(), region());
editor = new RegionEditor (trackview.session(), this);
}
editor->present ();
@ -791,6 +792,9 @@ RegionView::make_name () const
if (_region->muted()) {
str = std::string(u8"\U0001F507") + str; // SPEAKER WITH CANCELLATION STROKE
}
if (_region->has_region_fx()) {
str = str + " (Fx)";
}
return str;
}

View File

@ -172,9 +172,10 @@ RouteProcessorSelection::set (AxisView* r)
if (!shp.session()) {
return;
}
PresentationInfo::ChangeSuspender cs;
shp.session()->selection().clear_stripables ();
add (r, true);
StripableList sl;
sl.push_back (r->stripable());
shp.session()->selection().set (sl);
}
bool

View File

@ -51,11 +51,8 @@ RulerDialog::RulerDialog ()
connect_action (bbt_button, "bbt-ruler");
connect_action (tempo_button, "tempo-ruler");
connect_action (meter_button, "meter-ruler");
connect_action (loop_punch_button, "loop-punch-ruler");
connect_action (range_button, "range-ruler");
connect_action (mark_button, "marker-ruler");
connect_action (cdmark_button, "cd-marker-ruler");
connect_action (cuemark_button, "cue-marker-ruler");
connect_action (section_button, "arrangement-ruler");
connect_action (video_button, "video-ruler");
}

View File

@ -1176,11 +1176,11 @@ Selection::get_state () const
continue;
}
AudioRegionGainLine* argl = dynamic_cast<AudioRegionGainLine*> (&(*i)->line());
if (argl) {
RegionFxLine* fxl = dynamic_cast<RegionFxLine*> (&(*i)->line());
if (fxl) {
XMLNode* r = node->add_child (X_("ControlPoint"));
r->set_property (X_("type"), "region");
r->set_property (X_("region-id"), argl->region_view ().region ()->id ());
r->set_property (X_("region-id"), fxl->region_view ().region ()->id ());
r->set_property (X_("view-index"), (*i)->view_index());
}
@ -1324,35 +1324,6 @@ Selection::set_state (XMLNode const & node, int)
if (!cps.empty()) {
add (cps);
}
} else if (prop_type->value () == "region") {
PBD::ID region_id;
uint32_t view_index;
if (!(*i)->get_property (X_("region-id"), region_id) ||
!(*i)->get_property (X_("view-index"), view_index)) {
continue;
}
RegionSelection rs;
editor->get_regionviews_by_id (region_id, rs);
if (!rs.empty ()) {
vector <ControlPoint *> cps;
for (RegionSelection::iterator rsi = rs.begin(); rsi != rs.end(); ++rsi) {
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*rsi);
if (arv) {
std::shared_ptr<AudioRegionGainLine> gl = arv->get_gain_line ();
ControlPoint* cp = gl->nth(view_index);
if (cp) {
cps.push_back (cp);
cp->show();
}
}
}
if (!cps.empty()) {
add (cps);
}
}
}
} else if ((*i)->name() == X_("TimelineRange")) {

View File

@ -34,15 +34,13 @@ using namespace ARDOUR;
SessionArchiveDialog::SessionArchiveDialog ()
: ArdourDialog (_("Zip/Archive Current Session"))
, ProgressReporter ()
, format_Label (ARDOUR::session_archive_suffix)
, only_used_checkbox (_("Exclude unused audio sources"))
{
VBox* vbox = get_vbox();
vbox->set_spacing (6);
format_selector.append (ARDOUR::session_archive_suffix);
format_selector.set_active_text (ARDOUR::session_archive_suffix);
encode_selector.append (_("None"));
encode_selector.append (_("FLAC 16bit"));
encode_selector.append (_("FLAC 24bit"));
@ -66,7 +64,7 @@ SessionArchiveDialog::SessionArchiveDialog ()
HBox* hbox = manage (new HBox);
hbox->set_spacing (6);
hbox->pack_start (name_entry, true, true);
hbox->pack_start (format_selector, false, false);
hbox->pack_start (format_Label, false, false);
table->attach (*hbox, 1, 2, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
++row;
@ -124,7 +122,7 @@ SessionArchiveDialog::name_entry_changed ()
return;
}
std::string dir = Glib::build_filename (target_folder(), name_entry.get_text() + format_selector.get_active_text ());
std::string dir = Glib::build_filename (target_folder(), name_entry.get_text() + ARDOUR::session_archive_suffix);
if (Glib::file_test (dir, Glib::FILE_TEST_EXISTS)) {
set_response_sensitive (RESPONSE_OK, false);

View File

@ -54,7 +54,7 @@ protected:
private:
Gtk::FileChooserButton target_folder_selector;
Gtk::Entry name_entry;
Gtk::ComboBoxText format_selector;
Gtk::Label format_Label;
Gtk::ComboBoxText encode_selector;
Gtk::ComboBoxText compression_selector;
Gtk::CheckButton only_used_checkbox;

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

@ -68,7 +68,7 @@ SimpleExportDialog::SimpleExportDialog (PublicEditor& editor, bool vapor_export)
/* clang-format off */
t->attach (LBL ("Format preset:"), 0, 1, r, r + 1, FILL, SHRINK, 0, 0);
if (_vapor_export) {
t->attach (LBL ("ADM/BWF"), 1, 2, r, r + 1, EXPAND, SHRINK, 0, 0);
t->attach (LBL ("ADM BWF"), 1, 2, r, r + 1, EXPAND, SHRINK, 0, 0);
} else {
t->attach (_eps.the_combo (), 1, 2, r, r + 1, EXPAND | FILL, SHRINK, 0, 0);
}
@ -161,7 +161,7 @@ SimpleExportDialog::set_session (ARDOUR::Session* s)
}
if (_vapor_export && (s->surround_master ()->surround_return ()->total_n_channels () > 128)) {
set_error ("Error: ADM/BWN files cannot contain more than 128 channels.");
set_error ("Error: ADM BWF files cannot contain more than 128 channels.");
return;
}
@ -270,6 +270,44 @@ SimpleExportDialog::start_export ()
range_name = SimpleExport::_session->snap_name ();
}
samplepos_t rend = (*r)[_range_cols.end];
samplepos_t t24h;
Timecode::Time tc (SimpleExport::_session->timecode_frames_per_second ());
tc.hours = 24;
SimpleExport::_session->timecode_to_sample (tc, t24h, false /* use_offset */, false /* use_subframes */);
if (rend >= t24h) {
hide ();
std::string txt = _("Error: ADM BWF files timecode cannot be past 24h.");
Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
msg.run ();
return;
}
/* C_Ex_08 - prevent export that might fail on some systems - 23.976 vs. 24/1001 */
switch (SimpleExport::_session->config.get_timecode_format ()) {
case Timecode::timecode_23976:
case Timecode::timecode_2997:
case Timecode::timecode_2997drop:
case Timecode::timecode_2997000drop:
tc.hours = 23;
tc.minutes = 58;
tc.seconds = 35;
tc.frames = 0;
SimpleExport::_session->timecode_to_sample (tc, t24h, false /* use_offset */, false /* use_subframes */);
if (rend >= t24h) {
hide ();
std::string txt = _("Error: The file to be exported contains an illegal timecode value near the midnight boundary. Try moving the export-range earlier on the product timeline.");
Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
msg.run ();
return;
}
break;
default:
break;
}
/* Ensure timespan exists, see also SimpleExport::run_export */
auto ts = _manager->get_timespans ();
assert (ts.size () == 1);
@ -307,7 +345,7 @@ SimpleExportDialog::start_export ()
if (_post_export_combo.get_active_row_number () == 0) {
PBD::open_folder (folder ());
}
if (!ARDOUR::Profile->get_mixbus ()) {
if (!ARDOUR::Profile->get_mixbus () && !ARDOUR::Profile->get_livetrax ()) {
NagScreen* ns = NagScreen::maybe_nag (_("Export"));
if (ns) {
ns->nag ();

View File

@ -44,11 +44,6 @@ namespace ARDOUR {
class Location;
}
namespace ArdourWidgets {
class ArdourButton;
class HSliderController;
}
class TriggerPropertiesBox;
class RegionPropertiesBox;
class RegionOperationsBox;

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

@ -583,15 +583,6 @@ StartupFSM::get_session_parameters_from_path (string const & path_, string const
string path (path_);
/* ... did the user give us a path or just a name? */
if (path.find (G_DIR_SEPARATOR) == string::npos) {
/* user gave session name with no path info, use
default session folder.
*/
path = Glib::build_filename (Config->get_default_session_parent_dir (), path);
}
if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS)) {
session_is_new = false;
@ -606,6 +597,10 @@ StartupFSM::get_session_parameters_from_path (string const & path_, string const
}
}
// TODO THIS SHOULD CALL ::check_session_parameters (false)
// to handle session archives etc
// (needs refactoring of ::check_session_parameters)
session_name = basename_nosuffix (path);
if (Glib::file_test (path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
@ -642,6 +637,18 @@ StartupFSM::get_session_parameters_from_path (string const & path_, string const
}
if (!ARDOUR_COMMAND_LINE::new_session) {
return false;
}
/* ... did the user give us a path or just a name? */
if (!Glib::path_is_absolute (path)) {
/* check for cwd relative path */
if (path.find (G_DIR_SEPARATOR) == string::npos) {
path = Glib::build_filename (Config->get_default_session_parent_dir (), path);
}
}
/* Everything after this involves a new session */
session_name = basename_nosuffix (path);
@ -810,25 +817,11 @@ StartupFSM::check_session_parameters (bool must_be_new)
session_template = session_dialog->session_template_name();
}
if (session_name[0] == G_DIR_SEPARATOR ||
#ifdef PLATFORM_WINDOWS
// Windows file system .. detect absolute path
// C:/*
(session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
#else
// Sensible file systems
// /* or ./* or ../*
(session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
(session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
#endif
)
{
if (Glib::path_is_absolute (session_name) || session_name.find (G_DIR_SEPARATOR) != string::npos) {
/* user typed absolute path or cwd-relative path
specified into session name field. So ... infer
session path and name from what was given.
*/
* specified into session name field. So ... infer
* session path and name from what was given.
*/
session_path = Glib::path_get_dirname (session_name);
session_name = Glib::path_get_basename (session_name);

View File

@ -622,7 +622,7 @@ StreamView::get_selectables (timepos_t const & start, timepos_t const & end, dou
|| (!within && (*i)->region()->coverage (start, end) != Temporal::OverlapNone)) {
if (_trackview.editor().internal_editing()) {
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
if (arv && arv->get_gain_line ()) {
if (arv && arv->fx_line ()) {
/* Note: AutomationLine::get_selectables() uses trackview.current_height (),
* disregarding Stacked layer display height
*/
@ -630,7 +630,7 @@ StreamView::get_selectables (timepos_t const & start, timepos_t const & end, dou
double const y = (*i)->get_canvas_group ()->position().y;
double t = 1.0 - std::min (1.0, std::max (0., (top - _trackview.y_position () - y) / c));
double b = 1.0 - std::min (1.0, std::max (0., (bottom - _trackview.y_position () - y) / c));
arv->get_gain_line()->get_selectables (start, end, b, t, results);
arv->fx_line()->get_selectables (start, end, b, t, results);
}
} else {
results.push_back (*i);

View File

@ -365,6 +365,7 @@
<ColorAlias name="recording rect" alias="alert:ruddy"/>
<ColorAlias name="recording waveform fill" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform outline" alias="neutral:foregroundest"/>
<ColorAlias name="region automation line" alias="alert:blue"/>
<ColorAlias name="region list automatic" alias="theme:contrasting less"/>
<ColorAlias name="region list missing source" alias="alert:red"/>
<ColorAlias name="region list whole file" alias="neutral:foreground"/>

View File

@ -356,6 +356,7 @@
<ColorAlias name="recording note" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform fill" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform outline" alias="neutral:background2"/>
<ColorAlias name="region automation line" alias="alert:blue"/>
<ColorAlias name="region list automatic" alias="theme:contrasting less"/>
<ColorAlias name="region list missing source" alias="alert:red"/>
<ColorAlias name="region list whole file" alias="neutral:foreground"/>

View File

@ -357,6 +357,7 @@
<ColorAlias name="recording note" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform fill" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform outline" alias="neutral:background2"/>
<ColorAlias name="region automation line" alias="alert:blue"/>
<ColorAlias name="region list automatic" alias="theme:contrasting less"/>
<ColorAlias name="region list missing source" alias="alert:red"/>
<ColorAlias name="region list whole file" alias="neutral:foreground"/>

View File

@ -357,6 +357,7 @@
<ColorAlias name="recording note" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform fill" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform outline" alias="neutral:background2"/>
<ColorAlias name="region automation line" alias="alert:blue"/>
<ColorAlias name="region list automatic" alias="theme:contrasting less"/>
<ColorAlias name="region list missing source" alias="alert:red"/>
<ColorAlias name="region list whole file" alias="neutral:foreground"/>

View File

@ -357,6 +357,7 @@
<ColorAlias name="recording note" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform fill" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform outline" alias="neutral:background2"/>
<ColorAlias name="region automation line" alias="alert:blue"/>
<ColorAlias name="region list automatic" alias="theme:contrasting less"/>
<ColorAlias name="region list missing source" alias="alert:red"/>
<ColorAlias name="region list whole file" alias="neutral:foreground"/>

View File

@ -320,7 +320,7 @@
<ColorAlias name="pluginui toggle: fill" alias="widget:bg"/>
<ColorAlias name="pluginui toggle: fill active" alias="widget:blue"/>
<ColorAlias name="preference highlight" alias="alert:yellow"/>
<ColorAlias name="processor automation line" alias="theme:bg1"/>
<ColorAlias name="processor automation line" alias="alert:green"/>
<ColorAlias name="processor auxfeedback: fill" alias="theme:contrasting alt"/>
<ColorAlias name="processor auxfeedback: led active" alias="alert:green"/>
<ColorAlias name="processor control button: fill" alias="neutral:background"/>
@ -359,6 +359,7 @@
<ColorAlias name="recording note" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform fill" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform outline" alias="neutral:background2"/>
<ColorAlias name="region automation line" alias="alert:blue"/>
<ColorAlias name="region list automatic" alias="theme:contrasting less"/>
<ColorAlias name="region list missing source" alias="alert:red"/>
<ColorAlias name="region list whole file" alias="neutral:foreground"/>

View File

@ -358,6 +358,7 @@
<ColorAlias name="recording note" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform fill" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform outline" alias="neutral:background2"/>
<ColorAlias name="region automation line" alias="alert:blue"/>
<ColorAlias name="region list automatic" alias="theme:contrasting less"/>
<ColorAlias name="region list missing source" alias="alert:red"/>
<ColorAlias name="region list whole file" alias="neutral:foreground"/>

View File

@ -358,6 +358,7 @@
<ColorAlias name="recording note" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform fill" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform outline" alias="neutral:background2"/>
<ColorAlias name="region automation line" alias="alert:blue"/>
<ColorAlias name="region list automatic" alias="theme:contrasting less"/>
<ColorAlias name="region list missing source" alias="alert:red"/>
<ColorAlias name="region list whole file" alias="neutral:foreground"/>

View File

@ -356,6 +356,7 @@
<ColorAlias name="recording note" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform fill" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform outline" alias="neutral:background2"/>
<ColorAlias name="region automation line" alias="alert:blue"/>
<ColorAlias name="region list automatic" alias="theme:contrasting less"/>
<ColorAlias name="region list missing source" alias="alert:red"/>
<ColorAlias name="region list whole file" alias="neutral:foreground"/>

View File

@ -357,6 +357,7 @@
<ColorAlias name="recording note" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform fill" alias="neutral:foregroundest"/>
<ColorAlias name="recording waveform outline" alias="neutral:foregroundest"/>
<ColorAlias name="region automation line" alias="alert:blue"/>
<ColorAlias name="region list automatic" alias="theme:contrasting less"/>
<ColorAlias name="region list missing source" alias="alert:red"/>
<ColorAlias name="region list whole file" alias="neutral:foreground"/>

View File

@ -160,6 +160,7 @@ TimeAxisView::TimeAxisView (ARDOUR::Session* sess, PublicEditor& ed, TimeAxisVie
inactive_label.set_name (X_("TrackNameEditor"));
inactive_label.set_alignment (0.0, 0.5);
inactive_label.set_width_chars (12);
set_tooltip (inactive_label, _("This track is inactive. (right-click to activate)"));
{
@ -437,7 +438,13 @@ TimeAxisView::controls_ebox_button_press (GdkEventButton* event)
_ebox_release_can_act = true;
if (maybe_set_cursor (event->y) > 0) {
_resize_drag_start = event->y_root;
} else {
if (event->button == 1) {
_editor.start_track_drag (*this, event->y, controls_ebox);
}
}
return true;
@ -452,6 +459,12 @@ TimeAxisView::idle_resize (int32_t h)
bool
TimeAxisView::controls_ebox_motion (GdkEventMotion* ev)
{
if (_editor.track_dragging()) {
_editor.mid_track_drag (ev, controls_ebox);
gdk_event_request_motions (ev);
return true;
}
if (_resize_drag_start >= 0) {
/* (ab)use the DragManager to do autoscrolling - basically we
@ -467,13 +480,15 @@ TimeAxisView::controls_ebox_motion (GdkEventMotion* ev)
_editor.add_to_idle_resize (this, delta);
_resize_drag_start = ev->y_root;
_did_resize = true;
gdk_event_request_motions (ev);
return true;
} else {
/* not dragging but ... */
maybe_set_cursor (ev->y);
}
gdk_event_request_motions(ev);
return true;
gdk_event_request_motions (ev);
return false;
}
bool
@ -517,23 +532,27 @@ TimeAxisView::maybe_set_cursor (int y)
bool
TimeAxisView::controls_ebox_button_release (GdkEventButton* ev)
{
if (_resize_drag_start >= 0) {
if (_have_preresize_cursor) {
gdk_window_set_cursor (controls_ebox.get_window()->gobj(), _preresize_cursor);
_preresize_cursor = 0;
_have_preresize_cursor = false;
}
_editor.stop_canvas_autoscroll ();
_resize_drag_start = -1;
if (_did_resize) {
_did_resize = false;
// don't change selection
return true;
}
if (_editor.track_dragging()) {
_editor.end_track_drag ();
} else {
if (_resize_drag_start >= 0) {
if (_have_preresize_cursor) {
gdk_window_set_cursor (controls_ebox.get_window()->gobj(), _preresize_cursor);
_preresize_cursor = 0;
_have_preresize_cursor = false;
}
_editor.stop_canvas_autoscroll ();
_resize_drag_start = -1;
if (_did_resize) {
_did_resize = false;
// don't change selection
return true;
}
}
if (!_ebox_release_can_act) {
return true;
if (!_ebox_release_can_act) {
return true;
}
}
switch (ev->button) {

View File

@ -124,7 +124,9 @@ TransportMastersWidget::~TransportMastersWidget ()
void
TransportMastersWidget::set_transport_master (std::shared_ptr<TransportMaster> tm)
{
_session->request_sync_source (tm);
if (_session) {
_session->request_sync_source (tm);
}
}
void

View File

@ -20,13 +20,13 @@
#define __ardour_gtk_trigger_ui_h__
#include "gtkmm/colorselection.h"
#include "gtkmm/entry.h"
#include "gtkmm2ext/actions.h"
#include "gtkmm2ext/bindings.h"
#include "ardour/triggerbox.h"
#include "widgets/ardour_button.h"
#include "widgets/slider_controller.h"
#include "widgets/frame.h"
namespace Gtk

View File

@ -156,6 +156,8 @@ UI_CONFIG_VARIABLE (std::string, freesound_dir, "freesound-dir", "")
UI_CONFIG_VARIABLE (int, max_note_height, "max-note-height", 20)
UI_CONFIG_VARIABLE (bool, prefer_tap_tempo, "prefer-tap-tempo", false)
UI_CONFIG_VARIABLE (bool, sandbox_all_lua_scripts, "sandbox-all-lua-scripts", false)
UI_CONFIG_VARIABLE (bool, update_action_scripts, "update-action-scripts", true)
UI_CONFIG_VARIABLE (bool, use_cocoa_invalidation, "use-cocoa-invalidation", true)
/* these are visibility-type selections in the New Track dialog that we should make persistent for the user's choices */
UI_CONFIG_VARIABLE (bool, show_on_cue_page, "show-on-cue-page", true)

View File

@ -26,6 +26,8 @@
#include "ardour/session.h"
#include "gtkmm2ext/utils.h"
#include "widgets/slider_controller.h"
#include "widgets/tooltips.h"
#include "ardour_ui.h"

Some files were not shown because too many files have changed in this diff Show More