Compare commits
329 Commits
Author | SHA1 | Date |
---|---|---|
Paul Davis | ecf5f9b1d7 | |
Paul Davis | 949b4d4017 | |
Ben Loftis | 0a19b719d4 | |
Robin Gareus | a7c613db22 | |
Robin Gareus | 46086a24ef | |
Robin Gareus | 8c1fddca14 | |
Robin Gareus | 4a99a40afd | |
Ben Loftis | a3d92fe5a7 | |
Robin Gareus | fb5ebc351c | |
Robin Gareus | 44b47e70e0 | |
Paul Davis | 7c5bd69ff1 | |
Robin Gareus | 2b2d923dc6 | |
Paul Davis | bbda6b8c02 | |
Paul Davis | cb5a9f11dc | |
Paul Davis | 44ee16a5ac | |
Paul Davis | c98ec4456d | |
Paul Davis | a67963185f | |
Paul Davis | 66707bc133 | |
Robin Gareus | e7d4f10e0d | |
Paul Davis | 69d63bac92 | |
Paul Davis | 1dba8f9906 | |
Paul Davis | 2d8c641314 | |
Paul Davis | 1f35010713 | |
Paul Davis | 7f82b918ae | |
Ben Loftis | 875e89ff67 | |
Ben Loftis | 34875e4f3f | |
Ben Loftis | 00305c070d | |
Robin Gareus | 1cd78c94d3 | |
Robin Gareus | 0df0e14e23 | |
Robin Gareus | ace3f812c3 | |
Robin Gareus | ab62177bdf | |
Robin Gareus | e317d75b17 | |
Robin Gareus | 6e6322b315 | |
Robin Gareus | 1d0ef6337f | |
Paul Davis | cacc3881ec | |
Alexandre Prokoudine | a06bfcdbdc | |
Robin Gareus | 706d4c5dcc | |
Robin Gareus | fd96694a21 | |
Robin Gareus | 5a52b66dfa | |
Robin Gareus | 76beb21862 | |
Robin Gareus | 75f5720c55 | |
Robin Gareus | 5a9d88a48a | |
Robin Gareus | 03689d8070 | |
Robin Gareus | f74a6a146b | |
Robin Gareus | c8c7955d5d | |
Robin Gareus | 6b70ad254c | |
Robin Gareus | 8f3794f0ca | |
Robin Gareus | d48af9a64d | |
Robin Gareus | f38fe2445f | |
Robin Gareus | c2e048547a | |
Robin Gareus | 5b746b186a | |
Robin Gareus | 4a14f2fed5 | |
Paul Davis | 53ddd200e7 | |
Robin Gareus | 83b3070fe1 | |
Robin Gareus | a642448b88 | |
Paul Davis | 13db3f64de | |
Paul Davis | 871bd5e55b | |
Robin Gareus | 5f17d1b399 | |
Robin Gareus | 3ce07580cb | |
Paul Davis | ac004eee70 | |
Robin Gareus | f227839247 | |
Robin Gareus | 13814deba2 | |
Robin Gareus | 63b5c9ea2b | |
Paul Davis | 08eb25ef55 | |
Robin Gareus | 0929faf830 | |
Robin Gareus | 710a22521f | |
Paul Davis | 2d5884ccb1 | |
Robin Gareus | 8ad53bc96c | |
Ben Loftis | d3c2faa23b | |
Ben Loftis | 78f81b2074 | |
Ben Loftis | 64c201791c | |
Robin Gareus | 7bfd128a75 | |
Robin Gareus | 5fdc7c4601 | |
Robin Gareus | f693c0406a | |
Robin Gareus | 9de2b3435d | |
Robin Gareus | e34359b921 | |
Paul Davis | ac779b38b2 | |
Robin Gareus | 66d36999b9 | |
Robin Gareus | 6e0c5e6a34 | |
Robin Gareus | 897610a047 | |
Paul Davis | f1e7ab08c7 | |
Paul Davis | 6ed9835677 | |
Robin Gareus | 6fbf2f37d9 | |
Robin Gareus | 4ec86a2657 | |
Robin Gareus | cd2db2c3aa | |
Robin Gareus | 5f52329bed | |
Paul Davis | 907cf66a63 | |
Paul Davis | 553e534455 | |
Paul Davis | fc194237eb | |
Paul Davis | 93e1e1c1f2 | |
Robin Gareus | 9d046af47a | |
Robin Gareus | afb519cd84 | |
Robin Gareus | 1f0ee56726 | |
Robin Gareus | b3df8ea6ef | |
agfline | fc1377ae46 | |
Robin Gareus | 7b75748299 | |
Robin Gareus | 0bac1e07f5 | |
Robin Gareus | a0e27495c6 | |
Robin Gareus | dad32d8b11 | |
Robin Gareus | 3c524098b4 | |
Paul Davis | 86c3b70c54 | |
Robin Gareus | ac47688023 | |
Robin Gareus | 5b02561573 | |
Robin Gareus | e75ad3399e | |
Robin Gareus | aa55bf35eb | |
Robin Gareus | caae3501ec | |
Paul Davis | c3eb30d96b | |
Robin Gareus | 6b8018d927 | |
Robin Gareus | 68d3be8918 | |
Robin Gareus | 1b1d6e767b | |
Paul Davis | 2f32a22a4d | |
Paul Davis | 384739aa80 | |
Paul Davis | fce1f15a87 | |
Paul Davis | dcdcaf4b47 | |
Paul Davis | b929e8a4e2 | |
Paul Davis | de1a425704 | |
Paul Davis | edc03002eb | |
John Emmas | 2e55f4452f | |
Robin Gareus | c62fbc5c5b | |
Robin Gareus | a0dc432e7a | |
Robin Gareus | e542a8e0a0 | |
Robin Gareus | 3bab92f9a7 | |
Paul Davis | 94e0f2d3cd | |
Paul Davis | 7d04a8bdd4 | |
Paul Davis | 90d21161e7 | |
Paul Davis | fd1f68c34a | |
Paul Davis | 29aeb88ce1 | |
Robin Gareus | 88df55f86d | |
Robin Gareus | 5d175786e8 | |
Mattias Ohlsson | 10109c3147 | |
John Emmas | dc74533fab | |
John Emmas | a345d05f0f | |
Robin Gareus | 4b8b5acfc4 | |
Robin Gareus | 4f59b1ddf5 | |
Robin Gareus | 70898a676b | |
Paul Davis | 576403c4cb | |
Paul Davis | f92d821a72 | |
Paul Davis | fdd91cc325 | |
Paul Davis | 51d2b3329c | |
Paul Davis | c3fb69c385 | |
Paul Davis | b515174e6a | |
Paul Davis | e71fcaa92d | |
Paul Davis | e170b34bf0 | |
Paul Davis | 89d7d85239 | |
Paul Davis | 81d1724931 | |
Robin Gareus | dec7b9a9af | |
Robin Gareus | 8cf0fe5c77 | |
jean-emmanuel | 4e44f44e71 | |
Maciej Bliziński | 18949a8730 | |
Olivier HUMBERT | 68402aae12 | |
Florian Hülsmann | 27154d9769 | |
Robin Gareus | df4f998231 | |
Robin Gareus | 100ee72cec | |
Robin Gareus | 233a82d5f9 | |
Robin Gareus | 37d24eee7d | |
Ben Loftis | 27e2348b47 | |
Ben Loftis | a88d430609 | |
John Emmas | 631ee17e34 | |
Robin Gareus | 99e2ac28e1 | |
Robin Gareus | f355551839 | |
Robin Gareus | b9da1a5bd5 | |
Robin Gareus | 2ccda116c7 | |
Robin Gareus | 5b9e4fff63 | |
Robin Gareus | 4b0da72bc2 | |
Robin Gareus | ee87b068e8 | |
Robin Gareus | 170b915038 | |
Robin Gareus | 2af2df3516 | |
Robin Gareus | e90e31d682 | |
Robin Gareus | ce4f91483b | |
Robin Gareus | 9bafa8a216 | |
Robin Gareus | 75167ac347 | |
Robin Gareus | 5f7ecf59a5 | |
Robin Gareus | dcb732f07c | |
Paul Davis | 201580f7ba | |
Paul Davis | fc86629daf | |
Paul Davis | 21a39c5f1f | |
Paul Davis | b2570bcaa3 | |
Paul Davis | 0b8cfdee40 | |
Paul Davis | 87f40ddc7f | |
Paul Davis | a0756429cf | |
Paul Davis | 7bcdd5b2e4 | |
Paul Davis | e3b21ed77a | |
Paul Davis | a7dbf57afa | |
Paul Davis | ad53c31e50 | |
Paul Davis | 5d1233e60a | |
Paul Davis | 43e0f08b93 | |
Paul Davis | 8f7f204ae4 | |
Paul Davis | 9052eb013e | |
Paul Davis | 125b0f9432 | |
Paul Davis | 16ed245977 | |
Paul Davis | 46fa056da6 | |
Robin Gareus | 354e60d657 | |
Robin Gareus | 848832f8b0 | |
Robin Gareus | 97becda83a | |
Paul Davis | f1a3eb1e3d | |
Robin Gareus | 4665cdcb6b | |
Robin Gareus | b00ddcfe1c | |
agfline | 8ea3a14cd6 | |
agfline | 41587d3c06 | |
Robin Gareus | 895fe2f753 | |
Robin Gareus | df12126909 | |
Robin Gareus | 38adfdf79e | |
Robin Gareus | b2d4280e0f | |
Robin Gareus | e5506d281a | |
Robin Gareus | 457238ec2e | |
Robin Gareus | 1996945353 | |
Robin Gareus | ad9a3ae103 | |
Robin Gareus | b04fa05f20 | |
Robin Gareus | 1cd9a9b57d | |
Robin Gareus | 59b2369736 | |
Robin Gareus | f3823e8d7c | |
Robin Gareus | 2bb4a9ac4e | |
Robin Gareus | 598ff1cb9a | |
Robin Gareus | f858316503 | |
Robin Gareus | 2ca5f28910 | |
Robin Gareus | 2f6a428f05 | |
Robin Gareus | 6dfcb60763 | |
Robin Gareus | f111f200c1 | |
Robin Gareus | df8106bd85 | |
Robin Gareus | 92183430b9 | |
Robin Gareus | 5216a6d987 | |
Robin Gareus | f5b53a6d14 | |
Robin Gareus | 2da3141706 | |
Robin Gareus | d2bdf440c8 | |
Robin Gareus | 6191f89d55 | |
Robin Gareus | bcbb4393fc | |
Paul Davis | 894e6d27a4 | |
Paul Davis | c96e12ba58 | |
Robin Gareus | e64a071e39 | |
Robin Gareus | 08e394f681 | |
Robin Gareus | 136b7f42d5 | |
Robin Gareus | 4b6e372ce7 | |
Edgar Aichinger | c9c419213f | |
Paul Davis | dde59c8e4c | |
Paul Davis | 1eb2a345df | |
Paul Davis | e7b3b61dbc | |
Robin Gareus | ab1299da87 | |
Robin Gareus | 44610c7877 | |
Robin Gareus | 96e83f4101 | |
Robin Gareus | b8c474ff32 | |
Robin Gareus | a69ca86944 | |
Robin Gareus | fe7fd146aa | |
Robin Gareus | 6b3fbefd26 | |
Robin Gareus | 0eed49b48e | |
Robin Gareus | 3d375f12ed | |
Robin Gareus | d023ea0d77 | |
Robin Gareus | 8a7d92f196 | |
Robin Gareus | cde26c5205 | |
Robin Gareus | ecd22e9aa8 | |
Robin Gareus | 826103f08c | |
Robin Gareus | 4a0505979d | |
Robin Gareus | 2e991b0067 | |
Robin Gareus | 3b0e421de4 | |
Robin Gareus | bda7041643 | |
Robin Gareus | 15dc06b12a | |
Robin Gareus | 02220783e1 | |
Paul Davis | 6d29a0e99b | |
Paul Davis | b96d556451 | |
Robin Gareus | e29ac27c59 | |
Paul Davis | 719debf292 | |
Robin Gareus | e0db21d484 | |
Robin Gareus | 41115f1282 | |
Robin Gareus | 26b6bece95 | |
Robin Gareus | 93934dfb92 | |
Robin Gareus | 1c55cc6ee2 | |
Florian Walpen | 845171807f | |
Robin Gareus | 0bb3c166e8 | |
Robin Gareus | 980eb595cf | |
Robin Gareus | cfa45be99f | |
Paul Davis | 4d5175e32e | |
Paul Davis | adfba3d39d | |
Paul Davis | d57ce0eba1 | |
Paul Davis | 6c38e0a4e3 | |
Paul Davis | fe6a635c3a | |
Paul Davis | 7324070628 | |
Robin Gareus | bd4d6b4cba | |
Robin Gareus | 082297b932 | |
Robin Gareus | 73fea85381 | |
agfline | 25397d7812 | |
Robin Gareus | 4883867f2b | |
Robin Gareus | da4218c2db | |
Mads Kiilerich | a2bb1a3511 | |
Robin Gareus | c10154ad23 | |
Paul Davis | e64af8e4ed | |
Paul Davis | 4b563ae518 | |
Paul Davis | 71e085d825 | |
Paul Davis | 0c4eada414 | |
Paul Davis | 802d9fa487 | |
Paul Davis | 9efd521ea6 | |
agfline | 52cce5adc6 | |
Robin Gareus | 2224aca75c | |
Robin Gareus | f1ecd8c124 | |
Robin Gareus | 9e9fd201b5 | |
Robin Gareus | 069bf034ab | |
Robin Gareus | 16fb29d576 | |
Robin Gareus | 0fff58f905 | |
Robin Gareus | f2d938914d | |
Robin Gareus | 2f61071974 | |
Robin Gareus | 682f4dafd3 | |
Robin Gareus | 35017245d9 | |
Robin Gareus | 5d60c2668c | |
Robin Gareus | b783e3eab1 | |
Ben Loftis | e467e0c014 | |
Robin Gareus | 46a8b547fa | |
Robin Gareus | c012ab19e0 | |
Ben Loftis | f873f9f621 | |
Ben Loftis | 310e7f2279 | |
agfline | d03cdf86e1 | |
agfline | bd937366fd | |
agfline | 2b1349ffc2 | |
Robin Gareus | 5e2f027ee9 | |
Ben Loftis | 258b22c9f1 | |
Ben Loftis | e907aad05c | |
Ben Loftis | 7ad5278bfd | |
Robin Gareus | 43c08dd2f5 | |
Robin Gareus | 8a8a1b9fb9 | |
Robin Gareus | 13383b11a7 | |
Ben Loftis | 24b18c889b | |
Robin Gareus | 42dc033636 | |
Robin Gareus | 77e7470270 | |
Robin Gareus | 922ad14217 | |
Robin Gareus | 6df34a307d | |
Robin Gareus | 3a6171428a | |
Robin Gareus | bf7d4f895e | |
Robin Gareus | 517d82a6f2 | |
Robin Gareus | 53b951f6a9 | |
GianfrancoCostamagna | 338cd09a4a | |
Robin Gareus | 37d130f6e1 | |
Robin Gareus | ed98ff97b2 |
583
doc/Doxyfile
583
doc/Doxyfile
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,157 @@
|
|||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 - 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
class DoxygenAwesomeDarkModeToggle extends HTMLElement {
|
||||
// SVG icons from https://fonts.google.com/icons
|
||||
// Licensed under the Apache 2.0 license:
|
||||
// https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
static lightModeIcon = `<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#FCBF00"><rect fill="none" height="24" width="24"/><circle cx="12" cy="12" opacity=".3" r="3"/><path d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"/></svg>`
|
||||
static darkModeIcon = `<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#FE9700"><rect fill="none" height="24" width="24"/><path d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27 C17.45,17.19,14.93,19,12,19c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z" opacity=".3"/><path d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"/></svg>`
|
||||
static title = "Toggle Light/Dark Mode"
|
||||
|
||||
static prefersLightModeInDarkModeKey = "prefers-light-mode-in-dark-mode"
|
||||
static prefersDarkModeInLightModeKey = "prefers-dark-mode-in-light-mode"
|
||||
|
||||
static _staticConstructor = function() {
|
||||
DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.userPreference)
|
||||
// Update the color scheme when the browsers preference changes
|
||||
// without user interaction on the website.
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
|
||||
DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged()
|
||||
})
|
||||
// Update the color scheme when the tab is made visible again.
|
||||
// It is possible that the appearance was changed in another tab
|
||||
// while this tab was in the background.
|
||||
document.addEventListener("visibilitychange", visibilityState => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged()
|
||||
}
|
||||
});
|
||||
}()
|
||||
|
||||
static init() {
|
||||
$(function() {
|
||||
$(document).ready(function() {
|
||||
const toggleButton = document.createElement('doxygen-awesome-dark-mode-toggle')
|
||||
toggleButton.title = DoxygenAwesomeDarkModeToggle.title
|
||||
toggleButton.updateIcon()
|
||||
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
|
||||
toggleButton.updateIcon()
|
||||
})
|
||||
document.addEventListener("visibilitychange", visibilityState => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
toggleButton.updateIcon()
|
||||
}
|
||||
});
|
||||
|
||||
$(document).ready(function(){
|
||||
document.getElementById("MSearchBox").parentNode.appendChild(toggleButton)
|
||||
})
|
||||
$(window).resize(function(){
|
||||
document.getElementById("MSearchBox").parentNode.appendChild(toggleButton)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.onclick=this.toggleDarkMode
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns `true` for dark-mode, `false` for light-mode system preference
|
||||
*/
|
||||
static get systemPreference() {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns `true` for dark-mode, `false` for light-mode user preference
|
||||
*/
|
||||
static get userPreference() {
|
||||
return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) ||
|
||||
(DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey))
|
||||
}
|
||||
|
||||
static set userPreference(userPreference) {
|
||||
DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference
|
||||
if(!userPreference) {
|
||||
if(DoxygenAwesomeDarkModeToggle.systemPreference) {
|
||||
localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true)
|
||||
} else {
|
||||
localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)
|
||||
}
|
||||
} else {
|
||||
if(!DoxygenAwesomeDarkModeToggle.systemPreference) {
|
||||
localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true)
|
||||
} else {
|
||||
localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)
|
||||
}
|
||||
}
|
||||
DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged()
|
||||
}
|
||||
|
||||
static enableDarkMode(enable) {
|
||||
if(enable) {
|
||||
DoxygenAwesomeDarkModeToggle.darkModeEnabled = true
|
||||
document.documentElement.classList.add("dark-mode")
|
||||
document.documentElement.classList.remove("light-mode")
|
||||
} else {
|
||||
DoxygenAwesomeDarkModeToggle.darkModeEnabled = false
|
||||
document.documentElement.classList.remove("dark-mode")
|
||||
document.documentElement.classList.add("light-mode")
|
||||
}
|
||||
}
|
||||
|
||||
static onSystemPreferenceChanged() {
|
||||
DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference
|
||||
DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled)
|
||||
}
|
||||
|
||||
static onUserPreferenceChanged() {
|
||||
DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled)
|
||||
}
|
||||
|
||||
toggleDarkMode() {
|
||||
DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference
|
||||
this.updateIcon()
|
||||
}
|
||||
|
||||
updateIcon() {
|
||||
if(DoxygenAwesomeDarkModeToggle.darkModeEnabled) {
|
||||
this.innerHTML = DoxygenAwesomeDarkModeToggle.darkModeIcon
|
||||
} else {
|
||||
this.innerHTML = DoxygenAwesomeDarkModeToggle.lightModeIcon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("doxygen-awesome-dark-mode-toggle", DoxygenAwesomeDarkModeToggle);
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 - 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
class DoxygenAwesomeFragmentCopyButton extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.onclick=this.copyContent
|
||||
}
|
||||
static title = "Copy to clipboard"
|
||||
static copyIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>`
|
||||
static successIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/></svg>`
|
||||
static successDuration = 980
|
||||
static init() {
|
||||
$(function() {
|
||||
$(document).ready(function() {
|
||||
if(navigator.clipboard) {
|
||||
const fragments = document.getElementsByClassName("fragment")
|
||||
for(const fragment of fragments) {
|
||||
const fragmentWrapper = document.createElement("div")
|
||||
fragmentWrapper.className = "doxygen-awesome-fragment-wrapper"
|
||||
const fragmentCopyButton = document.createElement("doxygen-awesome-fragment-copy-button")
|
||||
fragmentCopyButton.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon
|
||||
fragmentCopyButton.title = DoxygenAwesomeFragmentCopyButton.title
|
||||
|
||||
fragment.parentNode.replaceChild(fragmentWrapper, fragment)
|
||||
fragmentWrapper.appendChild(fragment)
|
||||
fragmentWrapper.appendChild(fragmentCopyButton)
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
copyContent() {
|
||||
const content = this.previousSibling.cloneNode(true)
|
||||
// filter out line number from file listings
|
||||
content.querySelectorAll(".lineno, .ttc").forEach((node) => {
|
||||
node.remove()
|
||||
})
|
||||
let textContent = content.textContent
|
||||
// remove trailing newlines that appear in file listings
|
||||
let numberOfTrailingNewlines = 0
|
||||
while(textContent.charAt(textContent.length - (numberOfTrailingNewlines + 1)) == '\n') {
|
||||
numberOfTrailingNewlines++;
|
||||
}
|
||||
textContent = textContent.substring(0, textContent.length - numberOfTrailingNewlines)
|
||||
navigator.clipboard.writeText(textContent);
|
||||
this.classList.add("success")
|
||||
this.innerHTML = DoxygenAwesomeFragmentCopyButton.successIcon
|
||||
window.setTimeout(() => {
|
||||
this.classList.remove("success")
|
||||
this.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon
|
||||
}, DoxygenAwesomeFragmentCopyButton.successDuration);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("doxygen-awesome-fragment-copy-button", DoxygenAwesomeFragmentCopyButton)
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 - 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
class DoxygenAwesomeInteractiveToc {
|
||||
static topOffset = 38
|
||||
static hideMobileMenu = true
|
||||
static headers = []
|
||||
|
||||
static init() {
|
||||
window.addEventListener("load", () => {
|
||||
let toc = document.querySelector(".contents > .toc")
|
||||
if(toc) {
|
||||
toc.classList.add("interactive")
|
||||
if(!DoxygenAwesomeInteractiveToc.hideMobileMenu) {
|
||||
toc.classList.add("open")
|
||||
}
|
||||
document.querySelector(".contents > .toc > h3")?.addEventListener("click", () => {
|
||||
if(toc.classList.contains("open")) {
|
||||
toc.classList.remove("open")
|
||||
} else {
|
||||
toc.classList.add("open")
|
||||
}
|
||||
})
|
||||
|
||||
document.querySelectorAll(".contents > .toc > ul a").forEach((node) => {
|
||||
let id = node.getAttribute("href").substring(1)
|
||||
DoxygenAwesomeInteractiveToc.headers.push({
|
||||
node: node,
|
||||
headerNode: document.getElementById(id)
|
||||
})
|
||||
|
||||
document.getElementById("doc-content")?.addEventListener("scroll", () => {
|
||||
DoxygenAwesomeInteractiveToc.update()
|
||||
})
|
||||
})
|
||||
DoxygenAwesomeInteractiveToc.update()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
static update() {
|
||||
let active = DoxygenAwesomeInteractiveToc.headers[0]?.node
|
||||
DoxygenAwesomeInteractiveToc.headers.forEach((header) => {
|
||||
let position = header.headerNode.getBoundingClientRect().top
|
||||
header.node.classList.remove("active")
|
||||
header.node.classList.remove("aboveActive")
|
||||
if(position < DoxygenAwesomeInteractiveToc.topOffset) {
|
||||
active = header.node
|
||||
active?.classList.add("aboveActive")
|
||||
}
|
||||
})
|
||||
active?.classList.add("active")
|
||||
active?.classList.remove("aboveActive")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 - 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
class DoxygenAwesomeParagraphLink {
|
||||
// Icon from https://fonts.google.com/icons
|
||||
// Licensed under the Apache 2.0 license:
|
||||
// https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
static icon = `<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 0 24 24" width="20px"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M17 7h-4v2h4c1.65 0 3 1.35 3 3s-1.35 3-3 3h-4v2h4c2.76 0 5-2.24 5-5s-2.24-5-5-5zm-6 8H7c-1.65 0-3-1.35-3-3s1.35-3 3-3h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-2zm-3-4h8v2H8z"/></svg>`
|
||||
static title = "Permanent Link"
|
||||
static init() {
|
||||
$(function() {
|
||||
$(document).ready(function() {
|
||||
document.querySelectorAll(".contents a.anchor[id], .contents .groupheader > a[id]").forEach((node) => {
|
||||
let anchorlink = document.createElement("a")
|
||||
anchorlink.setAttribute("href", `#${node.getAttribute("id")}`)
|
||||
anchorlink.setAttribute("title", DoxygenAwesomeParagraphLink.title)
|
||||
anchorlink.classList.add("anchorlink")
|
||||
node.classList.add("anchor")
|
||||
anchorlink.innerHTML = DoxygenAwesomeParagraphLink.icon
|
||||
node.parentElement.appendChild(anchorlink)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 - 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
|
||||
#MSearchBox {
|
||||
width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - var(--searchbar-height) - 1px);
|
||||
}
|
||||
|
||||
#MSearchField {
|
||||
width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 66px - var(--searchbar-height));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 - 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
html {
|
||||
/* side nav width. MUST be = `TREEVIEW_WIDTH`.
|
||||
* Make sure it is wide enough to contain the page title (logo + title + version)
|
||||
*/
|
||||
--side-nav-fixed-width: 335px;
|
||||
--menu-display: none;
|
||||
|
||||
--top-height: 120px;
|
||||
--toc-sticky-top: -25px;
|
||||
--toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 25px);
|
||||
}
|
||||
|
||||
#projectname {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
html {
|
||||
--searchbar-background: var(--page-background-color);
|
||||
}
|
||||
|
||||
#side-nav {
|
||||
min-width: var(--side-nav-fixed-width);
|
||||
max-width: var(--side-nav-fixed-width);
|
||||
top: var(--top-height);
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#nav-tree, #side-nav {
|
||||
height: calc(100vh - var(--top-height)) !important;
|
||||
}
|
||||
|
||||
#nav-tree {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#top {
|
||||
display: block;
|
||||
border-bottom: none;
|
||||
height: var(--top-height);
|
||||
margin-bottom: calc(0px - var(--top-height));
|
||||
max-width: var(--side-nav-fixed-width);
|
||||
overflow: hidden;
|
||||
background: var(--side-nav-background);
|
||||
}
|
||||
#main-nav {
|
||||
float: left;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.ui-resizable-handle {
|
||||
cursor: default;
|
||||
width: 1px !important;
|
||||
background: var(--separator-color);
|
||||
box-shadow: 0 calc(-2 * var(--top-height)) 0 0 var(--separator-color);
|
||||
}
|
||||
|
||||
#nav-path {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
left: var(--side-nav-fixed-width);
|
||||
bottom: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#doc-content {
|
||||
height: calc(100vh - 31px) !important;
|
||||
padding-bottom: calc(3 * var(--spacing-large));
|
||||
padding-top: calc(var(--top-height) - 80px);
|
||||
box-sizing: border-box;
|
||||
margin-left: var(--side-nav-fixed-width) !important;
|
||||
}
|
||||
|
||||
#MSearchBox {
|
||||
width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)));
|
||||
}
|
||||
|
||||
#MSearchField {
|
||||
width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 65px);
|
||||
}
|
||||
|
||||
#MSearchResultsWindow {
|
||||
left: var(--spacing-medium) !important;
|
||||
right: auto;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
|
||||
Doxygen Awesome
|
||||
https://github.com/jothepro/doxygen-awesome-css
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 jothepro
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
class DoxygenAwesomeTabs {
|
||||
|
||||
static init() {
|
||||
window.addEventListener("load", () => {
|
||||
document.querySelectorAll(".tabbed:not(:empty)").forEach((tabbed, tabbedIndex) => {
|
||||
let tabLinkList = []
|
||||
tabbed.querySelectorAll(":scope > ul > li").forEach((tab, tabIndex) => {
|
||||
tab.id = "tab_" + tabbedIndex + "_" + tabIndex
|
||||
let header = tab.querySelector(".tab-title")
|
||||
let tabLink = document.createElement("button")
|
||||
tabLink.classList.add("tab-button")
|
||||
tabLink.appendChild(header)
|
||||
header.title = header.textContent
|
||||
tabLink.addEventListener("click", () => {
|
||||
tabbed.querySelectorAll(":scope > ul > li").forEach((tab) => {
|
||||
tab.classList.remove("selected")
|
||||
})
|
||||
tabLinkList.forEach((tabLink) => {
|
||||
tabLink.classList.remove("active")
|
||||
})
|
||||
tab.classList.add("selected")
|
||||
tabLink.classList.add("active")
|
||||
})
|
||||
tabLinkList.push(tabLink)
|
||||
if(tabIndex == 0) {
|
||||
tab.classList.add("selected")
|
||||
tabLink.classList.add("active")
|
||||
}
|
||||
})
|
||||
let tabsOverview = document.createElement("div")
|
||||
tabsOverview.classList.add("tabs-overview")
|
||||
let tabsOverviewContainer = document.createElement("div")
|
||||
tabsOverviewContainer.classList.add("tabs-overview-container")
|
||||
tabLinkList.forEach((tabLink) => {
|
||||
tabsOverview.appendChild(tabLink)
|
||||
})
|
||||
tabsOverviewContainer.appendChild(tabsOverview)
|
||||
tabbed.before(tabsOverviewContainer)
|
||||
|
||||
function resize() {
|
||||
let maxTabHeight = 0
|
||||
tabbed.querySelectorAll(":scope > ul > li").forEach((tab, tabIndex) => {
|
||||
let visibility = tab.style.display
|
||||
tab.style.display = "block"
|
||||
maxTabHeight = Math.max(tab.offsetHeight, maxTabHeight)
|
||||
tab.style.display = visibility
|
||||
})
|
||||
tabbed.style.height = `${maxTabHeight + 10}px`
|
||||
}
|
||||
|
||||
resize()
|
||||
new ResizeObserver(resize).observe(tabbed)
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
static resize(tabbed) {
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,54 @@
|
|||
html.alternative {
|
||||
/* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */
|
||||
--primary-color: #AF7FE4;
|
||||
--primary-dark-color: #9270E4;
|
||||
--primary-light-color: #7aabd6;
|
||||
--primary-lighter-color: #cae1f1;
|
||||
--primary-lightest-color: #e9f1f8;
|
||||
|
||||
/* page base colors */
|
||||
--page-background-color: white;
|
||||
--page-foreground-color: #2c3e50;
|
||||
--page-secondary-foreground-color: #67727e;
|
||||
|
||||
|
||||
--border-radius-large: 22px;
|
||||
--border-radius-small: 9px;
|
||||
--border-radius-medium: 14px;
|
||||
--spacing-small: 8px;
|
||||
--spacing-medium: 14px;
|
||||
--spacing-large: 19px;
|
||||
|
||||
--top-height: 125px;
|
||||
|
||||
--side-nav-background: #324067;
|
||||
--side-nav-foreground: #F1FDFF;
|
||||
--header-foreground: var(--side-nav-foreground);
|
||||
--searchbar-background: var(--side-nav-foreground);
|
||||
--searchbar-border-radius: var(--border-radius-medium);
|
||||
--header-background: var(--side-nav-background);
|
||||
--header-foreground: var(--side-nav-foreground);
|
||||
|
||||
--toc-background: rgb(243, 240, 252);
|
||||
--toc-foreground: var(--page-foreground-color);
|
||||
}
|
||||
|
||||
html.alternative.dark-mode {
|
||||
color-scheme: dark;
|
||||
|
||||
--primary-color: #AF7FE4;
|
||||
--primary-dark-color: #9270E4;
|
||||
--primary-light-color: #4779ac;
|
||||
--primary-lighter-color: #191e21;
|
||||
--primary-lightest-color: #191a1c;
|
||||
|
||||
--page-background-color: #1C1D1F;
|
||||
--page-foreground-color: #d2dbde;
|
||||
--page-secondary-foreground-color: #859399;
|
||||
--separator-color: #3a3246;
|
||||
--side-nav-background: #171D32;
|
||||
--side-nav-foreground: #F1FDFF;
|
||||
--toc-background: #20142C;
|
||||
--searchbar-background: var(--page-background-color);
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
.github-corner svg {
|
||||
fill: var(--primary-light-color);
|
||||
color: var(--page-background-color);
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.github-corner svg {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
#projectnumber {
|
||||
margin-right: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.alter-theme-button {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
background: var(--primary-color);
|
||||
color: var(--page-background-color) !important;
|
||||
border-radius: var(--border-radius-medium);
|
||||
padding: var(--spacing-small) var(--spacing-medium);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.alter-theme-button:hover {
|
||||
background: var(--primary-dark-color);
|
||||
}
|
||||
|
||||
html.dark-mode .darkmode_inverted_image img, /* < doxygen 1.9.3 */
|
||||
html.dark-mode .darkmode_inverted_image object[type="image/svg+xml"] /* doxygen 1.9.3 */ {
|
||||
filter: brightness(89%) hue-rotate(180deg) invert();
|
||||
}
|
||||
|
||||
.bordered_image {
|
||||
border-radius: var(--border-radius-small);
|
||||
border: 1px solid var(--separator-color);
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
html.dark-mode .bordered_image img, /* < doxygen 1.9.3 */
|
||||
html.dark-mode .bordered_image object[type="image/svg+xml"] /* doxygen 1.9.3 */ {
|
||||
border-radius: var(--border-radius-small);
|
||||
}
|
||||
|
||||
.title_screenshot {
|
||||
filter: drop-shadow(0px 3px 10px rgba(0,0,0,0.22));
|
||||
max-width: 500px;
|
||||
margin: var(--spacing-large) 0;
|
||||
}
|
||||
|
||||
.title_screenshot .caption {
|
||||
display: none;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||
<meta name="generator" content="Doxygen $doxygenversion"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
|
||||
<meta property="og:title" content="Ardour Source Documentation" />
|
||||
<meta property="og:image" content="/images/logo.png" />
|
||||
<meta property="og:description" content="the open source cross-platform DAW" />
|
||||
<meta property="og:url" content="https://ardour.org/" />
|
||||
|
||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
|
||||
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<link rel="icon" href="/images/icons/favicon.ico"/>
|
||||
<script type="text/javascript" src="$relpath^jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-darkmode-toggle.js"></script>
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-fragment-copy-button.js"></script>
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-paragraph-link.js"></script>
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-interactive-toc.js"></script>
|
||||
<script type="text/javascript" src="$relpath^doxygen-awesome-tabs.js"></script>
|
||||
<script type="text/javascript" src="$relpath^toggle-alternative-theme.js"></script>
|
||||
<script type="text/javascript">
|
||||
DoxygenAwesomeFragmentCopyButton.init()
|
||||
DoxygenAwesomeDarkModeToggle.init()
|
||||
DoxygenAwesomeParagraphLink.init()
|
||||
DoxygenAwesomeInteractiveToc.init()
|
||||
DoxygenAwesomeTabs.init()
|
||||
</script>
|
||||
$treeview
|
||||
$search
|
||||
$mathjax
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
|
||||
<!--BEGIN TITLEAREA-->
|
||||
<div id="titlearea">
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr style="height: 56px;">
|
||||
<!--BEGIN PROJECT_LOGO-->
|
||||
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
|
||||
<!--END PROJECT_LOGO-->
|
||||
<!--BEGIN PROJECT_NAME-->
|
||||
<td id="projectalign" style="padding-left: 0.5em;">
|
||||
<div id="projectname">$projectname
|
||||
<!--BEGIN PROJECT_NUMBER--> <span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
|
||||
</div>
|
||||
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
|
||||
</td>
|
||||
<!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME-->
|
||||
<!--BEGIN PROJECT_BRIEF-->
|
||||
<td style="padding-left: 0.5em;">
|
||||
<div id="projectbrief">$projectbrief</div>
|
||||
</td>
|
||||
<!--END PROJECT_BRIEF-->
|
||||
<!--END !PROJECT_NAME-->
|
||||
<!--BEGIN DISABLE_INDEX-->
|
||||
<!--BEGIN SEARCHENGINE-->
|
||||
<td>$searchbox</td>
|
||||
<!--END SEARCHENGINE-->
|
||||
<!--END DISABLE_INDEX-->
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--END TITLEAREA-->
|
||||
<!-- end header part -->
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
let original_theme_active = true;
|
||||
|
||||
function toggle_alternative_theme() {
|
||||
if(original_theme_active) {
|
||||
document.documentElement.classList.add("alternative")
|
||||
original_theme_active = false;
|
||||
} else {
|
||||
document.documentElement.classList.remove("alternative")
|
||||
original_theme_active = true;
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 1008 B After Width: | Height: | Size: 1008 B |
|
@ -0,0 +1,317 @@
|
|||
# Overview and Source Tree Layout
|
||||
|
||||
Welcome to the in-code documentation for Ardour.
|
||||
|
||||
The main components of Ardour are as follows:
|
||||
|
||||
- A GTK2 front-end, in `gtk2_ardour`.
|
||||
- libardour, the audio-processing back-end, in `libs/ardour`.
|
||||
|
||||
|
||||
|
||||
The source tree is laid out as follows:
|
||||
|
||||
## Front Ends
|
||||
|
||||
* `gtk2_ardour/`</dt>
|
||||
|
||||
The main Ardour GUI -- This is where most of the complexity is.
|
||||
It is cleanly separated from the backend and processing engine.
|
||||
|
||||
* `headless/`
|
||||
|
||||
hardour -- headless Ardour, mostly demo-code how to use Ardour without a GUI.
|
||||
|
||||
* `session_utils/`
|
||||
|
||||
command-line tools using libardour (e.g. export)
|
||||
|
||||
* `luasession/`
|
||||
|
||||
arlua -- fully fledged commandline interface to libardour
|
||||
|
||||
## Libraries
|
||||
|
||||
A collection of libraries and utility functions. Most are shared
|
||||
libraries, and almost all are exclusive to Ardour.
|
||||
A few specific libraries are compiled statically (e.g. fluidsynth for use in plugins).
|
||||
|
||||
### Ardour specific libs
|
||||
|
||||
* `libs/pbd/`
|
||||
|
||||
Generic utility classes. This is used the basis for all Ardour specific libraries.
|
||||
It provides basic concepts and OS abstractions.
|
||||
|
||||
*The name comes from "Paul Barton-Davis", Paul's full name at the time he started working on working on audio software.*
|
||||
|
||||
* `libs/evoral/`
|
||||
|
||||
Evoral is Ardour's event Library, used for control events, control lists, automation evaluation,
|
||||
parameter interpolation, parameter descriptions, incl. MIDI event abstraction.
|
||||
|
||||
- `libs/evoral/libsmf/` (contains several non-upstreamed fixes)
|
||||
|
||||
Handling Standard %MIDI File (Evoral::SMF) format. Abstracted to C++ in SMF.{cc,h}
|
||||
|
||||
* `libs/backends/`
|
||||
|
||||
Interaction with Operating System's Audio/MIDI API:
|
||||
ALSA, CoreAudio, JACK, PortAudio/ASIO, PulseAudio
|
||||
|
||||
see ARDOUR::AudioBackend
|
||||
|
||||
* `libs/surfaces/`
|
||||
|
||||
Control Surfaces, dynamically loaded by libardour on runtime,
|
||||
to remote-control ardour (midi bindings, network etc).
|
||||
|
||||
see ARDOUR::ControlProtocol
|
||||
|
||||
* `libs/midi++2/`
|
||||
|
||||
%MIDI parsing, MIDNAM handling, Port abstraction for I/O
|
||||
|
||||
* `libs/temporal/`
|
||||
|
||||
Various utility code for dealing with different kinds of time,
|
||||
including Timecode, and musical time conversions (Temporal::Beats, Temporal::BBT_Time).
|
||||
|
||||
This library also provides the fundamental time types, and the *TempoMap*.
|
||||
See <https://ardour.org/representing-time.html> for more information.
|
||||
|
||||
* `libs/panners/`
|
||||
|
||||
Pan plugins (stereo-balance, VBAP, etc) are dynamically loaded at runtime.
|
||||
|
||||
see ARDOUR::Panner
|
||||
|
||||
* `libs/audiographer/`
|
||||
|
||||
Mini Ardour inside Ardour to export audio-files from sessions.
|
||||
|
||||
It is a combination of AudioGrapher::Source and AudioGrapher::Sink classes that are chained together by ARDOUR::ExportGraphBuilder as shown in the ASCII art
|
||||
[Export Graph](https://git.ardour.org/ardour/ardour/src/commit/0df0e14e2309a00d433827fa34b87638b87f4fff/libs/ardour/export_graph_builder.cc#L73-L154).
|
||||
|
||||
* `libs/ardour/`
|
||||
|
||||
This is it. libardour runs Ardour sessions.
|
||||
|
||||
All realtime processing happens here, plugins are managed etc.
|
||||
|
||||
Some starting points are ARDOUR::Route ARDOUR::Session ARDOUR::Processor
|
||||
|
||||
### UI related libs
|
||||
|
||||
* `libs/gtkmm2ext/`
|
||||
|
||||
Utility Library to extend GDK, GTK, and basic abstraction for UIs
|
||||
and event-loops. This library is not limited to the GUI, but also
|
||||
used for other graphical interfaces (e.g. Push2, NI Maschine control
|
||||
surfaces).
|
||||
|
||||
* `libs/canvas/`
|
||||
|
||||
Cairo Canvas, provides a slate for scalable drawing and basic layout/packing
|
||||
This is used by Ardour's main editor.
|
||||
|
||||
See ArdourCanvas::GtkCanvas and ArdourCanvas::Item
|
||||
|
||||
* `libs/widgets/`
|
||||
|
||||
Ardour GUI widgets (buttons, fader, knobs, etc). They are basically all CairoWidget%s
|
||||
|
||||
* `libs/waveview/`
|
||||
|
||||
Threaded waveform rendering and waveform image cache.
|
||||
|
||||
* `libs/tk/`
|
||||
|
||||
A localized version of GTK+2, renamed as YTK. See Gtk namespace for relevant documentation.
|
||||
|
||||
- `libs/tk/ydk` `libs/tk/ytk`
|
||||
|
||||
gdk, gtk based on upstream gtk+ 2.24.23
|
||||
|
||||
- `libs/tk/ydk-pixbuf`
|
||||
|
||||
stripped down version of gdk-pixbuf 2.31.1
|
||||
|
||||
- `libs/tk/ydkmm` , `libs/tk/ytkmm`
|
||||
|
||||
gdkmm, gtkmm based on upstream gtkmm 2.45.3
|
||||
|
||||
- `libs/tk/ztk`
|
||||
|
||||
atk 2.14.0
|
||||
|
||||
- `libs/tk/ztkmm`
|
||||
|
||||
atkmm 2.22.7
|
||||
|
||||
- `libs/tk/suil`
|
||||
|
||||
A local copy of <https://github.com/lv2/suil/> (based on 0.10.8).
|
||||
Since GTK2 is in our source tree, we also need to provide various plugin UI wrappers
|
||||
(`x11_in_gtk2`, `win_in_gtk2`, `suil_cocoa_in_gtk2`).
|
||||
|
||||
### Plugin Scan Tools
|
||||
|
||||
By default plugins are scanned by a dedicated external process. If that crashes the
|
||||
main application is not affected, and the plugin that causes the scanner to crash can be
|
||||
blacklisted.
|
||||
|
||||
For practical and historical reasons the actual scanner code lives inside libardour.
|
||||
|
||||
* `libs/auscan/`
|
||||
|
||||
Apple Audio Unit Plugin Scan commandline tool.
|
||||
|
||||
* `libs/fst/`
|
||||
|
||||
VST2/3 plugin scan commandline tools.
|
||||
|
||||
* `libs/vfork/`
|
||||
|
||||
A exec-wrapper which redirects file-descriptors to be used with vfork(2).
|
||||
It is used to launch external applications, without impacting real-time
|
||||
constraints of the calling process.
|
||||
|
||||
|
||||
### Ardour Community Effect (ACE) Plugins
|
||||
|
||||
* `libs/plugins/`
|
||||
|
||||
A *bread and butter* set of LV2 Plugins included with Ardour.
|
||||
|
||||
Many of them are custom version of existing plugins (zamaudio, x42),
|
||||
that have been customized to be bundled with Ardour on all platforms
|
||||
that ardour runs on.
|
||||
|
||||
|
||||
### Independent, standalone libs
|
||||
|
||||
These are 3rd party libs that have been copied into Ardour's source-tree.
|
||||
|
||||
* `libs/aaf/`
|
||||
|
||||
Unmodified <https://github.com/agfline/LibAAF> for importing AAF sessions.
|
||||
|
||||
Use `tools/update_libaaf.sh` to update from upstream.
|
||||
|
||||
* `libs/appleutility/`
|
||||
|
||||
Utility classes, abstraction for CoreAudio and AudioUnits (OSX, macOS)
|
||||
|
||||
* `libs/ardouralsautil/`
|
||||
|
||||
Utility class for device-listing (used by the JACK and ALSA backends).
|
||||
Device-reservation commandline tool (linked against libdbus), which is
|
||||
also available from <https://github.com/x42/alsa_request_device>
|
||||
|
||||
* `libs/clearlooks-newer/`
|
||||
|
||||
GTK theme engine (used by `gtk2_ardour`)
|
||||
|
||||
* `libs/fluidsynth/`
|
||||
|
||||
Stripped down (library only) and slightly customized version of fluidsynth.
|
||||
|
||||
Use `tools/update_fluidsynth.sh` to update from upstream.
|
||||
|
||||
* `libs/hidapi/`
|
||||
|
||||
Unmodified <https://github.com/signal11/hidapi> for interaction with some
|
||||
control surfaces (Push2, NI Maschine)
|
||||
|
||||
* `libs/libltc/`
|
||||
|
||||
Unmodified <https://github.com/x42/libltc/> for Linear Timecode en/decoding. see LTCFrame.
|
||||
|
||||
* `libs/lua/`
|
||||
|
||||
Lua Script interpreter and C++ class abstraction
|
||||
- libs/lua/lua-5.3.5 is unmodified upstream Lua-5.3.5
|
||||
- libs/lua/LuaBridge is a highly customized version of
|
||||
<https://github.com/vinniefalco/LuaBridge> (C++ bindings)
|
||||
|
||||
* `libs/ptformat/`
|
||||
|
||||
Unmodified <https://github.com/zamaudio/ptformat> for loading ProTools sessions.
|
||||
|
||||
* `libs/qm-dsp/`
|
||||
|
||||
Stripped down version of <https://github.com/c4dm/qm-dsp>
|
||||
The Queen Mary DSP library is used by VAMP Plugins.
|
||||
|
||||
* `vamp-plugins`
|
||||
|
||||
VAMP plugins for audio analysis and offline processing (uses qm-dsp)
|
||||
|
||||
* `libs/vamp-pyin/`
|
||||
|
||||
VAMP plugins for pitch and note-tracking (uses qm-dsp), offline analysis
|
||||
|
||||
* `libs/vst3/`
|
||||
|
||||
Stripped down version of Steinberg's VST3 SDK
|
||||
<https://github.com/steinbergmedia/vst3sdk/>
|
||||
use `tools/update_vst3.sh` to update from upstream
|
||||
|
||||
* `libs/zita-convolver/`
|
||||
|
||||
A convolution kernel, so far only available to Lua scripts.
|
||||
|
||||
* `libs/zita-resampler/`
|
||||
|
||||
Efficient resampler with variable rate, useful for adaptive resampling.
|
||||
Mainly used for vari-speed playback. This has been customized for multiple mono
|
||||
channel processing (ArdourZita::VMResampler), and optimized to skip processing for a ratio of 1:1.
|
||||
|
||||
|
||||
## Resource Files
|
||||
|
||||
These are platform independent files, and bundled as-is.
|
||||
|
||||
* `share/export/`
|
||||
|
||||
Export Format and Presets (see <https://manual.ardour.org/exporting/edit-export-format-profile/>)
|
||||
|
||||
* `share/mcp/`
|
||||
|
||||
Mackie control surface device files (see <https://manual.ardour.org/using-control-surfaces/devices-using-mackielogic-control-protocol/>)
|
||||
|
||||
* `share/midi_maps/`
|
||||
|
||||
Generic %MIDI control surface presets
|
||||
|
||||
* `share/osc/`
|
||||
|
||||
[TouchOSC](https://hexler.net/touchosc) layouts for use with Ardour's OSC control surface.
|
||||
|
||||
* `share/patchfiles/`
|
||||
|
||||
MIDNAM files, %MIDI synth descriptions (note-names, CC, PGM names)
|
||||
|
||||
* `share/scripts/`
|
||||
|
||||
Lua scripts (files with a leading underscore are not bundled).
|
||||
see `share/scripts/README` for file name convention.
|
||||
|
||||
* `share/templates/`
|
||||
|
||||
Session templates (currently none)
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
* `doc/`
|
||||
|
||||
Misc developer oriented documentation files and Doxygen
|
||||
|
||||
* `patches/`
|
||||
|
||||
Some .diff files for the build-stack.
|
||||
|
||||
* `tools/`
|
||||
|
||||
Various developer tools, most notably packaging scripts
|
|
@ -1,13 +0,0 @@
|
|||
/** \mainpage Ardour
|
||||
*
|
||||
* Welcome to the in-code documentation for Ardour.
|
||||
*
|
||||
* The main components of Ardour are as follows:
|
||||
* - A GTK2 front-end, in \c gtk2_ardour.
|
||||
* - libardour, the audio-processing back-end, in \c libs/ardour.
|
||||
* - libpbd, a utility library, in \c libs/pbd.
|
||||
*
|
||||
* There are other assorted component libraries:
|
||||
* - gtkmm2ext, an library of extensions to gtkmm2, in \c libs/gtkmm2ext.
|
||||
* - and others...
|
||||
*/
|
|
@ -1,203 +0,0 @@
|
|||
Ardour Source-Tree layout (Feb 2022)
|
||||
|
||||
===== Front Ends =====
|
||||
|
||||
gtk2_ardour/
|
||||
The main Ardour GUI -- This is where most of the complexity is :)
|
||||
It is cleanly separated from the backend and processing engine.
|
||||
|
||||
headless/
|
||||
hardour -- headless Ardour, mostly demo-code how to use Ardour without a GUI.
|
||||
|
||||
session_utils/
|
||||
command-line tools using libardour (e.g. export)
|
||||
|
||||
luasession/
|
||||
arlua -- commandline interface to libardour
|
||||
|
||||
===== LIBRARIES =====
|
||||
A collection of libraries and utility functions. While most are shared
|
||||
libraries, and almost all are exclusive to Ardour.
|
||||
|
||||
libs/
|
||||
|
||||
**** Independent, standalone libs ****
|
||||
|
||||
- libs/appleutility/
|
||||
Utility Classes, abstraction for CoreAudio and AudioUnits (OSX, macOS)
|
||||
|
||||
- libs/ardouralsautil/
|
||||
Utility Class for device-listing (used by the jack and ALSA backends).
|
||||
Device-reservation commandline tool (linked against libdbus), which is
|
||||
also available from https://github.com/x42/alsa_request_device
|
||||
|
||||
- libs/clearlooks-newer/
|
||||
GTK theme engine (used by gtk2_ardour)
|
||||
|
||||
- libs/fluidsynth/
|
||||
Stripped down (library only) and slightly customized version of fluidsynth
|
||||
use tools/update_fluidsynth.sh to update from upstream
|
||||
|
||||
- libs/hidapi/
|
||||
Unmodified https://github.com/signal11/hidapi for interaction with some
|
||||
control surfaces (Push2, NI Maschine)
|
||||
|
||||
- libs/libltc/
|
||||
Unmodified https://github.com/x42/libltc/ for Linear Timecode en/decoding
|
||||
|
||||
- libs/lua/
|
||||
Lua Script interpreter and C++ class abstraction
|
||||
- libs/lua/lua-5.3.5 is unmodified upstream Lua-5.3.5
|
||||
- libs/lua/LuaBridge is a highly customized version of
|
||||
https://github.com/vinniefalco/LuaBridge (C++ bindings)
|
||||
|
||||
- libs/midi++2/
|
||||
(uses libpdb)
|
||||
MIDI parsing, MIDNAM handling, Port abstraction for I/O
|
||||
|
||||
- libs/ptformat/
|
||||
Unmodified https://github.com/zamaudio/ptformat for loading ProTools sessions
|
||||
|
||||
- libs/temporal
|
||||
various utility code for dealing with different kinds of time,
|
||||
including Timecode (FPS) and musical time conversions
|
||||
|
||||
- libs/qm-dsp/
|
||||
Stripped down version of https://github.com/c4dm/qm-dsp
|
||||
The Queen Mary DSP library is used by VAMP Plugins
|
||||
|
||||
- vamp-plugins
|
||||
VAMP plugins for audio analysis and offline processing (uses qm-dsp)
|
||||
|
||||
- libs/vamp-pyin/
|
||||
VAMP plugins for pitch and note-tracking (uses qm-dsp), offline analysis
|
||||
|
||||
- libs/vfork/
|
||||
A exec-wrapper which redirects file-descriptors to be used with vfork(2)
|
||||
|
||||
- libs/vst3/
|
||||
Stripped down version of Steinberg's VST3 SDK
|
||||
https://github.com/steinbergmedia/vst3sdk/
|
||||
see also tools/update_vst3.sh
|
||||
|
||||
- libs/plugins/
|
||||
LV2 Plugins included with Ardour. These are currently mostly
|
||||
independent (a-fluidsynth uses libfluidsynth).
|
||||
Most of them are custom version of existing plugins (zamaudio, x42),
|
||||
that have been customized to be bundled with Ardour on all platforms
|
||||
that ardour runs on.
|
||||
|
||||
- libs/zita-convolver/
|
||||
convolution kernel, so far only available to Lua scripts.
|
||||
|
||||
- libs/zita-resampler/
|
||||
Efficient resampler with variable rate, useful for adaptive resampling.
|
||||
Mainly used for vari-speed playback.
|
||||
|
||||
**** PBD dependent libs ****
|
||||
|
||||
- libs/pbd/
|
||||
Generic non-Ardour-specific utility classes. This is the basis for all Ardour specifics.
|
||||
It provides basic concepts and OS abstractions. The name comes from "Paul
|
||||
Barton-Davis", Paul's full name at the time he started working on working on
|
||||
audio software.
|
||||
|
||||
- libs/evoral/
|
||||
(uses libpbd)
|
||||
Control events, control lists, automation evaluation,
|
||||
parameter descriptions, incl MIDI event abstraction
|
||||
|
||||
- libs/evoral/libsmf/ (contains several non-upstreamed fixes)
|
||||
(used inside evoral)
|
||||
Handling Standard MIDI File format. Abstracted to C++ in SMF.{cc,h}
|
||||
|
||||
- libs/backends/
|
||||
(uses libpdb, ardouralsautil | appleutility, implements libardour interface)
|
||||
Interaction with Operating System's Audio/MIDI API:
|
||||
ALSA, CoreAudio, JACK, PortAudio/ASIO, PulseAudio
|
||||
|
||||
- libs/surfaces/
|
||||
(uses libpbd, libevoral, libtimecode, libardour ;; libgtkmm2ext, libcanvas)
|
||||
Control Surfaces, dynamically loaded by libardour on runtime,
|
||||
to remote-control ardour (midi bindings, network etc).
|
||||
|
||||
- libs/panners/
|
||||
(uses libpdb, implements libardour interface)
|
||||
Pan plugins (stereo-balance, VBAP, etc) are dynamically loaded at runtime.
|
||||
|
||||
- libs/audiographer/
|
||||
(uses libpdb)
|
||||
Mini Ardour inside Ardour to export audio-files from sessions.
|
||||
|
||||
- libs/ardour/
|
||||
(uses pretty much all the libs above)
|
||||
This is it. libardour runs Ardour sessions
|
||||
All realtime processing happens here, plugins are managed etc.
|
||||
|
||||
**** Plugin Scan Tools ****
|
||||
|
||||
- libs/auscan/
|
||||
Apple Audio Unit Plugin Scan commandline tool.
|
||||
|
||||
- libs/fst/
|
||||
VST2/3 plugin scan commandline tool.
|
||||
|
||||
|
||||
**** UI related libs ****
|
||||
|
||||
- libs/gtkmm2ext/
|
||||
(uses libpbd)
|
||||
Utility Library to extend GDK, GTK, and basic abstraction for UIs
|
||||
and event-loops. This library is not limited to the GUI, but also
|
||||
used for other graphical interfaces (e.g. Push2, NI Maschine control
|
||||
surfaces).
|
||||
|
||||
- libs/canvas/
|
||||
(uses libpbd, libgtkmm2ext)
|
||||
Cairo Canvas, provides a slate for scalable drawing and basic layout/packing
|
||||
This is used by gtk2ardour's main editor.
|
||||
|
||||
- libs/widgets/
|
||||
(uses libpbd, libgtkmm2ext ;; libcanvas utils/colors)
|
||||
Ardour GUI widgets (buttons, fader, knobs, etc)
|
||||
|
||||
- libs/waveview/
|
||||
(uses libpbd, libgtkmm2ext, canvas, libardour)
|
||||
Threaded waveform rendering and waveform image cache
|
||||
|
||||
|
||||
===== RESOURCE FILES =====
|
||||
These are bundled as-is.
|
||||
|
||||
share/export/
|
||||
Export Presets
|
||||
|
||||
share/mcp/
|
||||
Mackie control surface device files
|
||||
|
||||
share/midi_maps/
|
||||
Generic MIDI control surface presets
|
||||
|
||||
share/osc/
|
||||
Configuration presets for the OSC control surface
|
||||
|
||||
share/patchfiles/
|
||||
MIDNAM files, MIDI synth descriptions (note-names, CC, PGM names)
|
||||
|
||||
share/scripts/
|
||||
Lua scripts (files with a leading underscore are not bundled)
|
||||
see also share/scripts/README
|
||||
|
||||
share/templates/
|
||||
Session templates (currently none)
|
||||
|
||||
|
||||
===== MISC =====
|
||||
doc/
|
||||
Misc developer oriented documentation files and Doxygen
|
||||
|
||||
patches/
|
||||
Some .diff files for the build-stack.
|
||||
|
||||
tools/
|
||||
Various developer tools, most notably packaging scripts
|
|
@ -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/"));
|
||||
|
|
|
@ -7,3 +7,4 @@ Terminal=false
|
|||
MimeType=application/x-ardour;
|
||||
Type=Application
|
||||
Categories=AudioVideo;Audio;AudioEditing;X-Recorders;X-Multitrack;X-Jack;
|
||||
StartupWMClass=Ardour
|
||||
|
|
|
@ -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'/>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -576,6 +583,14 @@ ARDOUR_UI::install_dependent_actions ()
|
|||
act = ActionManager::register_action (common_actions, "jump-forward-to-mark", _("Jump to Next Mark"), sigc::mem_fun(*editor, &PublicEditor::jump_forward_to_mark));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
|
||||
act = ActionManager::register_action (common_actions, "jump-backward-to-location-mark", _("Jump to Previous Location Mark"),
|
||||
sigc::bind (sigc::mem_fun(*editor, &PublicEditor::jump_backward_to_mark_flagged), Location::Flags (0), Location::Flags (0), Location::IsMark));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
|
||||
act = ActionManager::register_action (common_actions, "jump-forward-to-location-mark", _("Jump to Next Location Mark"),
|
||||
sigc::bind (sigc::mem_fun(*editor, &PublicEditor::jump_forward_to_mark_flagged), Location::Flags (0), Location::Flags (0), Location::IsMark));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
|
||||
for (int i = 1; i <= 9; ++i) {
|
||||
string const a = string_compose(X_("goto-mark-%1"), i);
|
||||
string const n = string_compose(_("Locate to Mark %1"), i);
|
||||
|
@ -783,7 +798,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 ();
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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,13 @@ 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");
|
||||
return;
|
||||
|
||||
/* This is what this method used to do but after ruler consolidation
|
||||
* it is not clear what the correct semantics are/should be.
|
||||
*/
|
||||
|
||||
Glib::RefPtr<ToggleAction> tact; // = ActionManager::get_toggle_action (X_("Rulers"), "toggle-loop-punch-ruler");
|
||||
|
||||
tact->set_sensitive (false);
|
||||
|
||||
|
@ -255,9 +265,15 @@ ARDOUR_UI::show_loop_punch_ruler_and_disallow_hide ()
|
|||
void
|
||||
ARDOUR_UI::reenable_hide_loop_punch_ruler_if_appropriate ()
|
||||
{
|
||||
return;
|
||||
|
||||
/* This is what this method used to do but after ruler consolidation
|
||||
* it is not clear what the correct semantics are/should be.
|
||||
*/
|
||||
|
||||
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 +517,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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ®ion_before = audio_region()->get_state();
|
||||
audio_region()->set_envelope_active(true);
|
||||
XMLNode ®ion_after = audio_region()->get_state();
|
||||
region_memento = new MementoCommand<AudioRegion>(*(audio_region().get()), ®ion_before, ®ion_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);
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -31,3 +31,4 @@ PBD::DebugBits PBD::DEBUG::Accelerators = PBD::new_debug_bit ("accelerators");
|
|||
PBD::DebugBits PBD::DEBUG::GUITiming = PBD::new_debug_bit ("guitiming");
|
||||
PBD::DebugBits PBD::DEBUG::EngineControl = PBD::new_debug_bit ("enginecontrol");
|
||||
PBD::DebugBits PBD::DEBUG::GuiStartup = PBD::new_debug_bit ("guistartup");
|
||||
PBD::DebugBits PBD::DEBUG::TrackDrag = PBD::new_debug_bit ("trackdrag");
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace PBD {
|
|||
extern DebugBits GUITiming;
|
||||
extern DebugBits EngineControl;
|
||||
extern DebugBits GuiStartup;
|
||||
extern DebugBits TrackDrag;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -700,7 +670,6 @@ Editor::Editor ()
|
|||
Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
|
||||
Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
|
||||
Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
|
||||
Location::flags_changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_section_rects, this), gui_context ());
|
||||
|
||||
#if SELECTION_PROPERTIES_BOX_TODO
|
||||
add_notebook_page (_("Selection"), *_properties_box);
|
||||
|
@ -1394,6 +1363,7 @@ Editor::set_session (Session *t)
|
|||
}
|
||||
|
||||
refresh_location_display ();
|
||||
update_section_rects ();
|
||||
|
||||
/* restore rulers before calling set_state() which sets the grid,
|
||||
* which changes rulers and calls store_ruler_visibility() overriding
|
||||
|
@ -1441,6 +1411,7 @@ Editor::set_session (Session *t)
|
|||
_session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
|
||||
_session->auto_loop_location_changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::loop_location_changed, this, _1), gui_context ());
|
||||
_session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
|
||||
Location::flags_changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_section_rects, this), gui_context ());
|
||||
|
||||
_playhead_cursor->track_canvas_item().reparent ((ArdourCanvas::Item*) get_cursor_scroll_group());
|
||||
_playhead_cursor->show ();
|
||||
|
@ -2289,7 +2260,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 +2576,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 +2790,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 +3016,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 +4012,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 +4252,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 +6145,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 +6209,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 +6542,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 +7028,84 @@ 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), *_session);
|
||||
DEBUG_TRACE (DEBUG::TrackDrag, string_compose ("start track drag with %1\n", track_drag));
|
||||
PBD::stacktrace (std::cerr, 20);
|
||||
|
||||
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) {
|
||||
|
||||
/* move threshold */
|
||||
|
||||
if (abs (yo - track_drag->previous) < (int) (4 * UIConfiguration::instance().get_ui_scale())) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::TrackDrag, string_compose ("ending track drag with %1\n", track_drag));
|
||||
delete track_drag;
|
||||
track_drag = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::track_dragging() const
|
||||
{
|
||||
return (bool) track_drag;
|
||||
}
|
||||
|
|
|
@ -105,10 +105,6 @@ namespace ARDOUR {
|
|||
class Track;
|
||||
}
|
||||
|
||||
namespace LADSPA {
|
||||
class Plugin;
|
||||
}
|
||||
|
||||
class AnalysisWindow;
|
||||
class AudioClock;
|
||||
class AudioRegionView;
|
||||
|
@ -601,7 +597,6 @@ public:
|
|||
void metric_get_minsec (std::vector<ArdourCanvas::Ruler::Mark>&, int64_t, int64_t, gint);
|
||||
|
||||
/* editing operations that need to be public */
|
||||
void mouse_add_new_marker (Temporal::timepos_t where, ARDOUR::Location::Flags extra_flags = ARDOUR::Location::Flags (0), int32_t cue_id = 0);
|
||||
void split_regions_at (Temporal::timepos_t const & , RegionSelection&);
|
||||
void split_region_at_points (std::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false);
|
||||
RegionSelection get_regions_from_selection_and_mouse (Temporal::timepos_t const &);
|
||||
|
@ -745,8 +740,8 @@ private:
|
|||
void update_selection_markers ();
|
||||
void update_section_box ();
|
||||
|
||||
void jump_forward_to_mark ();
|
||||
void jump_backward_to_mark ();
|
||||
void jump_forward_to_mark_flagged (ARDOUR::Location::Flags, ARDOUR::Location::Flags, ARDOUR::Location::Flags);
|
||||
void jump_backward_to_mark_flagged (ARDOUR::Location::Flags, ARDOUR::Location::Flags, ARDOUR::Location::Flags);
|
||||
|
||||
struct LocationMarkers {
|
||||
ArdourMarker* start;
|
||||
|
@ -935,10 +930,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 +979,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 +1080,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 +1093,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 +1405,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 +1594,7 @@ private:
|
|||
void clear_xrun_markers ();
|
||||
void clear_ranges ();
|
||||
void clear_cues ();
|
||||
void clear_scenes ();
|
||||
void clear_locations ();
|
||||
void unhide_markers ();
|
||||
void unhide_ranges ();
|
||||
|
@ -1613,7 +1615,7 @@ private:
|
|||
void set_selection_from_loop ();
|
||||
void set_selection_from_region ();
|
||||
|
||||
void add_location_mark (Temporal::timepos_t const & where);
|
||||
void add_location_mark_with_flag (Temporal::timepos_t const & where, ARDOUR::Location::Flags flag, int32_t cue_id);
|
||||
void add_location_from_region ();
|
||||
void add_locations_from_region ();
|
||||
void add_location_from_selection ();
|
||||
|
@ -1789,6 +1791,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 +2152,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;
|
||||
|
@ -2277,7 +2298,7 @@ private:
|
|||
|
||||
/** computes the timeline position for an event whose coordinates
|
||||
* are in canvas units (pixels, scroll offset included). The time
|
||||
* domain used by the return value will match ::default_time_domain()
|
||||
* domain used by the return value will match Editor::default_time_domain()
|
||||
* at the time of calling.
|
||||
*/
|
||||
Temporal::timepos_t canvas_event_time (GdkEvent const*, double* px = 0, double* py = 0) const;
|
||||
|
@ -2593,6 +2614,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, ARDOUR::Session& s)
|
||||
: 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;
|
||||
|
|
|
@ -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"), _("Only 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"), _("Only Cue Markers"), sigc::bind (sigc::mem_fun(*this, &Editor::show_marker_type), CueMarks)));
|
||||
cue_marker_action = Glib::RefPtr<RadioAction>::cast_static (ActionManager::register_radio_action (ruler_actions, marker_choice_group, X_("show-scene-markers"), _("Only Scene Markers"), sigc::bind (sigc::mem_fun(*this, &Editor::show_marker_type), SceneMarks)));
|
||||
location_marker_action = Glib::RefPtr<RadioAction>::cast_static (ActionManager::register_radio_action (ruler_actions, marker_choice_group, X_("show-location-markers"), _("Only 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"), _("Only 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"), _("Only 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"), _("Only 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"), _("Only Named 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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
@ -1180,7 +1180,7 @@ Editor::section_rect_event (GdkEvent* ev, Location* loc, ArdourCanvas::Rectangle
|
|||
MenuList& items (section_box_menu.items());
|
||||
items.clear ();
|
||||
|
||||
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)));
|
||||
items.push_back (MenuElem (_("New Arrangement Marker"), sigc::bind (sigc::mem_fun(*this, &Editor::add_location_mark_with_flag), where, Location::Flags(Location::IsMark | Location::IsSection), 0)));
|
||||
items.push_back (MenuElem (_("Select Arrangement Section"), sigc::bind (sigc::mem_fun(*_sections, &EditorSections::select), l)));
|
||||
#if 0
|
||||
items.push_back (SeparatorElem());
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -327,7 +327,7 @@ protected:
|
|||
|
||||
private:
|
||||
bool _trackview_only; ///< true if pointer y value should always be relative to the top of the trackview group
|
||||
bool _hide_snapped_cursor; ///< set true of ::motion does not call `set_snapped_cursor_position`
|
||||
bool _hide_snapped_cursor; ///< set true of Drag::motion does not call `set_snapped_cursor_position`
|
||||
bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
|
||||
bool _starting_point_passed; ///< true if we called move () with first_move flag, otherwise false
|
||||
bool _initially_vertical; ///< true if after move threshold is passed we appear to be moving vertically; undefined before that
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -27,13 +27,11 @@ enum ItemType {
|
|||
WaveItem,
|
||||
PlayheadCursorItem,
|
||||
MarkerItem,
|
||||
SceneMarkerItem,
|
||||
MarkerBarItem,
|
||||
RangeMarkerBarItem,
|
||||
CdMarkerBarItem,
|
||||
SectionMarkerBarItem,
|
||||
CueMarkerBarItem,
|
||||
VideoBarItem,
|
||||
TransportMarkerBarItem,
|
||||
SelectionItem,
|
||||
ControlPointItem,
|
||||
GainLineItem,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
@ -779,52 +828,6 @@ Editor::LocationMarkers::setup_lines ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::mouse_add_new_marker (timepos_t where, Location::Flags extra_flags, int32_t cue_id)
|
||||
{
|
||||
if (!_session) {
|
||||
return;
|
||||
}
|
||||
|
||||
string markername;
|
||||
string namebase;
|
||||
Location::Flags flags = Location::Flags (extra_flags|Location::IsMark);
|
||||
|
||||
if (flags & Location::IsCueMarker) {
|
||||
/* XXX i18n needed for cue letter names */
|
||||
markername = string_compose (_("cue %1"), cue_marker_name (cue_id));
|
||||
} else {
|
||||
if (flags & Location::IsSection) {
|
||||
namebase = _("verse");
|
||||
} else {
|
||||
namebase = _("mark");
|
||||
}
|
||||
_session->locations()->next_available_name (markername, namebase);
|
||||
|
||||
if (!choose_new_marker_name (markername)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Location *location = new Location (*_session, where, where, markername, flags, cue_id);
|
||||
begin_reversible_command (_("add marker"));
|
||||
|
||||
XMLNode &before = _session->locations()->get_state();
|
||||
_session->locations()->add (location, true);
|
||||
XMLNode &after = _session->locations()->get_state();
|
||||
_session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
|
||||
|
||||
/* find the marker we just added */
|
||||
|
||||
LocationMarkers *lam = find_location_markers (location);
|
||||
if (lam) {
|
||||
/* make it the selected marker */
|
||||
selection->set (lam->start);
|
||||
}
|
||||
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::mouse_add_new_loop (timepos_t where)
|
||||
{
|
||||
|
@ -1887,8 +1890,6 @@ void
|
|||
Editor::new_transport_marker_menu_popdown ()
|
||||
{
|
||||
// hide rects
|
||||
transport_bar_drag_rect->hide();
|
||||
|
||||
_drags->abort ();
|
||||
}
|
||||
|
||||
|
@ -2084,3 +2085,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 = SceneMarks;
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -1820,30 +1793,14 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
|
|||
case MarkerBarItem:
|
||||
if (!_dragging_playhead) {
|
||||
snap_to_with_modifier (where, event, Temporal::RoundNearest, SnapToGrid_Scaled);
|
||||
mouse_add_new_marker (where);
|
||||
}
|
||||
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);
|
||||
add_location_mark (where);
|
||||
}
|
||||
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);
|
||||
mouse_add_new_marker (where, Location::IsSection);
|
||||
}
|
||||
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);
|
||||
add_location_mark (where, Location::Flags (Location::IsMark | Location::IsSection));
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -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()) {
|
||||
|
@ -2277,21 +2348,38 @@ Editor::add_location_from_selection ()
|
|||
}
|
||||
|
||||
void
|
||||
Editor::add_location_mark (timepos_t const & where)
|
||||
Editor::add_location_mark_with_flag (timepos_t const & where, Location::Flags flags, int32_t cue_id)
|
||||
{
|
||||
if (!_session) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_session->locations()->mark_at (where, timecnt_t (1))) {
|
||||
return;
|
||||
}
|
||||
|
||||
string markername;
|
||||
string namebase;
|
||||
|
||||
select_new_marker = true;
|
||||
|
||||
_session->locations()->next_available_name(markername,"mark");
|
||||
if (!choose_new_marker_name(markername)) {
|
||||
if (flags & Location::IsCueMarker) {
|
||||
/* XXX i18n needed for cue letter names */
|
||||
markername = string_compose (_("cue %1"), cue_marker_name (cue_id));
|
||||
} else if (flags & Location::IsSection) {
|
||||
namebase = _("section");
|
||||
} else if (flags & Location::IsCDMarker) {
|
||||
namebase = _("cd trk");
|
||||
} else {
|
||||
namebase = _("mark");
|
||||
}
|
||||
|
||||
_session->locations()->next_available_name(markername, namebase);
|
||||
|
||||
if (!choose_new_marker_name (markername)) {
|
||||
return;
|
||||
}
|
||||
Location *location = new Location (*_session, where, where, markername, Location::IsMark);
|
||||
Location *location = new Location (*_session, where, where, markername, flags, cue_id);
|
||||
begin_reversible_command (_("add marker"));
|
||||
|
||||
XMLNode &before = _session->locations()->get_state();
|
||||
|
@ -2475,13 +2563,13 @@ Editor::add_location_from_region ()
|
|||
/* MARKS */
|
||||
|
||||
void
|
||||
Editor::jump_forward_to_mark ()
|
||||
Editor::jump_forward_to_mark_flagged (Location::Flags whitelist, Location::Flags blacklist, Location::Flags equalist)
|
||||
{
|
||||
if (!_session) {
|
||||
return;
|
||||
}
|
||||
|
||||
timepos_t pos = _session->locations()->first_mark_after (timepos_t (_session->transport_sample()+1));
|
||||
timepos_t pos = _session->locations()->first_mark_after_flagged (timepos_t (_session->transport_sample()+1), true, whitelist, blacklist, equalist);
|
||||
|
||||
if (pos == timepos_t::max (Temporal::AudioTime)) {
|
||||
return;
|
||||
|
@ -2491,13 +2579,13 @@ Editor::jump_forward_to_mark ()
|
|||
}
|
||||
|
||||
void
|
||||
Editor::jump_backward_to_mark ()
|
||||
Editor::jump_backward_to_mark_flagged (Location::Flags whitelist, Location::Flags blacklist, Location::Flags equalist)
|
||||
{
|
||||
if (!_session) {
|
||||
return;
|
||||
}
|
||||
|
||||
timepos_t pos = _session->locations()->first_mark_before (timepos_t (_playhead_cursor->current_sample()));
|
||||
timepos_t pos = _session->locations()->first_mark_before_flagged (timepos_t (_playhead_cursor->current_sample()), true, whitelist, blacklist, equalist);
|
||||
|
||||
//handle the case where we are rolling, and we're less than one-half second past the mark, we want to go to the prior mark...
|
||||
if (_session->transport_rolling()) {
|
||||
|
@ -2612,6 +2700,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 +4866,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;
|
||||
|
@ -7162,7 +7266,7 @@ Editor::set_edit_point ()
|
|||
|
||||
if (selection->markers.empty()) {
|
||||
|
||||
mouse_add_new_marker (where);
|
||||
add_location_mark (where);
|
||||
|
||||
} else {
|
||||
bool ignored;
|
||||
|
|
|
@ -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,86 @@ 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::add_location_mark_with_flag), where, Location::Flags (Location::IsMark), 0)));
|
||||
add_items.push_back (MenuElem (_("Arrangement Marker"), sigc::bind (sigc::mem_fun(*this, &Editor::add_location_mark_with_flag), where, Location::Flags(Location::IsMark | Location::IsSection), 0)));
|
||||
add_items.push_back (MenuElem (_("CD Track Marker"), sigc::bind (sigc::mem_fun(*this, &Editor::add_location_mark_with_flag), where, Location::Flags(Location::IsMark |Location::IsCDMarker), 0)));
|
||||
add_items.push_back (MenuElem ("Cue Marker..."));
|
||||
Gtk::MenuItem& cue_submenu = add_items.back();
|
||||
Gtk::Menu* cue_menu = new Gtk::Menu;
|
||||
MenuList& cue_items = cue_menu->items();
|
||||
cue_items.push_back (MenuElem (_("Stop All Cues"), sigc::bind (sigc::mem_fun (*this, &Editor::add_location_mark_with_flag), where, Location::Flags(Location::IsMark |Location::IsCueMarker), CueRecord::stop_all)));
|
||||
for (int32_t n = 0; n < TriggerBox::default_triggers_per_box; ++n) {
|
||||
cue_items.push_back (MenuElem (string_compose (_("Cue %1"), cue_marker_name (n)), sigc::bind (sigc::mem_fun(*this, &Editor::add_location_mark_with_flag), where, Location::Flags(Location::IsMark |Location::IsCueMarker), n)));
|
||||
}
|
||||
cue_submenu.set_submenu (*cue_menu);
|
||||
|
||||
add_items.push_back (SeparatorElem());
|
||||
|
||||
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_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);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ruler_items.push_back (SeparatorElem());
|
||||
|
||||
/* 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-other-ranges"));
|
||||
|
||||
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 +380,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 +420,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 +440,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 +474,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 +592,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 +610,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));
|
||||
|
@ -931,10 +868,12 @@ Editor::set_timecode_ruler_scale (samplepos_t lower, samplepos_t upper)
|
|||
timecode_ruler_scale = timecode_show_many_hours;
|
||||
timecode_mark_modulo = std::max ((samplecnt_t) 1, 1 + (hours_in_range / timecode_nmarks));
|
||||
}
|
||||
|
||||
timecode_mark_modulo = 1;
|
||||
}
|
||||
|
||||
void
|
||||
Editor::metric_get_timecode (std::vector<ArdourCanvas::Ruler::Mark>& marks, int64_t lower, int64_t /*upper*/, gint /*maxchars*/)
|
||||
Editor::metric_get_timecode (std::vector<ArdourCanvas::Ruler::Mark>& marks, int64_t lower, int64_t upper, gint /*maxchars*/)
|
||||
{
|
||||
samplepos_t pos;
|
||||
samplecnt_t spacer;
|
||||
|
@ -953,146 +892,149 @@ Editor::metric_get_timecode (std::vector<ArdourCanvas::Ruler::Mark>& marks, int6
|
|||
lower = 0;
|
||||
}
|
||||
|
||||
pos = (samplecnt_t) floor (lower);
|
||||
pos = lower;
|
||||
// Find timecode time of this sample (pos)
|
||||
_session->sample_to_timecode (pos, timecode, true /* use_offset */, false /* use_subframes */);
|
||||
|
||||
switch (timecode_ruler_scale) {
|
||||
case timecode_show_bits:
|
||||
// Find timecode time of this sample (pos) with subframe accuracy
|
||||
_session->sample_to_timecode(pos, timecode, true /* use_offset */, true /* use_subframes */);
|
||||
for (n = 0; n < timecode_nmarks; n++) {
|
||||
_session->timecode_to_sample(timecode, pos, true /* use_offset */, true /* use_subframes */);
|
||||
if ((timecode.subframes % timecode_mark_modulo) == 0) {
|
||||
if (timecode.subframes == 0) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
|
||||
if (pos >= lower) {
|
||||
if ((timecode.subframes % timecode_mark_modulo) == 0) {
|
||||
if (timecode.subframes == 0) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
|
||||
} else {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Minor;
|
||||
snprintf (buf, sizeof(buf), ".%02u", timecode.subframes);
|
||||
}
|
||||
} else {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Minor;
|
||||
snprintf (buf, sizeof(buf), ".%02u", timecode.subframes);
|
||||
snprintf (buf, sizeof(buf)," ");
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
}
|
||||
} else {
|
||||
snprintf (buf, sizeof(buf)," ");
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
mark.label = buf;
|
||||
mark.position = pos;
|
||||
marks.push_back (mark);
|
||||
}
|
||||
mark.label = buf;
|
||||
mark.position = pos;
|
||||
marks.push_back (mark);
|
||||
// Increment subframes by one
|
||||
Timecode::increment_subframes (timecode, _session->config.get_subframes_per_frame());
|
||||
}
|
||||
break;
|
||||
|
||||
case timecode_show_samples:
|
||||
// Find timecode time of this sample (pos)
|
||||
_session->sample_to_timecode (pos, timecode, true /* use_offset */, false /* use_subframes */);
|
||||
// Go to next whole sample down
|
||||
Timecode::frames_floot (timecode);
|
||||
for (n = 0; n < timecode_nmarks; n++) {
|
||||
_session->timecode_to_sample (timecode, pos, true /* use_offset */, false /* use_subframes */);
|
||||
if ((timecode.frames % timecode_mark_modulo) == 0) {
|
||||
if (timecode.frames == 0) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
if (pos >= lower) {
|
||||
if ((timecode.frames % timecode_mark_modulo) == 0) {
|
||||
if (timecode.frames == 0) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
} else {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Minor;
|
||||
}
|
||||
mark.position = pos;
|
||||
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
|
||||
} else {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Minor;
|
||||
snprintf (buf, sizeof(buf)," ");
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
mark.position = pos;
|
||||
}
|
||||
mark.position = pos;
|
||||
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
|
||||
} else {
|
||||
snprintf (buf, sizeof(buf)," ");
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
mark.position = pos;
|
||||
mark.label = buf;
|
||||
marks.push_back (mark);
|
||||
}
|
||||
mark.label = buf;
|
||||
marks.push_back (mark);
|
||||
Timecode::increment (timecode, _session->config.get_subframes_per_frame());
|
||||
}
|
||||
break;
|
||||
|
||||
case timecode_show_seconds:
|
||||
// Find timecode time of this sample (pos)
|
||||
_session->sample_to_timecode (pos, timecode, true /* use_offset */, false /* use_subframes */);
|
||||
// Go to next whole second down
|
||||
Timecode::seconds_floor (timecode);
|
||||
for (n = 0; n < timecode_nmarks; n++) {
|
||||
_session->timecode_to_sample (timecode, pos, true /* use_offset */, false /* use_subframes */);
|
||||
if ((timecode.seconds % timecode_mark_modulo) == 0) {
|
||||
if (timecode.seconds == 0) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
mark.position = pos;
|
||||
if (pos >= lower) {
|
||||
if ((timecode.seconds % timecode_mark_modulo) == 0) {
|
||||
if (timecode.seconds == 0) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
mark.position = pos;
|
||||
} else {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Minor;
|
||||
mark.position = pos;
|
||||
}
|
||||
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
|
||||
} else {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Minor;
|
||||
snprintf (buf, sizeof(buf)," ");
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
mark.position = pos;
|
||||
}
|
||||
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
|
||||
} else {
|
||||
snprintf (buf, sizeof(buf)," ");
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
mark.position = pos;
|
||||
mark.label = buf;
|
||||
marks.push_back (mark);
|
||||
}
|
||||
mark.label = buf;
|
||||
marks.push_back (mark);
|
||||
Timecode::increment_seconds (timecode, _session->config.get_subframes_per_frame());
|
||||
}
|
||||
break;
|
||||
|
||||
case timecode_show_minutes:
|
||||
//Find timecode time of this sample (pos)
|
||||
_session->sample_to_timecode (pos, timecode, true /* use_offset */, false /* use_subframes */);
|
||||
// Go to next whole minute down
|
||||
Timecode::minutes_floor (timecode);
|
||||
for (n = 0; n < timecode_nmarks; n++) {
|
||||
_session->timecode_to_sample (timecode, pos, true /* use_offset */, false /* use_subframes */);
|
||||
if ((timecode.minutes % timecode_mark_modulo) == 0) {
|
||||
if (timecode.minutes == 0) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
if (pos >= lower) {
|
||||
if ((timecode.minutes % timecode_mark_modulo) == 0) {
|
||||
if (timecode.minutes == 0) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
} else {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Minor;
|
||||
}
|
||||
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
|
||||
} else {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Minor;
|
||||
snprintf (buf, sizeof(buf)," ");
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
}
|
||||
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
|
||||
} else {
|
||||
snprintf (buf, sizeof(buf)," ");
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
mark.label = buf;
|
||||
mark.position = pos;
|
||||
marks.push_back (mark);
|
||||
}
|
||||
mark.label = buf;
|
||||
mark.position = pos;
|
||||
marks.push_back (mark);
|
||||
Timecode::increment_minutes (timecode, _session->config.get_subframes_per_frame());
|
||||
}
|
||||
break;
|
||||
case timecode_show_hours:
|
||||
// Find timecode time of this sample (pos)
|
||||
_session->sample_to_timecode (pos, timecode, true /* use_offset */, false /* use_subframes */);
|
||||
// Go to next whole hour down
|
||||
Timecode::hours_floor (timecode);
|
||||
for (n = 0; n < timecode_nmarks; n++) {
|
||||
_session->timecode_to_sample (timecode, pos, true /* use_offset */, false /* use_subframes */);
|
||||
if ((timecode.hours % timecode_mark_modulo) == 0) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
|
||||
} else {
|
||||
snprintf (buf, sizeof(buf)," ");
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
if (pos >= lower) {
|
||||
if ((timecode.hours % timecode_mark_modulo) == 0) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
|
||||
} else {
|
||||
snprintf (buf, sizeof(buf)," ");
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Micro;
|
||||
}
|
||||
mark.label = buf;
|
||||
mark.position = pos;
|
||||
marks.push_back (mark);
|
||||
}
|
||||
mark.label = buf;
|
||||
mark.position = pos;
|
||||
marks.push_back (mark);
|
||||
Timecode::increment_hours (timecode, _session->config.get_subframes_per_frame());
|
||||
}
|
||||
break;
|
||||
case timecode_show_many_hours:
|
||||
// Find timecode time of this sample (pos)
|
||||
_session->sample_to_timecode (pos, timecode, true /* use_offset */, false /* use_subframes */);
|
||||
// Go to next whole hour down
|
||||
Timecode::hours_floor (timecode);
|
||||
|
||||
for (n = 0; n < timecode_nmarks;) {
|
||||
_session->timecode_to_sample (timecode, pos, true /* use_offset */, false /* use_subframes */);
|
||||
if ((timecode.hours % timecode_mark_modulo) == 0) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
|
||||
mark.label = buf;
|
||||
mark.position = pos;
|
||||
marks.push_back (mark);
|
||||
++n;
|
||||
if (pos >= lower) {
|
||||
if ((timecode.hours % timecode_mark_modulo) == 0) {
|
||||
mark.style = ArdourCanvas::Ruler::Mark::Major;
|
||||
snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
|
||||
mark.label = buf;
|
||||
mark.position = pos;
|
||||
marks.push_back (mark);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
/* can't use Timecode::increment_hours() here because we may be traversing thousands of hours
|
||||
* and doing it 1 hour at a time is just stupid (and slow).
|
||||
|
@ -1240,7 +1182,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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -2863,6 +2863,9 @@ EngineControl::on_latency_expand ()
|
|||
lbl_midi_system.hide ();
|
||||
midi_option_combo.hide ();
|
||||
midi_devices_button.hide ();
|
||||
if (!UIConfiguration::instance().get_allow_to_resize_engine_dialog ()) {
|
||||
resize (1, 1); // shrink window
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -831,19 +831,19 @@ ExportReport::init (const AnalysisResults & ar, bool with_file)
|
|||
get_vbox ()->set_spacing (4);
|
||||
get_vbox ()->pack_start (pages, false, false);
|
||||
|
||||
if (_session) {
|
||||
if (_session && _session->the_auditioner()) {
|
||||
_session->AuditionActive.connect(auditioner_connections, invalidator (*this), boost::bind (&ExportReport::audition_active, this, _1), gui_context());
|
||||
_session->the_auditioner()->AuditionProgress.connect(auditioner_connections, invalidator (*this), boost::bind (&ExportReport::audition_progress, this, _1, _2), gui_context());
|
||||
}
|
||||
|
||||
if (_session && with_file) {
|
||||
if (_session && with_file && _session->the_auditioner()) {
|
||||
play_btn = add_button (Stock::MEDIA_PLAY, RESPONSE_ACCEPT);
|
||||
stop_btn = add_button (Stock::MEDIA_STOP, RESPONSE_ACCEPT);
|
||||
}
|
||||
add_button (Stock::CLOSE, RESPONSE_CLOSE);
|
||||
|
||||
set_default_response (RESPONSE_CLOSE);
|
||||
if (_session && with_file) {
|
||||
if (_session && with_file && _session->the_auditioner()) {
|
||||
stop_btn->signal_clicked().connect (sigc::mem_fun (*this, &ExportReport::stop_audition));
|
||||
play_btn->signal_clicked().connect (sigc::mem_fun (*this, &ExportReport::play_audition));
|
||||
stop_btn->set_sensitive (false);
|
||||
|
@ -908,7 +908,7 @@ ExportReport::audition_active (bool active)
|
|||
void
|
||||
ExportReport::audition (std::string path, unsigned n_chn, int page)
|
||||
{
|
||||
assert (_session);
|
||||
assert (_session && _session->the_auditioner());
|
||||
_session->cancel_audition();
|
||||
|
||||
if (n_chn ==0) { return; }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -363,14 +363,17 @@ GroupTabs::get_menu (RouteGroup* g, bool in_tab_area)
|
|||
const VCAList vcas = _session->vca_manager().vcas ();
|
||||
|
||||
if (!in_tab_area) {
|
||||
/* context menu is not for a group tab, show the "create new
|
||||
from" items here
|
||||
/* context menu is not for a group tab (e.g. mixer sidebar).
|
||||
* Show the "create new from" items here.
|
||||
*/
|
||||
add_new_from_items (items);
|
||||
}
|
||||
|
||||
if (g) {
|
||||
if (!in_tab_area && g) {
|
||||
items.push_back (SeparatorElem());
|
||||
}
|
||||
|
||||
if (g) {
|
||||
items.push_back (MenuElem (_("Edit Group..."), sigc::bind (sigc::mem_fun (*this, &GroupTabs::edit_group), g)));
|
||||
items.push_back (MenuElem (_("Collect Group"), sigc::bind (sigc::mem_fun (*this, &GroupTabs::collect), g)));
|
||||
items.push_back (MenuElem (_("Remove Group"), sigc::bind (sigc::mem_fun (*this, &GroupTabs::remove_group), g)));
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
@ -1027,7 +1036,7 @@ LuaInstance::register_classes (lua_State* L, bool sandbox)
|
|||
|
||||
.addRefFunction ("find_location_from_marker", &PublicEditor::find_location_from_marker)
|
||||
.addFunction ("find_marker_from_location_id", &PublicEditor::find_marker_from_location_id)
|
||||
.addFunction ("mouse_add_new_marker", &PublicEditor::mouse_add_new_marker)
|
||||
.addFunction ("mouse_add_new_marker", &PublicEditor::add_location_mark)
|
||||
#if 0
|
||||
.addFunction ("get_regions_at", &PublicEditor::get_regions_at)
|
||||
.addFunction ("get_regions_after", &PublicEditor::get_regions_after)
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -910,11 +910,8 @@ MidiRegionView::create_note_at (timepos_t const & t, double y, Temporal::Beats l
|
|||
apply_note_diff();
|
||||
|
||||
trackview.editor().set_selected_midi_region_view (*this);
|
||||
list<Evoral::event_id_t> to_be_selected;
|
||||
to_be_selected.push_back (new_note->id());
|
||||
select_notes (to_be_selected, true);
|
||||
|
||||
play_midi_note (new_note);
|
||||
/* apply_note_diff above selects and plays the newly created note */
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2548,13 +2545,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 +4748,6 @@ MidiRegionView::note_to_y(uint8_t note) const
|
|||
void
|
||||
MidiRegionView::quantize_selected_notes ()
|
||||
{
|
||||
std::cerr << "QSN!\n";
|
||||
|
||||
RegionSelection rs;
|
||||
rs.push_back (this);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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&);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -34,22 +34,15 @@ NotePlayer::NotePlayer (std::shared_ptr<MidiTrack> mt)
|
|||
|
||||
NotePlayer::~NotePlayer ()
|
||||
{
|
||||
clear ();
|
||||
}
|
||||
|
||||
void
|
||||
NotePlayer::add (std::shared_ptr<NoteType> note)
|
||||
{
|
||||
/* Must not be called once play() has been called */
|
||||
notes.push_back (note);
|
||||
}
|
||||
|
||||
void
|
||||
NotePlayer::clear ()
|
||||
{
|
||||
off ();
|
||||
notes.clear ();
|
||||
}
|
||||
|
||||
void
|
||||
NotePlayer::on ()
|
||||
{
|
||||
|
@ -63,8 +56,7 @@ NotePlayer::play ()
|
|||
{
|
||||
on ();
|
||||
|
||||
/* note: if there is more than 1 note, we will silence them all at the same time
|
||||
*/
|
||||
/* note: if there is more than 1 note, we will silence them all at the same time */
|
||||
|
||||
const uint32_t note_length_ms = 100;
|
||||
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
|
||||
#include "evoral/Note.h"
|
||||
|
||||
namespace Temporal {
|
||||
class Beats;
|
||||
}
|
||||
|
||||
namespace ARDOUR {
|
||||
class MidiTrack;
|
||||
}
|
||||
|
@ -40,13 +44,11 @@ public:
|
|||
|
||||
void add (std::shared_ptr<NoteType>);
|
||||
void play ();
|
||||
void on ();
|
||||
void off ();
|
||||
void clear ();
|
||||
|
||||
static bool _off (NotePlayer*);
|
||||
|
||||
private:
|
||||
void on ();
|
||||
void off ();
|
||||
static bool _off (NotePlayer*);
|
||||
typedef std::vector< std::shared_ptr<NoteType> > Notes;
|
||||
|
||||
std::shared_ptr<ARDOUR::MidiTrack> track;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -48,10 +48,6 @@ namespace Gtk {
|
|||
class CheckMenuItem;
|
||||
}
|
||||
|
||||
namespace Pango {
|
||||
class Container;
|
||||
}
|
||||
|
||||
class Panner2dWindow;
|
||||
|
||||
class Panner2d : public Gtk::DrawingArea
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
2748
gtk2_ardour/po/de.po
2748
gtk2_ardour/po/de.po
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||
|
||||
|
|
4652
gtk2_ardour/po/ru.po
4652
gtk2_ardour/po/ru.po
File diff suppressed because it is too large
Load Diff
|
@ -292,9 +292,7 @@ PortGroupList::~PortGroupList()
|
|||
}
|
||||
|
||||
void
|
||||
PortGroupList::maybe_add_processor_to_list (
|
||||
std::weak_ptr<Processor> wp, list<std::shared_ptr<IO> >* route_ios, bool inputs, set<std::shared_ptr<IO> >& used_io
|
||||
)
|
||||
PortGroupList::maybe_add_processor_to_list (std::weak_ptr<Processor> wp, list<std::shared_ptr<IO> >* route_ios, bool inputs, set<std::shared_ptr<IO> >& used_io)
|
||||
{
|
||||
std::shared_ptr<Processor> p (wp.lock());
|
||||
|
||||
|
@ -302,6 +300,14 @@ PortGroupList::maybe_add_processor_to_list (
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef LIVETRAX
|
||||
std::shared_ptr<Delivery> d = std::dynamic_pointer_cast<Delivery> (p);
|
||||
|
||||
if (d && d->role() == Delivery::Main) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::shared_ptr<IOProcessor> iop = std::dynamic_pointer_cast<IOProcessor> (p);
|
||||
|
||||
if (iop) {
|
||||
|
@ -318,7 +324,9 @@ PortGroupList::maybe_add_processor_to_list (
|
|||
struct RouteIOs {
|
||||
RouteIOs (std::shared_ptr<Route> r, std::shared_ptr<IO> i) {
|
||||
route = r;
|
||||
ios.push_back (i);
|
||||
if (i) {
|
||||
ios.push_back (i);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Route> route;
|
||||
|
@ -365,11 +373,11 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
|
|||
std::shared_ptr<RouteList const> routes = session->get_routes ();
|
||||
list<RouteIOs> route_ios;
|
||||
|
||||
for (RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
|
||||
for (auto const & r : *routes) {
|
||||
|
||||
/* we never show the monitor bus inputs */
|
||||
|
||||
if (inputs && (*i)->is_monitor()) {
|
||||
if (inputs && r->is_monitor()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -379,12 +387,20 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
|
|||
*/
|
||||
|
||||
set<std::shared_ptr<IO> > used_io;
|
||||
std::shared_ptr<IO> io = inputs ? (*i)->input() : (*i)->output();
|
||||
std::shared_ptr<IO> io;
|
||||
|
||||
#ifdef LIVETRAX
|
||||
if (inputs) {
|
||||
io = r->input();
|
||||
used_io.insert (io);
|
||||
}
|
||||
#else
|
||||
io = inputs ? r->input() : r->output();
|
||||
used_io.insert (io);
|
||||
#endif
|
||||
|
||||
RouteIOs rb (*i, io);
|
||||
(*i)->foreach_processor (boost::bind (&PortGroupList::maybe_add_processor_to_list, this, _1, &rb.ios, inputs, used_io));
|
||||
|
||||
RouteIOs rb (r, io);
|
||||
r->foreach_processor (boost::bind (&PortGroupList::maybe_add_processor_to_list, this, _1, &rb.ios, inputs, used_io));
|
||||
route_ios.push_back (rb);
|
||||
}
|
||||
|
||||
|
@ -393,25 +409,25 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
|
|||
|
||||
/* Now put the bundles that belong to these sorted RouteIOs into the PortGroup. */
|
||||
|
||||
for (list<RouteIOs>::iterator i = route_ios.begin(); i != route_ios.end(); ++i) {
|
||||
TimeAxisView* tv = PublicEditor::instance().time_axis_view_from_stripable (i->route);
|
||||
for (auto & rio : route_ios) {
|
||||
TimeAxisView* tv = PublicEditor::instance().time_axis_view_from_stripable (rio.route);
|
||||
|
||||
/* Work out which group to put these IOs' bundles in */
|
||||
std::shared_ptr<PortGroup> g;
|
||||
if (std::dynamic_pointer_cast<Track> (i->route)) {
|
||||
if (std::dynamic_pointer_cast<Track> (rio.route)) {
|
||||
g = track;
|
||||
} else {
|
||||
g = bus;
|
||||
}
|
||||
|
||||
for (list<std::shared_ptr<IO> >::iterator j = i->ios.begin(); j != i->ios.end(); ++j) {
|
||||
for (auto & io : rio.ios) {
|
||||
/* Only add the bundle if there is at least one port
|
||||
* with a type that's been asked for */
|
||||
if (type == DataType::NIL || (*j)->bundle()->nchannels().n(type) > 0) {
|
||||
if (type == DataType::NIL || io->bundle()->nchannels().n(type) > 0) {
|
||||
if (tv) {
|
||||
g->add_bundle ((*j)->bundle(), *j, tv->color ());
|
||||
g->add_bundle (io->bundle(), io, tv->color ());
|
||||
} else {
|
||||
g->add_bundle ((*j)->bundle(), *j);
|
||||
g->add_bundle (io->bundle(), io);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -419,7 +435,7 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
|
|||
/* When on input side, let's look for sidechains in the route's plugins
|
||||
to display them right next to their route */
|
||||
for (uint32_t n = 0; inputs; ++n) {
|
||||
std::shared_ptr<Processor> p = (i->route)->nth_plugin (n);
|
||||
std::shared_ptr<Processor> p = (rio.route)->nth_plugin (n);
|
||||
if (!p) {
|
||||
break;
|
||||
}
|
||||
|
@ -462,7 +478,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());
|
||||
}
|
||||
|
@ -475,11 +493,11 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
|
|||
|
||||
std::shared_ptr<Bundle> sync (new Bundle (_("Sync"), inputs));
|
||||
AudioEngine* ae = AudioEngine::instance();
|
||||
TransportMasterManager::TransportMasters const & tm (TransportMasterManager::instance().transport_masters());
|
||||
TransportMasterManager::TransportMasters const & tms (TransportMasterManager::instance().transport_masters());
|
||||
|
||||
for (TransportMasterManager::TransportMasters::const_iterator i = tm.begin(); i != tm.end(); ++i) {
|
||||
for (auto const & tm : tms) {
|
||||
|
||||
std::shared_ptr<Port> port = (*i)->port ();
|
||||
std::shared_ptr<Port> port = tm->port ();
|
||||
|
||||
if (!port) {
|
||||
continue;
|
||||
|
@ -489,7 +507,7 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
|
|||
continue;
|
||||
}
|
||||
|
||||
sync->add_channel ((*i)->name(), DataType::AUDIO, ae->make_port_name_non_relative (port->name()));
|
||||
sync->add_channel (tm->name(), DataType::AUDIO, ae->make_port_name_non_relative (port->name()));
|
||||
}
|
||||
|
||||
program->add_bundle (sync);
|
||||
|
@ -753,7 +771,7 @@ PortGroupList::add_bundles_for_ports (std::vector<std::string> const & p, ARDOUR
|
|||
if (pf != cp && !nb.empty()) {
|
||||
std::shared_ptr<Bundle> b = make_bundle_from_ports (nb, type, inputs);
|
||||
group->add_bundle (b, allow_dups);
|
||||
nb.clear();
|
||||
nb.clear();
|
||||
}
|
||||
cp = pf;
|
||||
nb.push_back(s);
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -257,14 +257,23 @@ public:
|
|||
virtual void add_bbt_marker_at_playhead_cursor () = 0;
|
||||
virtual void add_location_from_playhead_cursor () = 0;
|
||||
virtual void remove_location_at_playhead_cursor () = 0;
|
||||
virtual void add_location_mark (Temporal::timepos_t const & where) = 0;
|
||||
void add_location_mark (Temporal::timepos_t const & where, ARDOUR::Location::Flags flags = ARDOUR::Location::IsMark, int32_t cue_id = 0) {
|
||||
add_location_mark_with_flag (where, flags, cue_id);
|
||||
}
|
||||
virtual void add_location_mark_with_flag (Temporal::timepos_t const & where, ARDOUR::Location::Flags, int32_t cue_id) = 0;
|
||||
virtual void update_grid () = 0;
|
||||
virtual void remove_tracks () = 0;
|
||||
virtual void set_loop_range (Temporal::timepos_t const & start, Temporal::timepos_t const & end, std::string cmd) = 0;
|
||||
virtual void set_punch_range (Temporal::timepos_t const & start, Temporal::timepos_t const & end, std::string cmd) = 0;
|
||||
|
||||
virtual void jump_forward_to_mark () = 0;
|
||||
virtual void jump_backward_to_mark () = 0;
|
||||
void jump_forward_to_mark () {
|
||||
jump_forward_to_mark_flagged (ARDOUR::Location::Flags (0), ARDOUR::Location::Flags (0), ARDOUR::Location::Flags (0));
|
||||
}
|
||||
void jump_backward_to_mark () {
|
||||
jump_backward_to_mark_flagged (ARDOUR::Location::Flags (0), ARDOUR::Location::Flags (0), ARDOUR::Location::Flags (0));
|
||||
}
|
||||
virtual void jump_forward_to_mark_flagged (ARDOUR::Location::Flags whitelist, ARDOUR::Location::Flags blacklist, ARDOUR::Location::Flags equalist) = 0;
|
||||
virtual void jump_backward_to_mark_flagged (ARDOUR::Location::Flags whitelist, ARDOUR::Location::Flags blacklist, ARDOUR::Location::Flags equalist) = 0;
|
||||
|
||||
virtual void set_session_start_from_playhead () = 0;
|
||||
virtual void set_session_end_from_playhead () = 0;
|
||||
|
@ -391,7 +400,6 @@ public:
|
|||
virtual void toggle_meter_updating() = 0;
|
||||
virtual void split_regions_at (Temporal::timepos_t const &, RegionSelection&) = 0;
|
||||
virtual void split_region_at_points (std::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false) = 0;
|
||||
virtual void mouse_add_new_marker (Temporal::timepos_t where, ARDOUR::Location::Flags extra_flags = ARDOUR::Location::Flags (0), int32_t cue_id = 0) = 0;
|
||||
virtual void foreach_time_axis_view (sigc::slot<void,TimeAxisView&>) = 0;
|
||||
virtual void add_to_idle_resize (TimeAxisView*, int32_t) = 0;
|
||||
virtual Temporal::timecnt_t get_nudge_distance (Temporal::timepos_t const & pos, Temporal::timecnt_t& next) = 0;
|
||||
|
@ -588,6 +596,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;
|
||||
|
|
|
@ -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")));
|
||||
|
@ -3727,6 +3739,20 @@ These settings will only take effect after %1 is restarted.\n\
|
|||
add_option (_("Transport"), psc);
|
||||
|
||||
|
||||
bo = new BoolOption ("mark-at-pgm-change",
|
||||
_("Create a marker when a MIDI program change is received (and RECORDING)"),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::get_mark_at_pgm_change),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::set_mark_at_pgm_change)
|
||||
);
|
||||
add_option (_("Transport"), bo);
|
||||
|
||||
bo = new BoolOption ("locate-to-pgm-change",
|
||||
_("Locate to the next matching scene marker when a MIDI program change is received (and NOT recording)"),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::get_locate_to_pgm_change),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::set_locate_to_pgm_change)
|
||||
);
|
||||
add_option (_("Transport"), bo);
|
||||
|
||||
add_option (_("Transport"), new OptionEditorHeading (_("Looping")));
|
||||
|
||||
bo = new BoolOption (
|
||||
|
@ -4894,6 +4920,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")));
|
||||
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue