mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-19 21:26:26 +01:00
[Summary] Merging from GIT
[Details] Starting point: Mar 24 2014, 11:47 PM Commit:87184ab80dTarget point: Commit:59e6694405Apr 16 2014, 4:01 PM [git-p4: depot-paths = "//Abdaw/dev_main/tracks/": change = 453690]
This commit is contained in:
parent
0046ee6488
commit
ce2a519afa
103 changed files with 2160 additions and 915 deletions
|
|
@ -85,15 +85,15 @@ ActionManager::load_menus (const string& menus_file)
|
|||
info << string_compose (_("Loading menus from %1"), ui_file) << endmsg;
|
||||
loaded = true;
|
||||
} catch (Glib::MarkupError& err) {
|
||||
error << string_compose (_("badly formatted UI definition file: %1"), err.what()) << endmsg;
|
||||
cerr << string_compose (_("badly formatted UI definition file: %1"), err.what()) << endl;
|
||||
error << string_compose (_("badly formatted menu definition file: %1"), err.what()) << endmsg;
|
||||
cerr << string_compose (_("badly formatted menu definition file: %1"), err.what()) << endl;
|
||||
} catch (...) {
|
||||
error << string_compose (_("%1 menu definition file not found"), PROGRAM_NAME) << endmsg;
|
||||
}
|
||||
|
||||
if (!loaded) {
|
||||
cerr << string_compose (_("%1 will not work without a valid ardour.menus file"), PROGRAM_NAME) << endl;
|
||||
error << string_compose (_("%1 will not work without a valid ardour.menus file"), PROGRAM_NAME) << endmsg;
|
||||
cerr << string_compose (_("%1 will not work without a valid menu definition file"), PROGRAM_NAME) << endl;
|
||||
error << string_compose (_("%1 will not work without a valid menu definition file"), PROGRAM_NAME) << endmsg;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -374,6 +374,7 @@ AnalysisWindow::analyze_data (Gtk::Button * /*button*/)
|
|||
|
||||
free(buf);
|
||||
free(mixbuf);
|
||||
free(gain);
|
||||
|
||||
track_list_ready = true;
|
||||
} /* end lock */
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ ArdourButton::render (cairo_t* cr)
|
|||
}
|
||||
}
|
||||
|
||||
if ( ((_elements & FlatFace)==FlatFace) && (active_state() != Gtkmm2ext::ExplicitActive) ) {
|
||||
if ( ((_elements & Inset)==Inset) && (active_state() != Gtkmm2ext::ExplicitActive) ) {
|
||||
|
||||
if ( !_flat_buttons ) {
|
||||
float rheight = get_height()*0.5-REFLECTION_HEIGHT;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class ArdourButton : public CairoWidget , public Gtkmm2ext::Activatable
|
|||
Body = 0x2,
|
||||
Text = 0x4,
|
||||
Indicator = 0x8,
|
||||
FlatFace = 0x10,
|
||||
Inset = 0x10,
|
||||
};
|
||||
|
||||
static Element default_elements;
|
||||
|
|
|
|||
|
|
@ -1659,10 +1659,10 @@ ARDOUR_UI::session_add_mixed_track (const ChanCount& input, const ChanCount& out
|
|||
|
||||
catch (...) {
|
||||
MessageDialog msg (*editor,
|
||||
string_compose (_("There are insufficient JACK ports available\n\
|
||||
string_compose (_("There are insufficient ports available\n\
|
||||
to create a new track or bus.\n\
|
||||
You should save %1, exit and\n\
|
||||
restart JACK with more ports."), PROGRAM_NAME));
|
||||
restart with more ports."), PROGRAM_NAME));
|
||||
msg.run ();
|
||||
}
|
||||
}
|
||||
|
|
@ -1720,10 +1720,10 @@ ARDOUR_UI::session_add_audio_route (
|
|||
|
||||
catch (...) {
|
||||
MessageDialog msg (*editor,
|
||||
string_compose (_("There are insufficient JACK ports available\n\
|
||||
string_compose (_("There are insufficient ports available\n\
|
||||
to create a new track or bus.\n\
|
||||
You should save %1, exit and\n\
|
||||
restart JACK with more ports."), PROGRAM_NAME));
|
||||
restart with more ports."), PROGRAM_NAME));
|
||||
pop_back_splash (msg);
|
||||
msg.run ();
|
||||
}
|
||||
|
|
@ -1885,12 +1885,25 @@ ARDOUR_UI::transport_roll ()
|
|||
bool rolling = _session->transport_rolling();
|
||||
|
||||
if (_session->get_play_loop()) {
|
||||
|
||||
/* If loop playback is not a mode, then we should cancel
|
||||
it when this action is requested. If it is a mode
|
||||
we just leave it in place.
|
||||
*/
|
||||
|
||||
if (!Config->get_loop_is_mode()) {
|
||||
/* XXX it is not possible to just leave seamless loop and keep
|
||||
playing at present (nov 4th 2009)
|
||||
*/
|
||||
if (!Config->get_seamless_loop()) {
|
||||
/* stop loop playback and stop rolling */
|
||||
_session->request_play_loop (false, true);
|
||||
} else if (rolling) {
|
||||
/* stop loop playback but keep rolling */
|
||||
_session->request_play_loop (false, false);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (_session->get_play_range () && !Config->get_always_play_range()) {
|
||||
/* stop playing a range if we currently are */
|
||||
_session->request_play_range (0, true);
|
||||
|
|
@ -1947,7 +1960,7 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
|
|||
/* disk buffers are normal, so we can keep playing */
|
||||
affect_transport = false;
|
||||
}
|
||||
_session->request_play_loop (false, true);
|
||||
_session->request_play_loop (false, affect_transport);
|
||||
} else if (_session->get_play_range ()) {
|
||||
affect_transport = false;
|
||||
_session->request_play_range (0, true);
|
||||
|
|
@ -1978,16 +1991,23 @@ ARDOUR_UI::toggle_session_auto_loop ()
|
|||
|
||||
if (_session->get_play_loop()) {
|
||||
|
||||
if (_session->transport_rolling()) {
|
||||
/* looping enabled, our job is to disable it */
|
||||
|
||||
_session->request_locate (looploc->start(), true);
|
||||
_session->request_play_loop (false);
|
||||
|
||||
} else {
|
||||
_session->request_play_loop (false);
|
||||
|
||||
/* looping not enabled, our job is to enable it.
|
||||
|
||||
loop-is-NOT-mode: this action always starts the transport rolling.
|
||||
loop-IS-mode: this action simply sets the loop play mechanism, but
|
||||
does not start transport.
|
||||
*/
|
||||
if (Config->get_loop_is_mode()) {
|
||||
_session->request_play_loop (true, false);
|
||||
} else {
|
||||
_session->request_play_loop (true, true);
|
||||
}
|
||||
} else {
|
||||
_session->request_play_loop (true);
|
||||
}
|
||||
|
||||
//show the loop markers
|
||||
|
|
@ -2115,7 +2135,11 @@ ARDOUR_UI::map_transport_state ()
|
|||
|
||||
auto_loop_button.set_active (true);
|
||||
play_selection_button.set_active (false);
|
||||
if (Config->get_loop_is_mode()) {
|
||||
roll_button.set_active (true);
|
||||
} else {
|
||||
roll_button.set_active (false);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -2137,7 +2161,11 @@ ARDOUR_UI::map_transport_state ()
|
|||
stop_button.set_active (true);
|
||||
roll_button.set_active (false);
|
||||
play_selection_button.set_active (false);
|
||||
if (Config->get_loop_is_mode ()) {
|
||||
auto_loop_button.set_active (_session->get_play_loop());
|
||||
} else {
|
||||
auto_loop_button.set_active (false);
|
||||
}
|
||||
update_disk_space ();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
|
|||
|
||||
void new_midi_tracer_window ();
|
||||
void toggle_editing_space();
|
||||
void toggle_mixer_space();
|
||||
void toggle_keep_tearoffs();
|
||||
|
||||
Gtk::Tooltips& tooltips() { return _tooltips; }
|
||||
|
|
|
|||
|
|
@ -387,7 +387,7 @@ ARDOUR_UI::setup_transport ()
|
|||
HBox* clock_box = manage (new HBox);
|
||||
|
||||
clock_box->pack_start (*primary_clock, false, false);
|
||||
if (!ARDOUR::Profile->get_small_screen()) {
|
||||
if (!ARDOUR::Profile->get_small_screen() && !ARDOUR::Profile->get_trx()) {
|
||||
clock_box->pack_start (*secondary_clock, false, false);
|
||||
}
|
||||
clock_box->set_spacing (3);
|
||||
|
|
@ -400,7 +400,16 @@ ARDOUR_UI::setup_transport ()
|
|||
transport_vbox->set_border_width (0);
|
||||
transport_vbox->set_spacing (3);
|
||||
transport_vbox->pack_start (*tbox, true, true, 0);
|
||||
|
||||
if (!Profile->get_trx()) {
|
||||
transport_vbox->pack_start (*shuttle_box, false, false, 0);
|
||||
}
|
||||
|
||||
time_info_box = manage (new TimeInfoBox);
|
||||
|
||||
if (ARDOUR::Profile->get_trx()) {
|
||||
transport_tearoff_hbox.pack_start (*time_info_box, false, false);
|
||||
}
|
||||
|
||||
transport_tearoff_hbox.pack_start (*transport_vbox, false, false);
|
||||
|
||||
|
|
@ -410,21 +419,33 @@ ARDOUR_UI::setup_transport ()
|
|||
auto_box->set_homogeneous (true);
|
||||
auto_box->set_spacing (2);
|
||||
auto_box->pack_start (sync_button, false, false);
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
auto_box->pack_start (follow_edits_button, false, false);
|
||||
auto_box->pack_start (auto_return_button, false, false);
|
||||
}
|
||||
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
transport_tearoff_hbox.pack_start (*auto_box, false, false);
|
||||
}
|
||||
transport_tearoff_hbox.pack_start (*clock_box, true, true);
|
||||
|
||||
time_info_box = manage (new TimeInfoBox);
|
||||
transport_tearoff_hbox.pack_start (*time_info_box, false, false);
|
||||
if (ARDOUR::Profile->get_trx()) {
|
||||
transport_tearoff_hbox.pack_start (*auto_box, false, false);
|
||||
}
|
||||
|
||||
if (Profile->get_small_screen()) {
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
transport_tearoff_hbox.pack_start (*time_info_box, false, false);
|
||||
}
|
||||
|
||||
if (ARDOUR::Profile->get_small_screen()) {
|
||||
transport_tearoff_hbox.pack_start (_editor_transport_box, false, false);
|
||||
}
|
||||
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
transport_tearoff_hbox.pack_start (alert_box, false, false);
|
||||
transport_tearoff_hbox.pack_start (meter_box, false, false);
|
||||
transport_tearoff_hbox.pack_start (editor_meter_peak_display, false, false);
|
||||
}
|
||||
|
||||
if (Profile->get_sae()) {
|
||||
Image* img = manage (new Image ((::get_icon (X_("sae")))));
|
||||
|
|
|
|||
|
|
@ -23,9 +23,10 @@
|
|||
This is to cut down on the compile times. It also helps with my sanity.
|
||||
*/
|
||||
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/audioengine.h"
|
||||
#include "ardour/automation_watch.h"
|
||||
#include "ardour/profile.h"
|
||||
#include "ardour/session.h"
|
||||
|
||||
#ifdef interface
|
||||
#undef interface
|
||||
|
|
@ -210,6 +211,7 @@ ARDOUR_UI::set_session (Session *s)
|
|||
_session->master_out() &&
|
||||
_session->master_out()->n_outputs().n(DataType::AUDIO) > 0) {
|
||||
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
editor_meter = new LevelMeterHBox(_session);
|
||||
editor_meter->set_meter (_session->master_out()->shared_peak_meter().get());
|
||||
editor_meter->clear_meters();
|
||||
|
|
@ -217,6 +219,7 @@ ARDOUR_UI::set_session (Session *s)
|
|||
editor_meter->setup_meters (30, 12, 6);
|
||||
editor_meter->show();
|
||||
meter_box.pack_start(*editor_meter);
|
||||
}
|
||||
|
||||
ArdourMeter::ResetAllPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_peak_display));
|
||||
ArdourMeter::ResetRoutePeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_route_peak_display));
|
||||
|
|
@ -231,7 +234,7 @@ ARDOUR_UI::set_session (Session *s)
|
|||
editor_meter_max_peak = -INFINITY;
|
||||
editor_meter_peak_display.signal_button_release_event().connect (sigc::mem_fun(*this, &ARDOUR_UI::editor_meter_peak_button_release), false);
|
||||
|
||||
if (Config->get_show_editor_meter()) {
|
||||
if (Config->get_show_editor_meter() && !ARDOUR::Profile->get_trx()) {
|
||||
transport_tearoff_hbox.pack_start (meter_box, false, false);
|
||||
transport_tearoff_hbox.pack_start (editor_meter_peak_display, false, false);
|
||||
meter_box.show();
|
||||
|
|
@ -574,3 +577,18 @@ ARDOUR_UI::editor_meter_peak_button_release (GdkEventButton* ev)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ARDOUR_UI::toggle_mixer_space()
|
||||
{
|
||||
Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMaximalMixer");
|
||||
|
||||
if (act) {
|
||||
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
|
||||
if (tact->get_active()) {
|
||||
mixer->maximise_mixer_space ();
|
||||
} else {
|
||||
mixer->restore_mixer_space ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -191,6 +191,7 @@ ARDOUR_UI::install_actions ()
|
|||
/* windows visibility actions */
|
||||
|
||||
ActionManager::register_toggle_action (common_actions, X_("ToggleMaximalEditor"), _("Maximise Editor Space"), sigc::mem_fun (*this, &ARDOUR_UI::toggle_editing_space));
|
||||
ActionManager::register_toggle_action (common_actions, X_("ToggleMaximalMixer"), _("Maximise Mixer Space"), sigc::mem_fun (*this, &ARDOUR_UI::toggle_mixer_space));
|
||||
act = ActionManager::register_toggle_action (common_actions, X_("KeepTearoffs"), _("Show Toolbars"), mem_fun (*this, &ARDOUR_UI::toggle_keep_tearoffs));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
|
||||
|
|
|
|||
497
gtk2_ardour/bundle_env_msvc.cc
Normal file
497
gtk2_ardour/bundle_env_msvc.cc
Normal file
|
|
@ -0,0 +1,497 @@
|
|||
/*
|
||||
Copyright (C) 2014 John Emmas
|
||||
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "bundle_env.h"
|
||||
#include "i18n.h"
|
||||
|
||||
#include <shlobj.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
#include <glibmm.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
#include "ardour/ardour.h"
|
||||
#include "ardour/search_paths.h"
|
||||
#include "ardour/filesystem_paths.h"
|
||||
|
||||
#include "pbd/file_utils.h"
|
||||
#include "pbd/epa.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace PBD;
|
||||
using namespace ARDOUR;
|
||||
|
||||
std::string
|
||||
get_windows_drive_volume_letter()
|
||||
{
|
||||
static std::string ret;
|
||||
char path[PATH_MAX+1];
|
||||
LPITEMIDLIST pidl = 0;
|
||||
|
||||
if (!ret.length()) {
|
||||
if (S_OK == SHGetSpecialFolderLocation (0, CSIDL_WINDOWS, &pidl))
|
||||
{
|
||||
if (SHGetPathFromIDListA (pidl, path)) {
|
||||
path[2] = '\0'; // Gives us just the drive letter and colon
|
||||
ret = path;
|
||||
}
|
||||
|
||||
CoTaskMemFree (pidl);
|
||||
}
|
||||
// The above should never fail - but just in case...
|
||||
else if (char *env_path = getenv ("windir"))
|
||||
{
|
||||
strcpy (path, env_path);
|
||||
path[2] = '\0'; // Gives us just the drive letter and colon
|
||||
ret = path;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const string
|
||||
get_module_folder ()
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
// Gives the top-level Ardour installation folder (on Windows)
|
||||
// Typically, this will be somehwere like "C:\Program Files"
|
||||
|
||||
gchar* pExeRoot = g_win32_get_package_installation_directory_of_module (0);
|
||||
|
||||
if (0 == pExeRoot) {
|
||||
pExeRoot = g_build_filename("C:\\", "Program Files", PROGRAM_NAME, 0);
|
||||
}
|
||||
|
||||
if (pExeRoot) {
|
||||
gchar tmp[PATH_MAX+1];
|
||||
gchar* p;
|
||||
|
||||
strcpy(tmp, pExeRoot);
|
||||
if (0 != (p = strrchr (tmp, G_DIR_SEPARATOR))) {
|
||||
*p = '\0';
|
||||
|
||||
if (0 != (p = g_build_filename(tmp, 0))) {
|
||||
ret = p;
|
||||
g_free (p);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (pExeRoot);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
bool
|
||||
fixup_config_file (Glib::ustring str_file_to_fix)
|
||||
{
|
||||
FILE* fd;
|
||||
char buf[4096];
|
||||
bool conversion_needed = false;
|
||||
bool succeeded = false;
|
||||
|
||||
fstream file_to_fix (fd = g_fopen(str_file_to_fix.c_str(), "r+b"));
|
||||
|
||||
if (file_to_fix.is_open()) {
|
||||
vector<std::string> lines;
|
||||
std::string line;
|
||||
|
||||
file_to_fix.seekg (0, std::ios::beg);
|
||||
file_to_fix.seekp (0, std::ios::beg);
|
||||
|
||||
try {
|
||||
while (!file_to_fix.eof() && file_to_fix.getline (buf, sizeof(buf))) {
|
||||
line = buf;
|
||||
|
||||
if (!conversion_needed && (std::string::npos != line.find("$(")))
|
||||
conversion_needed = true;
|
||||
lines.push_back(line);
|
||||
}
|
||||
|
||||
if (conversion_needed) {
|
||||
bool error = false;
|
||||
std::string::size_type token_begin, token_end;
|
||||
vector<string>::iterator i;
|
||||
|
||||
for (i = lines.begin(); i != lines.end(); ++i) {
|
||||
if (string::npos != (token_begin = i->find("$("))) {
|
||||
if (string::npos != (token_end = i->find(")", token_begin))) {
|
||||
std::string str_replace_with;
|
||||
std::string str_to_replace = i->substr(token_begin, ((token_end+1)-token_begin));
|
||||
|
||||
if (0 == str_to_replace.compare("$(CWD)")) {
|
||||
// Replace our token with the current working directory
|
||||
if (getcwd(buf, sizeof(buf))) {
|
||||
if (buf[strlen(buf)-1] == G_DIR_SEPARATOR)
|
||||
buf[strlen(buf)-1] = '\0';
|
||||
str_replace_with = buf;
|
||||
|
||||
// Replace the first occurrence of our token with the required string
|
||||
i->erase(token_begin, ((token_end+1)-token_begin));
|
||||
i->insert(token_begin, str_replace_with);
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
} else if (0 == str_to_replace.compare("$(WINDRIVE)")){
|
||||
// Replace our token with the drive letter (and colon) for the user's Windows volume
|
||||
str_replace_with = get_windows_drive_volume_letter();
|
||||
|
||||
// Replace the first occurrence of our token with the required string
|
||||
i->erase(token_begin, ((token_end+1)-token_begin));
|
||||
i->insert(token_begin, str_replace_with);
|
||||
} else {
|
||||
// Assume that our token represents an environment variable
|
||||
std::string envvar_name = str_to_replace.substr(2, str_to_replace.length()-3);
|
||||
|
||||
if (const char *envvar_value = getenv(envvar_name.c_str())) {
|
||||
strcpy(buf, envvar_value);
|
||||
if (buf[strlen(buf)-1] == G_DIR_SEPARATOR)
|
||||
buf[strlen(buf)-1] = '\0';
|
||||
str_replace_with = buf;
|
||||
|
||||
// Replace the first occurrence of our token with the required string
|
||||
i->erase(token_begin, ((token_end+1)-token_begin));
|
||||
i->insert(token_begin, str_replace_with);
|
||||
} else {
|
||||
error = true;
|
||||
cerr << _("ERROR: unknown environment variable") << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
file_to_fix.clear (); // Clear the EOF flag etc
|
||||
file_to_fix.seekg (0, std::ios::beg); // Seek our 'get' ptr to the file start pos
|
||||
// (our 'put' ptr shouldn't have moved yet).
|
||||
chsize(fileno (fd), 0); // Truncate the file, ready for re-writing
|
||||
|
||||
for (i = lines.begin(); i != lines.end(); ++i) {
|
||||
|
||||
// Write the converted contents to our file
|
||||
file_to_fix << (*i).c_str() << endl;
|
||||
}
|
||||
|
||||
try {
|
||||
file_to_fix.close();
|
||||
succeeded = true;
|
||||
} catch (...) {}
|
||||
}
|
||||
} else {
|
||||
file_to_fix.close();
|
||||
succeeded = true;
|
||||
}
|
||||
} catch (...) {
|
||||
file_to_fix.close();
|
||||
succeeded = false;
|
||||
}
|
||||
} else {
|
||||
cerr << _("ERROR: Could not open config file '") << str_file_to_fix << "'" << endl;
|
||||
}
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
void
|
||||
fixup_fonts_config ()
|
||||
{
|
||||
string fonts_conf_file;
|
||||
|
||||
#ifdef DEBUG
|
||||
fonts_conf_file = get_module_folder();
|
||||
|
||||
if (!fonts_conf_file.empty()) {
|
||||
fonts_conf_file += "\\";
|
||||
fonts_conf_file += PROGRAM_NAME;
|
||||
fonts_conf_file += FONTS_CONF_LOCATION;
|
||||
#else
|
||||
if (PBD::find_file_in_search_path (ARDOUR::ardour_config_search_path(), "fonts.conf", fonts_conf_file)) {
|
||||
#endif
|
||||
Glib::setenv ("FONTCONFIG_FILE", fonts_conf_file, true);
|
||||
|
||||
if (0 == fixup_config_file (fonts_conf_file))
|
||||
cerr << _("ERROR: processing error for 'fonts.conf' file") << endl;
|
||||
} else {
|
||||
cerr << _("ERROR: Malformed module folder (fonts.conf)") << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fixup_pango_config ()
|
||||
{
|
||||
string pango_modules_file;
|
||||
|
||||
#if defined(DEBUG) || defined(RDC_BUILD)
|
||||
// Make sure we pick up the debuggable DLLs !!!
|
||||
pango_modules_file = get_module_folder();
|
||||
|
||||
if (!pango_modules_file.empty()) {
|
||||
pango_modules_file += "\\";
|
||||
pango_modules_file += PROGRAM_NAME;
|
||||
pango_modules_file += PANGO_CONF_LOCATION;
|
||||
#if 0
|
||||
// JE - handy for non-English locale testing (Greek, in this case)
|
||||
Glib::ustring pango_modules_path = Glib::locale_to_utf8("C:\\Program Files\\Mixbus3\\etc\\ÄÇÌÇÔÑÇÓ\\pango.modules");
|
||||
/**/
|
||||
#else
|
||||
Glib::ustring pango_modules_path = pango_modules_file;
|
||||
#endif
|
||||
pango_modules_path.resize (pango_modules_path.size()-14); // Remove "/pango.modules" from the end
|
||||
#else
|
||||
if (PBD::find_file_in_search_path (ARDOUR::ardour_config_search_path(), "pango.modules", pango_modules_file)) {
|
||||
|
||||
Glib::ustring pango_modules_path = pango_modules_file;
|
||||
pango_modules_path.resize (pango_modules_path.size()-14); // Remove "/pango.modules" from the end
|
||||
#endif
|
||||
// Set an environment variable so we can find our pango modules. Note
|
||||
// that this requires a modified version of libpango (pango-utils.c)
|
||||
Glib::setenv ("PANGO_MODULE_PATH", Glib::filename_from_utf8(pango_modules_path), true);
|
||||
|
||||
if (0 == fixup_config_file (pango_modules_file))
|
||||
cerr << _("ERROR: processing error for 'pango.modules' file") << endl;
|
||||
} else {
|
||||
cerr << _("ERROR: Malformed module folder (pango.modules)") << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fixup_pixbuf_loaders_config ()
|
||||
{
|
||||
string gdk_pixbuf_loaders_file;
|
||||
|
||||
#if defined(DEBUG) || defined(RDC_BUILD)
|
||||
// Make sure we pick up the debuggable DLLs !!!
|
||||
gdk_pixbuf_loaders_file = get_module_folder();
|
||||
|
||||
if (!gdk_pixbuf_loaders_file.empty()) {
|
||||
gdk_pixbuf_loaders_file += "\\";
|
||||
gdk_pixbuf_loaders_file += PROGRAM_NAME;
|
||||
gdk_pixbuf_loaders_file += PIXBUFLOADERS_CONF_LOCATION;
|
||||
#else
|
||||
if (PBD::find_file_in_search_path (ARDOUR::ardour_config_search_path(), "gdk-pixbuf.loaders", gdk_pixbuf_loaders_file)) {
|
||||
#endif
|
||||
// Set an environment variable so we can find our pixbuf modules.
|
||||
Glib::setenv ("GDK_PIXBUF_MODULE_FILE", Glib::filename_from_utf8(gdk_pixbuf_loaders_file), true);
|
||||
|
||||
if (0 == fixup_config_file (gdk_pixbuf_loaders_file))
|
||||
cerr << _("ERROR: processing error for 'gdk-pixbuf.loaders' file") << endl;
|
||||
} else {
|
||||
cerr << _("ERROR: Malformed module folder (gdk-pixbuf.loaders)") << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fixup_clearlooks_config ()
|
||||
{
|
||||
string clearlooks_la_file;
|
||||
|
||||
#if defined(DEBUG) || defined(RDC_BUILD)
|
||||
// Make sure we pick up the debuggable DLLs !!!
|
||||
clearlooks_la_file = get_module_folder();
|
||||
|
||||
if (!clearlooks_la_file.empty()) {
|
||||
clearlooks_la_file += "\\";
|
||||
clearlooks_la_file += PROGRAM_NAME;
|
||||
clearlooks_la_file += CLEARLOOKS_CONF_LOCATION;
|
||||
#else
|
||||
if (PBD::find_file_in_search_path (ARDOUR::ardour_config_search_path(), "libclearlooks.la", clearlooks_la_file)) {
|
||||
#endif
|
||||
// Set an environment variable so we can find our clearlooks engine.
|
||||
// Note that this requires a modified version of libgtk (gtkthemes.c)
|
||||
Glib::setenv ("GTK_THEME_ENGINE_FILE", Glib::filename_from_utf8(clearlooks_la_file).c_str(), true);
|
||||
|
||||
if (0 == fixup_config_file (clearlooks_la_file))
|
||||
cerr << _("ERROR: processing error for 'clearlooks.la' file") << endl;
|
||||
} else {
|
||||
cerr << _("ERROR: Malformed module folder (clearlooks.la)") << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fixup_bundle_environment (int argc, char* argv[], const char** localedir)
|
||||
{
|
||||
std::string exec_path = argv[0];
|
||||
std::string dir_path = Glib::path_get_dirname (exec_path);
|
||||
|
||||
// Make sure that our runtime CWD is set to Mixbus's install
|
||||
// folder, regardless of where the caller's CWD was set to.
|
||||
g_chdir (dir_path.c_str());
|
||||
|
||||
EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true));
|
||||
|
||||
// Now set 'dir_path' so we can append some relative paths
|
||||
dir_path = Glib::path_get_dirname (dir_path);
|
||||
|
||||
std::string path;
|
||||
const char *cstr;
|
||||
|
||||
// First, set up 'ARDOUR_DLL_PATH'
|
||||
path = dir_path;
|
||||
path += "\\lib\\ardour3\\surfaces;";
|
||||
path += dir_path;
|
||||
path += "\\lib\\ardour3\\panners;";
|
||||
path += dir_path;
|
||||
path += "\\lib\\ardour3\\backends;";
|
||||
path += dir_path;
|
||||
path += "\\bin";
|
||||
Glib::setenv ("ARDOUR_DLL_PATH", path, true);
|
||||
|
||||
|
||||
// Next, set up 'ARDOUR_DATA_PATH'
|
||||
path = get_module_folder() + "\\";
|
||||
path += PROGRAM_NAME;
|
||||
path += "\\share";
|
||||
Glib::setenv ("ARDOUR_DATA_PATH", path, true);
|
||||
|
||||
|
||||
// Next, set up 'ARDOUR_CONFIG_PATH'
|
||||
#ifdef _WIN64
|
||||
path = user_config_directory() + "\\win64;";
|
||||
#else
|
||||
path = user_config_directory() + "\\win32;";
|
||||
#endif
|
||||
Glib::setenv ("ARDOUR_CONFIG_PATH", path, true);
|
||||
|
||||
|
||||
// Next, set up 'ARDOUR_PATH'
|
||||
path = user_config_directory();
|
||||
path = Glib::path_get_dirname (path);
|
||||
path += G_SEARCHPATH_SEPARATOR;
|
||||
path += windows_search_path().to_string();
|
||||
path += "\\icons;";
|
||||
path += windows_search_path().to_string();
|
||||
path += "\\pixmaps;";
|
||||
path += ardour_data_search_path().to_string(); // In fact, adds both the 'data' search
|
||||
path += G_SEARCHPATH_SEPARATOR; // path and our 'config' search path
|
||||
path += dir_path;
|
||||
path += "\\etc";
|
||||
Glib::setenv ("ARDOUR_PATH", path, true);
|
||||
|
||||
|
||||
// Next, set up 'ARDOUR_INSTANT_XML_PATH'
|
||||
path = user_config_directory();
|
||||
Glib::setenv ("ARDOUR_INSTANT_XML_PATH", path, true);
|
||||
|
||||
|
||||
// Next, set up 'LADSPA_PATH'
|
||||
path = ladspa_search_path().to_string();
|
||||
Glib::setenv ("LADSPA_PATH", path, true);
|
||||
|
||||
|
||||
// Next, set up 'VAMP_PATH'
|
||||
cstr = getenv ("VAMP_PATH");
|
||||
if (cstr) {
|
||||
path = cstr;
|
||||
path += G_SEARCHPATH_SEPARATOR;
|
||||
} else {
|
||||
path = "";
|
||||
}
|
||||
path += get_module_folder() + "\\";
|
||||
path += PROGRAM_NAME;
|
||||
path += "\\bin\\vamp";
|
||||
path += G_SEARCHPATH_SEPARATOR;
|
||||
path += "%ProgramFiles%\\Vamp Plugins";
|
||||
Glib::setenv ("VAMP_PATH", path, true);
|
||||
|
||||
|
||||
// Next, set up 'ARDOUR_CONTROL_SURFACE_PATH'
|
||||
cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
|
||||
if (cstr) {
|
||||
path = cstr;
|
||||
path += G_SEARCHPATH_SEPARATOR;
|
||||
} else {
|
||||
path = "";
|
||||
}
|
||||
path += control_protocol_search_path().to_string();
|
||||
Glib::setenv ("ARDOUR_CONTROL_SURFACE_PATH", path, true);
|
||||
|
||||
|
||||
// Next, set up 'GTK_LOCALEDIR'
|
||||
if (ARDOUR::translations_are_enabled ()) {
|
||||
path = windows_search_path().to_string();
|
||||
path += "\\locale";
|
||||
Glib::setenv ("GTK_LOCALEDIR", path, true);
|
||||
|
||||
// and return the same path to our caller
|
||||
(*localedir) = strdup (path.c_str());
|
||||
}
|
||||
|
||||
|
||||
// Next, set up 'GTK_PATH'
|
||||
cstr = getenv ("GTK_PATH");
|
||||
if (cstr) {
|
||||
path = cstr;
|
||||
path += G_SEARCHPATH_SEPARATOR;
|
||||
} else {
|
||||
path = "";
|
||||
}
|
||||
path += user_config_directory();
|
||||
path += "\\.gtk-2.0";
|
||||
Glib::setenv ("GTK_PATH", path, true);
|
||||
|
||||
|
||||
// Unset GTK_RC_FILES so that we only load the RC files that we define
|
||||
Glib::unsetenv ("GTK_RC_FILES");
|
||||
|
||||
|
||||
// and set a '$HOME' environment variable. This variable changes the value returned
|
||||
// by 'g_get_home_dir()' so to prevent that function from unexpectedly changing its
|
||||
// mind, we'll set '$HOME' to whatever 'g_get_home_dir()' is already returning!!
|
||||
if (NULL == getenv("HOME")) {
|
||||
Glib::setenv ("HOME", Glib::locale_from_utf8(g_get_home_dir()), true);
|
||||
}
|
||||
|
||||
fixup_fonts_config();
|
||||
fixup_pango_config();
|
||||
fixup_clearlooks_config();
|
||||
fixup_pixbuf_loaders_config();
|
||||
}
|
||||
|
||||
|
||||
void load_custom_fonts()
|
||||
{
|
||||
std::string ardour_mono_file;
|
||||
|
||||
if (!find_file_in_search_path (ardour_data_search_path(), "ArdourMono.ttf", ardour_mono_file)) {
|
||||
cerr << _("Cannot find ArdourMono TrueType font") << endl;
|
||||
}
|
||||
|
||||
FcConfig *config = FcInitLoadConfigAndFonts();
|
||||
FcBool ret = FcConfigAppFontAddFile(config, reinterpret_cast<const FcChar8*>(ardour_mono_file.c_str()));
|
||||
|
||||
if (ret == FcFalse) {
|
||||
cerr << _("Cannot load ArdourMono TrueType font.") << endl;
|
||||
}
|
||||
|
||||
ret = FcConfigSetCurrent(config);
|
||||
|
||||
if (ret == FcFalse) {
|
||||
cerr << _("Failed to set fontconfig configuration.") << endl;
|
||||
}
|
||||
}
|
||||
|
|
@ -167,6 +167,7 @@
|
|||
<Binding action="Editor/pitch-shift-region" key="F5"/>
|
||||
<Binding action="Editor/select-range-between-cursors" key="F6"/>
|
||||
<Binding action="Common/ToggleMaximalEditor" key="F11"/>
|
||||
<Binding action="Common/ToggleMaximalMixer" key="F12"/>
|
||||
<Binding action="Editor/save-visual-state-1" key="Primary-F1"/>
|
||||
<Binding action="Editor/save-visual-state-2" key="Primary-F2"/>
|
||||
<Binding action="Editor/save-visual-state-3" key="Primary-F3"/>
|
||||
|
|
|
|||
|
|
@ -259,10 +259,11 @@ Editor::Editor ()
|
|||
/* tool bar related */
|
||||
|
||||
, zoom_range_clock (new AudioClock (X_("zoomrange"), false, X_("zoom range"), true, false, true))
|
||||
|
||||
, toolbar_selection_clock_table (2,3)
|
||||
|
||||
, _mouse_mode_tearoff (0)
|
||||
, automation_mode_button (_("mode"))
|
||||
, _zoom_tearoff (0)
|
||||
, _tools_tearoff (0)
|
||||
|
||||
, _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
|
||||
|
||||
|
|
@ -309,14 +310,19 @@ Editor::Editor ()
|
|||
rb_current_opt = 4;
|
||||
#endif
|
||||
|
||||
build_edit_mode_menu();
|
||||
build_zoom_focus_menu();
|
||||
build_track_count_menu();
|
||||
build_snap_mode_menu();
|
||||
build_snap_type_menu();
|
||||
build_edit_point_menu();
|
||||
|
||||
snap_threshold = 5.0;
|
||||
bbt_beat_subdivision = 4;
|
||||
_visible_canvas_width = 0;
|
||||
_visible_canvas_height = 0;
|
||||
last_autoscroll_x = 0;
|
||||
last_autoscroll_y = 0;
|
||||
autoscroll_active = false;
|
||||
autoscroll_timeout_tag = -1;
|
||||
autoscroll_horizontal_allowed = false;
|
||||
autoscroll_vertical_allowed = false;
|
||||
logo_item = 0;
|
||||
|
||||
analysis_window = 0;
|
||||
|
|
@ -374,6 +380,7 @@ Editor::Editor ()
|
|||
_edit_point = EditAtMouse;
|
||||
_internal_editing = false;
|
||||
current_canvas_cursor = 0;
|
||||
_visible_track_count = 16;
|
||||
|
||||
samples_per_pixel = 2048; /* too early to use reset_zoom () */
|
||||
|
||||
|
|
@ -475,7 +482,9 @@ Editor::Editor ()
|
|||
|
||||
HBox* h = manage (new HBox);
|
||||
_group_tabs = new EditorGroupTabs (this);
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
h->pack_start (*_group_tabs, PACK_SHRINK);
|
||||
}
|
||||
h->pack_start (edit_controls_vbox);
|
||||
controls_layout.add (*h);
|
||||
|
||||
|
|
@ -594,10 +603,14 @@ Editor::Editor ()
|
|||
_summary_hbox.pack_start (*summary_frame, true, true);
|
||||
_summary_hbox.pack_start (*summary_arrows_right, false, false);
|
||||
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
editor_summary_pane.pack2 (_summary_hbox);
|
||||
}
|
||||
|
||||
edit_pane.pack1 (editor_summary_pane, true, true);
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
edit_pane.pack2 (_the_notebook, false, true);
|
||||
}
|
||||
|
||||
editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
|
||||
|
||||
|
|
@ -637,6 +650,7 @@ Editor::Editor ()
|
|||
setup_toolbar ();
|
||||
|
||||
set_zoom_focus (zoom_focus);
|
||||
set_visible_track_count (_visible_track_count);
|
||||
_snap_type = SnapToBeat;
|
||||
set_snap_to (_snap_type);
|
||||
_snap_mode = SnapOff;
|
||||
|
|
@ -656,12 +670,12 @@ Editor::Editor ()
|
|||
|
||||
/* nudge stuff */
|
||||
|
||||
nudge_forward_button.set_name ("zoom button");
|
||||
nudge_forward_button.add_elements (ArdourButton::FlatFace);
|
||||
nudge_forward_button.set_name ("nudge button");
|
||||
nudge_forward_button.add_elements (ArdourButton::Inset);
|
||||
nudge_forward_button.set_image(::get_icon("nudge_right"));
|
||||
|
||||
nudge_backward_button.set_name ("zoom button");
|
||||
nudge_backward_button.add_elements (ArdourButton::FlatFace);
|
||||
nudge_backward_button.set_name ("nudge button");
|
||||
nudge_backward_button.add_elements (ArdourButton::Inset);
|
||||
nudge_backward_button.set_image(::get_icon("nudge_left"));
|
||||
|
||||
fade_context_menu.set_name ("ArdourContextMenu");
|
||||
|
|
@ -2255,6 +2269,10 @@ Editor::set_state (const XMLNode& node, int /*version*/)
|
|||
reset_zoom (samples_per_pixel);
|
||||
}
|
||||
|
||||
if ((prop = node.property ("visible-track-count"))) {
|
||||
set_visible_track_count (PBD::atoi (prop->value()));
|
||||
}
|
||||
|
||||
if ((prop = node.property ("snap-to"))) {
|
||||
set_snap_to ((SnapType) string_2_enum (prop->value(), _snap_type));
|
||||
}
|
||||
|
|
@ -2482,6 +2500,8 @@ Editor::get_state ()
|
|||
node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
|
||||
node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
|
||||
node->add_property ("edit-point", enum_2_string (_edit_point));
|
||||
snprintf (buf, sizeof(buf), "%d", _visible_track_count);
|
||||
node->add_property ("visible-track-count", buf);
|
||||
|
||||
snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
|
||||
node->add_property ("playhead", buf);
|
||||
|
|
@ -2851,15 +2871,21 @@ Editor::setup_toolbar ()
|
|||
|
||||
mouse_mode_hbox->set_spacing (2);
|
||||
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
mouse_mode_hbox->pack_start (smart_mode_button, false, false);
|
||||
}
|
||||
|
||||
mouse_mode_hbox->pack_start (mouse_move_button, false, false);
|
||||
mouse_mode_hbox->pack_start (mouse_select_button, false, false);
|
||||
mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
|
||||
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
|
||||
mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
|
||||
mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
|
||||
mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
|
||||
mouse_mode_hbox->pack_start (internal_edit_button, false, false, 8);
|
||||
}
|
||||
|
||||
mouse_mode_vbox->pack_start (*mouse_mode_hbox);
|
||||
|
||||
|
|
@ -2878,7 +2904,9 @@ Editor::setup_toolbar ()
|
|||
set_popdown_strings (edit_mode_selector, edit_mode_strings);
|
||||
edit_mode_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::edit_mode_selection_done));
|
||||
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
mode_box->pack_start (edit_mode_selector, false, false);
|
||||
}
|
||||
mode_box->pack_start (*mouse_mode_box, false, false);
|
||||
|
||||
_mouse_mode_tearoff = manage (new TearOff (*mode_box));
|
||||
|
|
@ -2906,21 +2934,21 @@ Editor::setup_toolbar ()
|
|||
RefPtr<Action> act;
|
||||
|
||||
zoom_in_button.set_name ("zoom button");
|
||||
zoom_in_button.add_elements ( ArdourButton::FlatFace );
|
||||
zoom_in_button.add_elements ( ArdourButton::Inset );
|
||||
zoom_in_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
|
||||
zoom_in_button.set_image(::get_icon ("zoom_in"));
|
||||
act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
|
||||
zoom_in_button.set_related_action (act);
|
||||
|
||||
zoom_out_button.set_name ("zoom button");
|
||||
zoom_out_button.add_elements ( ArdourButton::FlatFace );
|
||||
zoom_out_button.add_elements ( ArdourButton::Inset );
|
||||
zoom_out_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
|
||||
zoom_out_button.set_image(::get_icon ("zoom_out"));
|
||||
act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
|
||||
zoom_out_button.set_related_action (act);
|
||||
|
||||
zoom_out_full_button.set_name ("zoom button");
|
||||
zoom_out_full_button.add_elements ( ArdourButton::FlatFace );
|
||||
zoom_out_full_button.add_elements ( ArdourButton::Inset );
|
||||
zoom_out_full_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
|
||||
zoom_out_full_button.set_image(::get_icon ("zoom_full"));
|
||||
act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
|
||||
|
|
@ -2930,15 +2958,23 @@ Editor::setup_toolbar ()
|
|||
set_popdown_strings (zoom_focus_selector, zoom_focus_strings);
|
||||
zoom_focus_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done));
|
||||
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
_zoom_box.pack_start (zoom_out_button, false, false);
|
||||
_zoom_box.pack_start (zoom_in_button, false, false);
|
||||
_zoom_box.pack_start (zoom_out_full_button, false, false);
|
||||
|
||||
_zoom_box.pack_start (zoom_focus_selector, false, false);
|
||||
} else {
|
||||
mode_box->pack_start (zoom_out_button, false, false);
|
||||
mode_box->pack_start (zoom_in_button, false, false);
|
||||
}
|
||||
|
||||
/* Track zoom buttons */
|
||||
visible_tracks_selector.set_name ("zoom button");
|
||||
// visible_tracks_selector.add_elements ( ArdourButton::Inset );
|
||||
set_size_request_to_display_given_text (visible_tracks_selector, _("all"), 40, 2);
|
||||
|
||||
tav_expand_button.set_name ("zoom button");
|
||||
tav_expand_button.add_elements ( ArdourButton::FlatFace );
|
||||
// tav_expand_button.add_elements ( ArdourButton::Inset );
|
||||
tav_expand_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
|
||||
tav_expand_button.set_size_request (-1, 20);
|
||||
tav_expand_button.set_image(::get_icon ("tav_exp"));
|
||||
|
|
@ -2946,16 +2982,20 @@ Editor::setup_toolbar ()
|
|||
tav_expand_button.set_related_action (act);
|
||||
|
||||
tav_shrink_button.set_name ("zoom button");
|
||||
tav_shrink_button.add_elements ( ArdourButton::FlatFace );
|
||||
// tav_shrink_button.add_elements ( ArdourButton::Inset );
|
||||
tav_shrink_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
|
||||
tav_shrink_button.set_size_request (-1, 20);
|
||||
tav_shrink_button.set_image(::get_icon ("tav_shrink"));
|
||||
act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
|
||||
tav_shrink_button.set_related_action (act);
|
||||
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
_zoom_box.pack_start (visible_tracks_selector);
|
||||
}
|
||||
_zoom_box.pack_start (tav_shrink_button);
|
||||
_zoom_box.pack_start (tav_expand_button);
|
||||
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
_zoom_tearoff = manage (new TearOff (_zoom_box));
|
||||
|
||||
_zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
|
||||
|
|
@ -2966,6 +3006,7 @@ Editor::setup_toolbar ()
|
|||
&_zoom_tearoff->tearoff_window()));
|
||||
_zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
|
||||
&_zoom_tearoff->tearoff_window(), 0));
|
||||
}
|
||||
|
||||
snap_box.set_spacing (2);
|
||||
snap_box.set_border_width (2);
|
||||
|
|
@ -3029,15 +3070,19 @@ Editor::setup_toolbar ()
|
|||
toolbar_hbox.set_border_width (1);
|
||||
|
||||
toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
|
||||
toolbar_hbox.pack_start (*_tools_tearoff, false, false);
|
||||
}
|
||||
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
hbox->pack_start (snap_box, false, false);
|
||||
if (!Profile->get_small_screen()) {
|
||||
hbox->pack_start (*nudge_box, false, false);
|
||||
} else {
|
||||
ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
|
||||
}
|
||||
}
|
||||
hbox->pack_start (panic_box, false, false);
|
||||
|
||||
hbox->show_all ();
|
||||
|
|
@ -3054,6 +3099,81 @@ Editor::setup_toolbar ()
|
|||
toolbar_frame.add (_toolbar_viewport);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::build_edit_point_menu ()
|
||||
{
|
||||
#if 0
|
||||
using namespace Menu_Helpers;
|
||||
|
||||
edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
|
||||
edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
|
||||
edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Editor::build_edit_mode_menu ()
|
||||
{
|
||||
#if 0
|
||||
using namespace Menu_Helpers;
|
||||
|
||||
edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Slide), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
|
||||
edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Splice), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
|
||||
edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Lock), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Editor::build_snap_mode_menu ()
|
||||
{
|
||||
#if 0
|
||||
using namespace Menu_Helpers;
|
||||
|
||||
snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
|
||||
snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
|
||||
snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Editor::build_snap_type_menu ()
|
||||
{
|
||||
#if 0
|
||||
using namespace Menu_Helpers;
|
||||
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
|
||||
snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Editor::setup_tooltips ()
|
||||
{
|
||||
|
|
@ -3075,6 +3195,7 @@ Editor::setup_tooltips ()
|
|||
ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
|
||||
ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
|
||||
ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
|
||||
ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks"));
|
||||
ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
|
||||
ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
|
||||
ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
|
||||
|
|
@ -3472,6 +3593,21 @@ Editor::edit_point_selection_done ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::build_zoom_focus_menu ()
|
||||
{
|
||||
#if 0
|
||||
using namespace Menu_Helpers;
|
||||
|
||||
zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
|
||||
zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
|
||||
zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
|
||||
zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
|
||||
zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
|
||||
zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Editor::zoom_focus_selection_done ()
|
||||
{
|
||||
|
|
@ -3499,6 +3635,76 @@ Editor::zoom_focus_selection_done ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::build_track_count_menu ()
|
||||
{
|
||||
#if 0
|
||||
using namespace Menu_Helpers;
|
||||
|
||||
visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
|
||||
visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
|
||||
visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
|
||||
visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
|
||||
visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
|
||||
visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
|
||||
visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
|
||||
visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
|
||||
visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
|
||||
visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
|
||||
visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
|
||||
visible_tracks_selector.AddMenuElem (MenuElem (_("all"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_visible_track_count (int32_t n)
|
||||
{
|
||||
_visible_track_count = n;
|
||||
|
||||
/* if the canvas hasn't really been allocated any size yet, just
|
||||
record the desired number of visible tracks and return. when canvas
|
||||
allocation happens, we will get called again and then we can do the
|
||||
real work.
|
||||
*/
|
||||
|
||||
if (_visible_canvas_height <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int h;
|
||||
string str;
|
||||
|
||||
if (_visible_track_count > 0) {
|
||||
h = _visible_canvas_height / _visible_track_count;
|
||||
std::ostringstream s;
|
||||
s << _visible_track_count;
|
||||
str = s.str();
|
||||
} else if (_visible_track_count == 0) {
|
||||
h = _visible_canvas_height / track_views.size();
|
||||
str = _("all");
|
||||
} else {
|
||||
/* negative value means that the visible track count has
|
||||
been overridden by explicit track height changes.
|
||||
*/
|
||||
visible_tracks_selector.set_active_text (X_("*"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||
(*i)->set_height (h);
|
||||
}
|
||||
|
||||
if (str != visible_tracks_selector.get_active_text()) {
|
||||
visible_tracks_selector.set_active_text (str);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::override_visible_track_count ()
|
||||
{
|
||||
_visible_track_count = -_visible_track_count;
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::edit_controls_button_release (GdkEventButton* ev)
|
||||
{
|
||||
|
|
@ -3642,7 +3848,7 @@ Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
|
|||
{
|
||||
if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) &&
|
||||
(_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) &&
|
||||
(_zoom_tearoff->torn_off() || !_zoom_tearoff->visible())) {
|
||||
(_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
|
||||
top_hbox.remove (toolbar_frame);
|
||||
}
|
||||
}
|
||||
|
|
@ -3952,8 +4158,10 @@ Editor::update_tearoff_visibility()
|
|||
bool visible = Config->get_keep_tearoffs();
|
||||
_mouse_mode_tearoff->set_visible (visible);
|
||||
_tools_tearoff->set_visible (visible);
|
||||
if (_zoom_tearoff) {
|
||||
_zoom_tearoff->set_visible (visible);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::maximise_editing_space ()
|
||||
|
|
@ -4291,35 +4499,45 @@ Editor::idle_visual_changer ()
|
|||
pending_visual_change.idle_handler_id = -1;
|
||||
pending_visual_change.being_handled = true;
|
||||
|
||||
VisualChange::Type p = pending_visual_change.pending;
|
||||
VisualChange vc = pending_visual_change;
|
||||
|
||||
pending_visual_change.pending = (VisualChange::Type) 0;
|
||||
|
||||
visual_changer (vc);
|
||||
|
||||
pending_visual_change.being_handled = false;
|
||||
|
||||
return 0; /* this is always a one-shot call */
|
||||
}
|
||||
|
||||
void
|
||||
Editor::visual_changer (const VisualChange& vc)
|
||||
{
|
||||
double const last_time_origin = horizontal_position ();
|
||||
|
||||
|
||||
if (p & VisualChange::ZoomLevel) {
|
||||
set_samples_per_pixel (pending_visual_change.samples_per_pixel);
|
||||
if (vc.pending & VisualChange::ZoomLevel) {
|
||||
set_samples_per_pixel (vc.samples_per_pixel);
|
||||
|
||||
compute_fixed_ruler_scale ();
|
||||
|
||||
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
|
||||
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
|
||||
|
||||
compute_current_bbt_points (pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_samples(),
|
||||
compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
|
||||
current_bbt_points_begin, current_bbt_points_end);
|
||||
compute_bbt_ruler_scale (pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_samples(),
|
||||
compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
|
||||
current_bbt_points_begin, current_bbt_points_end);
|
||||
update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
|
||||
|
||||
update_video_timeline();
|
||||
}
|
||||
|
||||
if (p & VisualChange::TimeOrigin) {
|
||||
set_horizontal_position (pending_visual_change.time_origin / samples_per_pixel);
|
||||
if (vc.pending & VisualChange::TimeOrigin) {
|
||||
set_horizontal_position (vc.time_origin / samples_per_pixel);
|
||||
}
|
||||
|
||||
if (p & VisualChange::YOrigin) {
|
||||
vertical_adjustment.set_value (pending_visual_change.y_origin);
|
||||
if (vc.pending & VisualChange::YOrigin) {
|
||||
vertical_adjustment.set_value (vc.y_origin);
|
||||
}
|
||||
|
||||
if (last_time_origin == horizontal_position ()) {
|
||||
|
|
@ -4328,14 +4546,11 @@ Editor::idle_visual_changer ()
|
|||
redisplay_tempo (true);
|
||||
}
|
||||
|
||||
if (!(p & VisualChange::ZoomLevel)) {
|
||||
if (!(vc.pending & VisualChange::ZoomLevel)) {
|
||||
update_video_timeline();
|
||||
}
|
||||
|
||||
_summary->set_overlays_dirty ();
|
||||
|
||||
pending_visual_change.being_handled = false;
|
||||
return 0; /* this is always a one-shot call */
|
||||
}
|
||||
|
||||
struct EditorOrderTimeAxisSorter {
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
void set_internal_edit (bool yn);
|
||||
bool toggle_internal_editing_from_double_click (GdkEvent*);
|
||||
|
||||
void _ensure_time_axis_view_is_visible (const TimeAxisView& tav, bool at_top);
|
||||
void foreach_time_axis_view (sigc::slot<void,TimeAxisView&>);
|
||||
void add_to_idle_resize (TimeAxisView*, int32_t);
|
||||
|
||||
|
|
@ -207,7 +208,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
account any scrolling offsets.
|
||||
*/
|
||||
|
||||
framepos_t pixel_to_sample (double pixel) const {
|
||||
framepos_t pixel_to_sample_from_event (double pixel) const {
|
||||
|
||||
/* pixel can be less than zero when motion events
|
||||
are processed. since we've already run the world->canvas
|
||||
|
|
@ -222,6 +223,10 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
}
|
||||
}
|
||||
|
||||
framepos_t pixel_to_sample (double pixel) const {
|
||||
return pixel * samples_per_pixel;
|
||||
}
|
||||
|
||||
double sample_to_pixel (framepos_t sample) const {
|
||||
return sample / samples_per_pixel;
|
||||
}
|
||||
|
|
@ -345,9 +350,10 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
|
||||
void show_window ();
|
||||
|
||||
void ensure_time_axis_view_is_visible (const TimeAxisView& tav);
|
||||
void scroll_tracks_down_line ();
|
||||
void scroll_tracks_up_line ();
|
||||
bool scroll_up_one_track ();
|
||||
bool scroll_down_one_track ();
|
||||
|
||||
void prepare_for_cleanup ();
|
||||
void finish_cleanup ();
|
||||
|
|
@ -408,7 +414,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
return _drags;
|
||||
}
|
||||
|
||||
void maybe_autoscroll (bool, bool, bool, bool);
|
||||
void maybe_autoscroll (bool, bool, bool);
|
||||
bool autoscroll_active() const;
|
||||
|
||||
Gdk::Cursor* get_canvas_cursor () const { return current_canvas_cursor; }
|
||||
void set_canvas_cursor (Gdk::Cursor*, bool save=false);
|
||||
|
|
@ -442,6 +449,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
ArdourCanvas::GtkCanvasViewport* get_time_bars_canvas () const;
|
||||
ArdourCanvas::GtkCanvasViewport* get_track_canvas () const;
|
||||
|
||||
void override_visible_track_count ();
|
||||
|
||||
protected:
|
||||
void map_transport_state ();
|
||||
|
|
@ -728,6 +736,12 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
/* The group used for region motion. Sits on top of _trackview_group */
|
||||
ArdourCanvas::Group* _region_motion_group;
|
||||
|
||||
/* a rect that sits at the bottom of all tracks to act as a drag-no-drop/clickable
|
||||
* target area.
|
||||
*/
|
||||
ArdourCanvas::Rectangle* _canvas_bottom_rect;
|
||||
bool canvas_bottom_rect_event (GdkEvent* event);
|
||||
|
||||
enum RulerType {
|
||||
ruler_metric_timecode = 0,
|
||||
ruler_metric_bbt = 1,
|
||||
|
|
@ -1022,6 +1036,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
|
||||
static int _idle_visual_changer (void *arg);
|
||||
int idle_visual_changer ();
|
||||
void visual_changer (const VisualChange&);
|
||||
void ensure_visual_change_idle_handler ();
|
||||
|
||||
/* track views */
|
||||
|
|
@ -1440,7 +1455,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
|
||||
Gtk::Allocation _canvas_viewport_allocation;
|
||||
void track_canvas_viewport_allocate (Gtk::Allocation alloc);
|
||||
bool track_canvas_viewport_size_allocated ();
|
||||
void track_canvas_viewport_size_allocated ();
|
||||
bool track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const &, int, int, guint);
|
||||
bool track_canvas_key_press (GdkEventKey *);
|
||||
bool track_canvas_key_release (GdkEventKey *);
|
||||
|
|
@ -1557,6 +1572,11 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
|
||||
ArdourButton tav_expand_button;
|
||||
ArdourButton tav_shrink_button;
|
||||
Gtk::ComboBoxText visible_tracks_selector;
|
||||
|
||||
int32_t _visible_track_count;
|
||||
void build_track_count_menu ();
|
||||
void set_visible_track_count (int32_t);
|
||||
|
||||
Gtk::VBox toolbar_clock_vbox;
|
||||
Gtk::VBox toolbar_selection_clock_vbox;
|
||||
|
|
@ -1587,7 +1607,9 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
Gtk::VBox automation_box;
|
||||
Gtk::Button automation_mode_button;
|
||||
|
||||
//edit mode menu stuff
|
||||
Gtk::ComboBoxText edit_mode_selector;
|
||||
void build_edit_mode_menu ();
|
||||
Gtk::VBox edit_mode_box;
|
||||
std::vector<std::string> edit_mode_strings;
|
||||
|
||||
|
|
@ -1596,7 +1618,10 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
void edit_mode_selection_done ();
|
||||
|
||||
Gtk::ComboBoxText snap_type_selector;
|
||||
void build_snap_type_menu ();
|
||||
|
||||
Gtk::ComboBoxText snap_mode_selector;
|
||||
void build_snap_mode_menu ();
|
||||
Gtk::HBox snap_box;
|
||||
|
||||
std::vector<std::string> snap_type_strings;
|
||||
|
|
@ -1612,7 +1637,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
|
||||
Gtk::ComboBoxText zoom_focus_selector;
|
||||
Gtk::VBox zoom_focus_box;
|
||||
|
||||
void build_zoom_focus_menu ();
|
||||
std::vector<std::string> zoom_focus_strings;
|
||||
|
||||
void zoom_focus_selection_done ();
|
||||
|
|
@ -1722,22 +1747,15 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
|
||||
/* autoscrolling */
|
||||
|
||||
bool autoscroll_active;
|
||||
int autoscroll_timeout_tag;
|
||||
int autoscroll_x;
|
||||
int autoscroll_y;
|
||||
int last_autoscroll_x;
|
||||
int last_autoscroll_y;
|
||||
sigc::connection autoscroll_connection;
|
||||
bool autoscroll_horizontal_allowed;
|
||||
bool autoscroll_vertical_allowed;
|
||||
uint32_t autoscroll_cnt;
|
||||
framecnt_t autoscroll_x_distance;
|
||||
double autoscroll_y_distance;
|
||||
Gtk::Widget* autoscroll_widget;
|
||||
ArdourCanvas::Rect autoscroll_boundary;
|
||||
|
||||
bool _autoscroll_fudging;
|
||||
int autoscroll_fudge_threshold () const;
|
||||
|
||||
static gint _autoscroll_canvas (void *);
|
||||
bool autoscroll_canvas ();
|
||||
void start_canvas_autoscroll (int x, int y);
|
||||
void start_canvas_autoscroll (bool allow_horiz, bool allow_vert, const ArdourCanvas::Rect& boundary);
|
||||
void stop_canvas_autoscroll ();
|
||||
|
||||
/* trimming */
|
||||
|
|
@ -1945,6 +1963,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
Editing::EditPoint _edit_point;
|
||||
|
||||
Gtk::ComboBoxText edit_point_selector;
|
||||
void build_edit_point_menu();
|
||||
|
||||
void set_edit_point_preference (Editing::EditPoint ep, bool force = false);
|
||||
void cycle_edit_point (bool with_marker);
|
||||
|
|
|
|||
|
|
@ -414,49 +414,49 @@ Editor::register_actions ()
|
|||
smart_mode_action = Glib::RefPtr<ToggleAction>::cast_static (act);
|
||||
smart_mode_button.set_related_action (smart_mode_action);
|
||||
smart_mode_button.set_text (_("Smart"));
|
||||
smart_mode_button.add_elements ( ArdourButton::FlatFace );
|
||||
smart_mode_button.add_elements ( ArdourButton::Inset );
|
||||
smart_mode_button.set_name ("mouse mode button");
|
||||
|
||||
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-object", _("Object Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
|
||||
mouse_move_button.set_related_action (act);
|
||||
mouse_move_button.set_image (::get_icon("tool_object"));
|
||||
mouse_move_button.add_elements ( ArdourButton::FlatFace );
|
||||
mouse_move_button.add_elements ( ArdourButton::Inset );
|
||||
mouse_move_button.set_name ("mouse mode button");
|
||||
|
||||
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-range", _("Range Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
|
||||
mouse_select_button.set_related_action (act);
|
||||
mouse_select_button.set_image (::get_icon("tool_range"));
|
||||
mouse_select_button.add_elements ( ArdourButton::FlatFace );
|
||||
mouse_select_button.add_elements ( ArdourButton::Inset );
|
||||
mouse_select_button.set_name ("mouse mode button");
|
||||
|
||||
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-draw", _("Note Drawing Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseDraw));
|
||||
mouse_draw_button.set_related_action (act);
|
||||
mouse_draw_button.set_image (::get_icon("midi_tool_pencil"));
|
||||
mouse_draw_button.add_elements ( ArdourButton::FlatFace );
|
||||
mouse_draw_button.add_elements ( ArdourButton::Inset );
|
||||
mouse_draw_button.set_name ("mouse mode button");
|
||||
|
||||
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-gain", _("Gain Tool"), sigc::bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
|
||||
mouse_gain_button.set_related_action (act);
|
||||
mouse_gain_button.set_image (::get_icon("tool_gain"));
|
||||
mouse_gain_button.add_elements ( ArdourButton::FlatFace );
|
||||
mouse_gain_button.add_elements ( ArdourButton::Inset );
|
||||
mouse_gain_button.set_name ("mouse mode button");
|
||||
|
||||
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-zoom", _("Zoom Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
|
||||
mouse_zoom_button.set_related_action (act);
|
||||
mouse_zoom_button.set_image (::get_icon("tool_zoom"));
|
||||
mouse_zoom_button.add_elements ( ArdourButton::FlatFace );
|
||||
mouse_zoom_button.add_elements ( ArdourButton::Inset );
|
||||
mouse_zoom_button.set_name ("mouse mode button");
|
||||
|
||||
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-audition", _("Audition Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
|
||||
mouse_audition_button.set_related_action (act);
|
||||
mouse_audition_button.set_image (::get_icon("tool_audition"));
|
||||
mouse_audition_button.add_elements ( ArdourButton::FlatFace );
|
||||
mouse_audition_button.add_elements ( ArdourButton::Inset );
|
||||
mouse_audition_button.set_name ("mouse mode button");
|
||||
|
||||
act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-timefx", _("Time FX Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
|
||||
mouse_timefx_button.set_related_action (act);
|
||||
mouse_timefx_button.set_image (::get_icon("tool_stretch"));
|
||||
mouse_timefx_button.add_elements ( ArdourButton::FlatFace );
|
||||
mouse_timefx_button.add_elements ( ArdourButton::Inset );
|
||||
mouse_timefx_button.set_name ("mouse mode button");
|
||||
|
||||
ActionManager::register_action (editor_actions, "step-mouse-mode", _("Step Mouse Mode"), sigc::bind (sigc::mem_fun(*this, &Editor::step_mouse_mode), true));
|
||||
|
|
@ -464,7 +464,7 @@ Editor::register_actions ()
|
|||
act = ActionManager::register_toggle_action (mouse_mode_actions, "toggle-internal-edit", _("Edit MIDI"), sigc::mem_fun(*this, &Editor::toggle_internal_editing));
|
||||
internal_edit_button.set_related_action (act);
|
||||
internal_edit_button.set_image (::get_icon("tool_note"));
|
||||
internal_edit_button.add_elements ( ArdourButton::FlatFace );
|
||||
internal_edit_button.add_elements ( ArdourButton::Inset );
|
||||
internal_edit_button.set_name ("mouse mode button");
|
||||
|
||||
RadioAction::Group edit_point_group;
|
||||
|
|
@ -1650,7 +1650,9 @@ Editor::parameter_changed (std::string p)
|
|||
} else if (p == "timecode-offset" || p == "timecode-offset-negative") {
|
||||
update_just_timecode ();
|
||||
} else if (p == "show-zoom-tools") {
|
||||
if (_zoom_tearoff) {
|
||||
_zoom_tearoff->set_visible (Config->get_show_zoom_tools(), true);
|
||||
}
|
||||
} else if (p == "sound-midi-notes") {
|
||||
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("sound-midi-notes"));
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ Editor::initialize_canvas ()
|
|||
// logo_item->property_width_in_pixels() = true;
|
||||
// logo_item->property_height_set() = true;
|
||||
// logo_item->property_width_set() = true;
|
||||
logo_item->show ();
|
||||
// logo_item->show ();
|
||||
}
|
||||
|
||||
/*a group to hold global rects like punch/loop indicators */
|
||||
|
|
@ -192,12 +192,10 @@ Editor::initialize_canvas ()
|
|||
// used to show zoom mode active zooming
|
||||
zoom_rect = new ArdourCanvas::Rectangle (_track_canvas->root(), ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
|
||||
zoom_rect->hide();
|
||||
|
||||
zoom_rect->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_zoom_rect_event), (ArdourCanvas::Item*) 0));
|
||||
|
||||
// used as rubberband rect
|
||||
rubberband_rect = new ArdourCanvas::Rectangle (_trackview_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
|
||||
|
||||
rubberband_rect->hide();
|
||||
|
||||
tempo_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_tempo_bar_event), tempo_bar));
|
||||
|
|
@ -213,7 +211,17 @@ Editor::initialize_canvas ()
|
|||
if (logo_item) {
|
||||
logo_item->lower_to_bottom ();
|
||||
}
|
||||
/* need to handle 4 specific types of events as catch-alls */
|
||||
|
||||
|
||||
_canvas_bottom_rect = new ArdourCanvas::Rectangle (_track_canvas->root(), ArdourCanvas::Rect (0.0, 0.0, max_canvas_coordinate, 20));
|
||||
/* this thing is transparent */
|
||||
_canvas_bottom_rect->set_fill (false);
|
||||
_canvas_bottom_rect->set_outline (false);
|
||||
_canvas_bottom_rect->Event.connect (sigc::mem_fun (*this, &Editor::canvas_bottom_rect_event));
|
||||
|
||||
/* these signals will initially be delivered to the canvas itself, but if they end up remaining unhandled, they are passed to Editor-level
|
||||
handlers.
|
||||
*/
|
||||
|
||||
_track_canvas->signal_scroll_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_scroll_event));
|
||||
_track_canvas->signal_motion_notify_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_motion_notify_event));
|
||||
|
|
@ -257,7 +265,7 @@ Editor::track_canvas_viewport_allocate (Gtk::Allocation alloc)
|
|||
track_canvas_viewport_size_allocated ();
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
Editor::track_canvas_viewport_size_allocated ()
|
||||
{
|
||||
bool height_changed = _visible_canvas_height != _canvas_viewport_allocation.get_height();
|
||||
|
|
@ -281,13 +289,13 @@ Editor::track_canvas_viewport_size_allocated ()
|
|||
*/
|
||||
vertical_adjustment.set_value (_full_canvas_height - _visible_canvas_height);
|
||||
}
|
||||
|
||||
set_visible_track_count (_visible_track_count);
|
||||
}
|
||||
|
||||
update_fixed_rulers();
|
||||
redisplay_tempo (false);
|
||||
_summary->set_overlays_dirty ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -315,12 +323,24 @@ Editor::reset_controls_layout_width ()
|
|||
void
|
||||
Editor::reset_controls_layout_height (int32_t h)
|
||||
{
|
||||
/* ensure that the rect that represents the "bottom" of the canvas
|
||||
* (the drag-n-drop zone) is, in fact, at the bottom.
|
||||
*/
|
||||
|
||||
_canvas_bottom_rect->set_position (ArdourCanvas::Duple (0, h));
|
||||
|
||||
/* track controls layout must span the full height of "h" (all tracks)
|
||||
* plus the bottom rect.
|
||||
*/
|
||||
|
||||
h += _canvas_bottom_rect->height ();
|
||||
|
||||
/* set the height of the scrollable area (i.e. the sum of all contained widgets)
|
||||
* for the controls layout. The size request is set elsewhere.
|
||||
*/
|
||||
|
||||
controls_layout.property_height() = h;
|
||||
|
||||
/* size request is set elsewhere, see ::track_canvas_allocate() */
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -448,245 +468,265 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
|
|||
context->drag_finish (true, false, time);
|
||||
}
|
||||
|
||||
/** If the editor window is arranged such that the edge of the trackview is right up
|
||||
* against the edge of the screen, autoscroll will not work very well. In this situation,
|
||||
* we start autoscrolling some distance in from the right-hand-side of the screen edge;
|
||||
* this is the distance at which that happens.
|
||||
*/
|
||||
int
|
||||
Editor::autoscroll_fudge_threshold () const
|
||||
{
|
||||
return current_page_samples() / 6;
|
||||
}
|
||||
|
||||
/** @param allow_horiz true to allow horizontal autoscroll, otherwise false.
|
||||
*
|
||||
* @param allow_vert true to allow vertical autoscroll, otherwise false.
|
||||
*
|
||||
* @param moving_left true if we are moving left, so we only want to autoscroll on the left of the canvas,
|
||||
* otherwise false, so we only want to autoscroll on the right of the canvas.
|
||||
*
|
||||
* @param moving_up true if we are moving up, so we only want to autoscroll at the top of the canvas,
|
||||
* otherwise false, so we only want to autoscroll at the bottom of the canvas.
|
||||
*/
|
||||
void
|
||||
Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool moving_left, bool moving_up)
|
||||
Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers)
|
||||
{
|
||||
if (!Config->get_autoscroll_editor ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool startit = false;
|
||||
|
||||
/* Work out the distance between the right hand edge of the trackview and the edge of
|
||||
the monitor that it is on.
|
||||
ArdourCanvas::Rect scrolling_boundary;
|
||||
Gtk::Allocation alloc;
|
||||
|
||||
if (from_headers) {
|
||||
alloc = controls_layout.get_allocation ();
|
||||
} else {
|
||||
alloc = _track_canvas_viewport->get_allocation ();
|
||||
|
||||
/* the effective width of the autoscroll boundary so
|
||||
that we start scrolling before we hit the edge.
|
||||
|
||||
this helps when the window is slammed up against the
|
||||
right edge of the screen, making it hard to scroll
|
||||
effectively.
|
||||
*/
|
||||
|
||||
Glib::RefPtr<Gdk::Window> gdk_window = get_window ();
|
||||
Gdk::Rectangle window_rect;
|
||||
gdk_window->get_frame_extents (window_rect);
|
||||
|
||||
Glib::RefPtr<Gdk::Screen> screen = get_screen ();
|
||||
Gdk::Rectangle root_rect;
|
||||
screen->get_root_window()->get_frame_extents (root_rect);
|
||||
|
||||
Gtk::Allocation editor_list = _the_notebook.get_allocation ();
|
||||
|
||||
framecnt_t distance = pixel_to_sample (root_rect.get_x() + root_rect.get_width() - window_rect.get_x() - window_rect.get_width());
|
||||
if (_the_notebook.is_visible ()) {
|
||||
distance += pixel_to_sample (editor_list.get_width());
|
||||
}
|
||||
|
||||
/* Note whether we're fudging the autoscroll (see autoscroll_fudge_threshold) */
|
||||
_autoscroll_fudging = (distance < autoscroll_fudge_threshold ());
|
||||
|
||||
/* ty is in canvas-coordinate space */
|
||||
|
||||
double const ty = _drags->current_pointer_y();
|
||||
ArdourCanvas::Rect visible = _track_canvas->visible_area();
|
||||
|
||||
autoscroll_y = 0;
|
||||
autoscroll_x = 0;
|
||||
if (ty < visible.y0 && moving_up && allow_vert) {
|
||||
autoscroll_y = -1;
|
||||
startit = true;
|
||||
} else if (ty > visible.y1 && !moving_up && allow_vert) {
|
||||
autoscroll_y = 1;
|
||||
startit = true;
|
||||
}
|
||||
|
||||
framepos_t rightmost_frame = leftmost_frame + current_page_samples();
|
||||
if (_autoscroll_fudging) {
|
||||
rightmost_frame -= autoscroll_fudge_threshold ();
|
||||
}
|
||||
|
||||
if (_drags->current_pointer_frame() > rightmost_frame && allow_horiz) {
|
||||
if (rightmost_frame < max_framepos && !moving_left) {
|
||||
autoscroll_x = 1;
|
||||
startit = true;
|
||||
}
|
||||
} else if (_drags->current_pointer_frame() < leftmost_frame && allow_horiz) {
|
||||
if (leftmost_frame > 0 && moving_left) {
|
||||
autoscroll_x = -1;
|
||||
startit = true;
|
||||
if (alloc.get_width() > 20) {
|
||||
alloc.set_width (alloc.get_width() - 20);
|
||||
alloc.set_x (alloc.get_x() + 10);
|
||||
}
|
||||
}
|
||||
|
||||
if (autoscroll_active && ((autoscroll_x != last_autoscroll_x) || (autoscroll_y != last_autoscroll_y) || (autoscroll_x == 0 && autoscroll_y == 0))) {
|
||||
stop_canvas_autoscroll ();
|
||||
scrolling_boundary = ArdourCanvas::Rect (alloc.get_x(), alloc.get_y(),
|
||||
alloc.get_x() + alloc.get_width(),
|
||||
alloc.get_y() + alloc.get_height());
|
||||
|
||||
int x, y;
|
||||
Gdk::ModifierType mask;
|
||||
|
||||
get_window()->get_pointer (x, y, mask);
|
||||
|
||||
if ((allow_horiz && (x < scrolling_boundary.x0 || x >= scrolling_boundary.x1)) ||
|
||||
(allow_vert && (y < scrolling_boundary.y0 || y >= scrolling_boundary.y1))) {
|
||||
start_canvas_autoscroll (allow_horiz, allow_vert, scrolling_boundary);
|
||||
}
|
||||
}
|
||||
|
||||
if (startit && autoscroll_timeout_tag < 0) {
|
||||
start_canvas_autoscroll (autoscroll_x, autoscroll_y);
|
||||
}
|
||||
|
||||
last_autoscroll_x = autoscroll_x;
|
||||
last_autoscroll_y = autoscroll_y;
|
||||
}
|
||||
|
||||
gint
|
||||
Editor::_autoscroll_canvas (void *arg)
|
||||
bool
|
||||
Editor::autoscroll_active () const
|
||||
{
|
||||
return ((Editor *) arg)->autoscroll_canvas ();
|
||||
return autoscroll_connection.connected ();
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::autoscroll_canvas ()
|
||||
{
|
||||
framepos_t new_frame;
|
||||
framepos_t limit = max_framepos - current_page_samples();
|
||||
double new_pixel;
|
||||
int x, y;
|
||||
Gdk::ModifierType mask;
|
||||
frameoffset_t dx = 0;
|
||||
bool no_stop = false;
|
||||
bool y_motion = false;
|
||||
|
||||
if (autoscroll_x_distance != 0) {
|
||||
get_window()->get_pointer (x, y, mask);
|
||||
|
||||
if (autoscroll_x > 0) {
|
||||
autoscroll_x_distance = (_drags->current_pointer_frame() - (leftmost_frame + current_page_samples())) / 3;
|
||||
if (_autoscroll_fudging) {
|
||||
autoscroll_x_distance += autoscroll_fudge_threshold () / 3;
|
||||
}
|
||||
} else if (autoscroll_x < 0) {
|
||||
autoscroll_x_distance = (leftmost_frame - _drags->current_pointer_frame()) / 3;
|
||||
VisualChange vc;
|
||||
|
||||
}
|
||||
if (autoscroll_horizontal_allowed) {
|
||||
|
||||
framepos_t new_frame = leftmost_frame;
|
||||
|
||||
/* horizontal */
|
||||
|
||||
if (x > autoscroll_boundary.x1) {
|
||||
|
||||
/* bring it back into view */
|
||||
dx = x - autoscroll_boundary.x1;
|
||||
dx += 10 + (2 * (autoscroll_cnt/2));
|
||||
|
||||
dx = pixel_to_sample (dx);
|
||||
|
||||
if (leftmost_frame < max_framepos - dx) {
|
||||
new_frame = leftmost_frame + dx;
|
||||
} else {
|
||||
new_frame = max_framepos;
|
||||
}
|
||||
|
||||
if (autoscroll_y_distance != 0) {
|
||||
if (autoscroll_y > 0) {
|
||||
autoscroll_y_distance = (_drags->current_pointer_y() - _visible_canvas_height) / 3;
|
||||
} else if (autoscroll_y < 0) {
|
||||
no_stop = true;
|
||||
|
||||
autoscroll_y_distance = (vertical_adjustment.get_value () - _drags->current_pointer_y()) / 3;
|
||||
}
|
||||
}
|
||||
} else if (x < autoscroll_boundary.x0) {
|
||||
|
||||
if (autoscroll_x < 0) {
|
||||
if (leftmost_frame < autoscroll_x_distance) {
|
||||
dx = autoscroll_boundary.x0 - x;
|
||||
dx += 10 + (2 * (autoscroll_cnt/2));
|
||||
|
||||
dx = pixel_to_sample (dx);
|
||||
|
||||
if (leftmost_frame >= dx) {
|
||||
new_frame = leftmost_frame - dx;
|
||||
} else {
|
||||
new_frame = 0;
|
||||
} else {
|
||||
new_frame = leftmost_frame - autoscroll_x_distance;
|
||||
}
|
||||
} else if (autoscroll_x > 0) {
|
||||
if (leftmost_frame > limit - autoscroll_x_distance) {
|
||||
new_frame = limit;
|
||||
} else {
|
||||
new_frame = leftmost_frame + autoscroll_x_distance;
|
||||
}
|
||||
} else {
|
||||
new_frame = leftmost_frame;
|
||||
}
|
||||
|
||||
double vertical_pos = vertical_adjustment.get_value();
|
||||
|
||||
if (autoscroll_y < 0) {
|
||||
|
||||
if (vertical_pos < autoscroll_y_distance) {
|
||||
new_pixel = 0;
|
||||
} else {
|
||||
new_pixel = vertical_pos - autoscroll_y_distance;
|
||||
}
|
||||
|
||||
} else if (autoscroll_y > 0) {
|
||||
|
||||
new_pixel = min (_full_canvas_height - _visible_canvas_height, min (_full_canvas_height, (vertical_adjustment.get_value() + autoscroll_y_distance)));
|
||||
|
||||
} else {
|
||||
new_pixel = vertical_pos;
|
||||
}
|
||||
|
||||
if ((new_frame == 0 || new_frame == limit) && (new_pixel == 0 || new_pixel == DBL_MAX)) {
|
||||
/* we are done */
|
||||
return false;
|
||||
no_stop = true;
|
||||
}
|
||||
|
||||
if (new_frame != leftmost_frame) {
|
||||
reset_x_origin (new_frame);
|
||||
vc.time_origin = new_frame;
|
||||
vc.add (VisualChange::TimeOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_pixel != vertical_pos) {
|
||||
vertical_adjustment.set_value (new_pixel);
|
||||
if (autoscroll_vertical_allowed) {
|
||||
|
||||
const double vertical_pos = vertical_adjustment.get_value();
|
||||
double new_pixel = vertical_pos;
|
||||
const int speed_factor = 20;
|
||||
|
||||
/* vertical */
|
||||
|
||||
new_pixel = vertical_pos;
|
||||
|
||||
if (y < autoscroll_boundary.y0) {
|
||||
|
||||
/* scroll to make higher tracks visible */
|
||||
|
||||
if (autoscroll_cnt && (autoscroll_cnt % speed_factor == 0)) {
|
||||
y_motion = scroll_up_one_track ();
|
||||
}
|
||||
|
||||
/* fake an event. */
|
||||
} else if (y > autoscroll_boundary.y1) {
|
||||
|
||||
if (autoscroll_cnt && (autoscroll_cnt % speed_factor == 0)) {
|
||||
y_motion = scroll_down_one_track ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
no_stop = true;
|
||||
}
|
||||
|
||||
if (vc.pending) {
|
||||
|
||||
/* change horizontal first */
|
||||
|
||||
if (vc.pending) {
|
||||
visual_changer (vc);
|
||||
}
|
||||
|
||||
/* now send a motion event to notify anyone who cares
|
||||
that we have moved to a new location (because we scrolled)
|
||||
*/
|
||||
|
||||
Glib::RefPtr<Gdk::Window> canvas_window = const_cast<Editor*>(this)->_track_canvas->get_window();
|
||||
gint x, y;
|
||||
Gdk::ModifierType mask;
|
||||
GdkEventMotion ev;
|
||||
canvas_window->get_pointer (x, y, mask);
|
||||
|
||||
ev.type = GDK_MOTION_NOTIFY;
|
||||
ev.state = Gdk::BUTTON1_MASK;
|
||||
|
||||
/* the motion handler expects events in canvas coordinate space */
|
||||
ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (x, y));
|
||||
|
||||
/* first convert from Editor window coordinates to canvas
|
||||
* window coordinates
|
||||
*/
|
||||
|
||||
int cx;
|
||||
int cy;
|
||||
|
||||
/* clamp x and y to remain within the visible area */
|
||||
|
||||
x = min (max ((ArdourCanvas::Coord) x, autoscroll_boundary.x0), autoscroll_boundary.x1);
|
||||
y = min (max ((ArdourCanvas::Coord) y, autoscroll_boundary.y0), autoscroll_boundary.y1);
|
||||
|
||||
translate_coordinates (*_track_canvas_viewport, x, y, cx, cy);
|
||||
|
||||
ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (cx, cy));
|
||||
ev.x = d.x;
|
||||
ev.y = d.y;
|
||||
|
||||
motion_handler (0, (GdkEvent*) &ev, true);
|
||||
|
||||
autoscroll_cnt++;
|
||||
} else if (no_stop) {
|
||||
|
||||
if (autoscroll_cnt == 1) {
|
||||
/* not changing visual state but pointer is outside the scrolling boundary
|
||||
* so we still need to deliver a fake motion event
|
||||
*/
|
||||
|
||||
/* connect the timeout so that we get called repeatedly */
|
||||
GdkEventMotion ev;
|
||||
|
||||
autoscroll_timeout_tag = g_idle_add ( _autoscroll_canvas, this);
|
||||
ev.type = GDK_MOTION_NOTIFY;
|
||||
ev.state = Gdk::BUTTON1_MASK;
|
||||
|
||||
/* the motion handler expects events in canvas coordinate space */
|
||||
|
||||
/* first convert from Editor window coordinates to canvas
|
||||
* window coordinates
|
||||
*/
|
||||
|
||||
int cx;
|
||||
int cy;
|
||||
|
||||
/* clamp x and y to remain within the visible area. except
|
||||
* .. if horizontal scrolling is allowed, always allow us to
|
||||
* move back to zero
|
||||
*/
|
||||
|
||||
if (autoscroll_horizontal_allowed) {
|
||||
x = min (max ((ArdourCanvas::Coord) x, 0.0), autoscroll_boundary.x1);
|
||||
} else {
|
||||
x = min (max ((ArdourCanvas::Coord) x, autoscroll_boundary.x0), autoscroll_boundary.x1);
|
||||
}
|
||||
y = min (max ((ArdourCanvas::Coord) y, autoscroll_boundary.y0), autoscroll_boundary.y1);
|
||||
|
||||
translate_coordinates (*_track_canvas_viewport, x, y, cx, cy);
|
||||
|
||||
ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (cx, cy));
|
||||
ev.x = d.x;
|
||||
ev.y = d.y;
|
||||
|
||||
motion_handler (0, (GdkEvent*) &ev, true);
|
||||
|
||||
} else {
|
||||
stop_canvas_autoscroll ();
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
autoscroll_cnt++;
|
||||
|
||||
return true; /* call me again */
|
||||
}
|
||||
|
||||
void
|
||||
Editor::start_canvas_autoscroll (int dx, int dy)
|
||||
Editor::start_canvas_autoscroll (bool allow_horiz, bool allow_vert, const ArdourCanvas::Rect& boundary)
|
||||
{
|
||||
if (!_session || autoscroll_active) {
|
||||
if (!_session) {
|
||||
return;
|
||||
}
|
||||
|
||||
stop_canvas_autoscroll ();
|
||||
|
||||
autoscroll_active = true;
|
||||
autoscroll_x = dx;
|
||||
autoscroll_y = dy;
|
||||
autoscroll_x_distance = (framepos_t) floor (current_page_samples()/50.0);
|
||||
autoscroll_y_distance = fabs ((double)dy * 5); /* pixels */
|
||||
autoscroll_cnt = 0;
|
||||
autoscroll_horizontal_allowed = allow_horiz;
|
||||
autoscroll_vertical_allowed = allow_vert;
|
||||
autoscroll_boundary = boundary;
|
||||
|
||||
/* do it right now, which will start the repeated callbacks */
|
||||
/* do the first scroll right now
|
||||
*/
|
||||
|
||||
autoscroll_canvas ();
|
||||
|
||||
/* scroll again at very very roughly 30FPS */
|
||||
|
||||
autoscroll_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::autoscroll_canvas), 30);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::stop_canvas_autoscroll ()
|
||||
{
|
||||
if (autoscroll_timeout_tag >= 0) {
|
||||
g_source_remove (autoscroll_timeout_tag);
|
||||
autoscroll_timeout_tag = -1;
|
||||
}
|
||||
|
||||
autoscroll_active = false;
|
||||
autoscroll_connection.disconnect ();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -709,19 +749,26 @@ Editor::entered_track_canvas (GdkEventCrossing */*ev*/)
|
|||
}
|
||||
|
||||
void
|
||||
Editor::ensure_time_axis_view_is_visible (const TimeAxisView& tav)
|
||||
Editor::_ensure_time_axis_view_is_visible (const TimeAxisView& tav, bool at_top)
|
||||
{
|
||||
double begin = tav.y_position();
|
||||
|
||||
double v = vertical_adjustment.get_value ();
|
||||
|
||||
if (begin < v || begin + tav.current_height() > v + _visible_canvas_height) {
|
||||
if (!at_top && (begin < v || begin + tav.current_height() > v + _visible_canvas_height)) {
|
||||
/* try to put the TimeAxisView roughly central */
|
||||
if (begin >= _visible_canvas_height/2.0) {
|
||||
begin -= _visible_canvas_height/2.0;
|
||||
}
|
||||
vertical_adjustment.set_value (begin);
|
||||
}
|
||||
|
||||
/* Clamp the y pos so that we do not extend beyond the canvas full
|
||||
* height.
|
||||
*/
|
||||
if (_full_canvas_height - begin < _visible_canvas_height){
|
||||
begin = _full_canvas_height - _visible_canvas_height;
|
||||
}
|
||||
|
||||
vertical_adjustment.set_value (begin);
|
||||
}
|
||||
|
||||
/** Called when the main vertical_adjustment has changed */
|
||||
|
|
@ -748,8 +795,6 @@ Editor::set_horizontal_position (double p)
|
|||
}
|
||||
|
||||
update_video_timeline();
|
||||
|
||||
HorizontalPositionChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1009,6 +1009,13 @@ Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
|
|||
return typed_event (item, event, NoteItem);
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::canvas_bottom_rect_event (GdkEvent* event)
|
||||
{
|
||||
cerr << "CBR event, type " << event << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const& context, int x, int y, guint time)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -361,16 +361,16 @@ Drag::motion_handler (GdkEvent* event, bool from_autoscroll)
|
|||
|
||||
if (event->motion.state & Gdk::BUTTON1_MASK || event->motion.state & Gdk::BUTTON2_MASK) {
|
||||
if (!from_autoscroll) {
|
||||
bool const moving_left = _drags->current_pointer_x() < _last_pointer_x;
|
||||
bool const moving_up = _drags->current_pointer_y() < _last_pointer_y;
|
||||
_editor->maybe_autoscroll (true, allow_vertical_autoscroll (), moving_left, moving_up);
|
||||
_editor->maybe_autoscroll (true, allow_vertical_autoscroll (), false);
|
||||
}
|
||||
|
||||
if (!_editor->autoscroll_active() || from_autoscroll) {
|
||||
motion (event, _move_threshold_passed != old_move_threshold_passed);
|
||||
|
||||
_last_pointer_x = _drags->current_pointer_x ();
|
||||
_last_pointer_y = _drags->current_pointer_y ();
|
||||
_last_pointer_frame = adjusted_current_frame (event);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3912,9 +3912,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
|
|||
break;
|
||||
}
|
||||
|
||||
if (event->button.x >= _editor->horizontal_position() + _editor->_visible_canvas_width) {
|
||||
_editor->start_canvas_autoscroll (1, 0);
|
||||
}
|
||||
_editor->maybe_autoscroll (true, false, false);
|
||||
|
||||
if (start != end) {
|
||||
switch (_operation) {
|
||||
|
|
@ -4103,9 +4101,7 @@ RangeMarkerBarDrag::motion (GdkEvent* event, bool first_move)
|
|||
}
|
||||
}
|
||||
|
||||
if (event->button.x >= _editor->horizontal_position() + _editor->_visible_canvas_width) {
|
||||
_editor->start_canvas_autoscroll (1, 0);
|
||||
}
|
||||
_editor->maybe_autoscroll (true, false, false);
|
||||
|
||||
if (start != end) {
|
||||
_editor->temp_location->set (start, end);
|
||||
|
|
|
|||
|
|
@ -179,12 +179,12 @@ Editor::canvas_event_sample (GdkEvent const * event, double* pcx, double* pcy) c
|
|||
*pcy = y;
|
||||
}
|
||||
|
||||
/* note that pixel_to_sample() never returns less than zero, so even if the pixel
|
||||
/* note that pixel_to_sample_from_event() never returns less than zero, so even if the pixel
|
||||
position is negative (as can be the case with motion events in particular),
|
||||
the frame location is always positive.
|
||||
*/
|
||||
|
||||
return pixel_to_sample (x);
|
||||
return pixel_to_sample_from_event (x);
|
||||
}
|
||||
|
||||
Gdk::Cursor*
|
||||
|
|
@ -2914,8 +2914,6 @@ Editor::set_canvas_cursor_for_region_view (double x, RegionView* rv)
|
|||
return;
|
||||
}
|
||||
|
||||
assert (rv);
|
||||
|
||||
ArdourCanvas::Group* g = rv->get_canvas_group ();
|
||||
ArdourCanvas::Group* p = g->parent ();
|
||||
|
||||
|
|
@ -2927,17 +2925,23 @@ Editor::set_canvas_cursor_for_region_view (double x, RegionView* rv)
|
|||
assert (item_bbox);
|
||||
ArdourCanvas::Rect parent_bbox = g->item_to_parent (item_bbox.get ());
|
||||
|
||||
/* Halfway across the region */
|
||||
double const h = (parent_bbox.x0 + parent_bbox.x1) / 2;
|
||||
/* First or last 10% of region is used for trimming, if the whole
|
||||
region is wider than 20 pixels at the current zoom level.
|
||||
*/
|
||||
|
||||
double const w = parent_bbox.width();
|
||||
|
||||
if (w > 20.0 && x >= parent_bbox.x0 && x < parent_bbox.x1) {
|
||||
|
||||
Trimmable::CanTrim ct = rv->region()->can_trim ();
|
||||
if (x <= h) {
|
||||
|
||||
if (((x - parent_bbox.x0) / w) < 0.10) {
|
||||
if (ct & Trimmable::FrontTrimEarlier) {
|
||||
set_canvas_cursor (_cursors->left_side_trim, true);
|
||||
} else {
|
||||
set_canvas_cursor (_cursors->left_side_trim_right_only, true);
|
||||
}
|
||||
} else {
|
||||
} else if (((parent_bbox.x1 - x) / w) < 0.10) {
|
||||
if (ct & Trimmable::EndTrimLater) {
|
||||
set_canvas_cursor (_cursors->right_side_trim, true);
|
||||
} else {
|
||||
|
|
@ -2945,6 +2949,7 @@ Editor::set_canvas_cursor_for_region_view (double x, RegionView* rv)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Obtain the pointer position in canvas coordinates */
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1276,6 +1276,69 @@ Editor::scroll_tracks_up_line ()
|
|||
reset_y_origin (vertical_adjustment.get_value() - 60);
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::scroll_down_one_track ()
|
||||
{
|
||||
double vertical_pos = vertical_adjustment.get_value () + vertical_adjustment.get_page_size() - 1.0;
|
||||
|
||||
TrackViewList::reverse_iterator next = track_views.rend();
|
||||
std::pair<TimeAxisView*,double> res;
|
||||
|
||||
for (TrackViewList::reverse_iterator t = track_views.rbegin(); t != track_views.rend(); ++t) {
|
||||
if ((*t)->hidden()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
res = (*t)->covers_y_position (vertical_pos);
|
||||
|
||||
if (res.first) {
|
||||
break;
|
||||
}
|
||||
|
||||
next = t;
|
||||
}
|
||||
|
||||
/* move to the track below the first one that covers the */
|
||||
|
||||
if (next != track_views.rend()) {
|
||||
ensure_track_visible (*next);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::scroll_up_one_track ()
|
||||
{
|
||||
double vertical_pos = vertical_adjustment.get_value ();
|
||||
|
||||
TrackViewList::iterator prev = track_views.end();
|
||||
std::pair<TimeAxisView*,double> res;
|
||||
|
||||
for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
|
||||
|
||||
if ((*t)->hidden()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
res = (*t)->covers_y_position(vertical_pos);
|
||||
|
||||
if (res.first) {
|
||||
break;
|
||||
}
|
||||
|
||||
prev = t;
|
||||
}
|
||||
|
||||
if (prev != track_views.end()) {
|
||||
ensure_track_visible (*prev);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ZOOM */
|
||||
|
||||
void
|
||||
|
|
@ -4755,12 +4818,17 @@ Editor::fork_region ()
|
|||
MidiRegionView* const mrv = dynamic_cast<MidiRegionView*>(*r);
|
||||
|
||||
if (mrv) {
|
||||
try {
|
||||
boost::shared_ptr<Playlist> playlist = mrv->region()->playlist();
|
||||
boost::shared_ptr<MidiRegion> newregion = mrv->midi_region()->clone ();
|
||||
boost::shared_ptr<MidiSource> new_source = _session->create_midi_source_by_stealing_name (mrv->midi_view()->track());
|
||||
boost::shared_ptr<MidiRegion> newregion = mrv->midi_region()->clone (new_source);
|
||||
|
||||
playlist->clear_changes ();
|
||||
playlist->replace_region (mrv->region(), newregion, mrv->region()->position());
|
||||
_session->add_command(new StatefulDiffCommand (playlist));
|
||||
} catch (...) {
|
||||
error << string_compose (_("Could not unlink %1"), mrv->region()->name()) << endmsg;
|
||||
}
|
||||
}
|
||||
|
||||
r = tmp;
|
||||
|
|
@ -6432,13 +6500,14 @@ Editor::remove_tracks ()
|
|||
|
||||
for (TrackSelection::iterator x = ts.begin(); x != ts.end(); ++x) {
|
||||
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*x);
|
||||
if (rtv) {
|
||||
if (!rtv) {
|
||||
continue;
|
||||
}
|
||||
if (rtv->is_track()) {
|
||||
ntracks++;
|
||||
} else {
|
||||
nbusses++;
|
||||
}
|
||||
}
|
||||
routes.push_back (rtv->_route);
|
||||
|
||||
if (rtv->route()->is_master() || rtv->route()->is_monitor()) {
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ EditorRoutes::EditorRoutes (Editor* e)
|
|||
_display.set_headers_visible (true);
|
||||
_display.get_selection()->set_mode (SELECTION_SINGLE);
|
||||
_display.get_selection()->set_select_function (sigc::mem_fun (*this, &EditorRoutes::selection_filter));
|
||||
_display.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::selection_changed));
|
||||
_display.set_reorderable (true);
|
||||
_display.set_name (X_("EditGroupList"));
|
||||
_display.set_rules_hint (true);
|
||||
|
|
@ -1292,27 +1293,46 @@ EditorRoutes::button_press (GdkEventButton* ev)
|
|||
//Scroll editor canvas to selected track
|
||||
if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
|
||||
|
||||
// Get the model row.
|
||||
Gtk::TreeModel::Row row = *_model->get_iter (path);
|
||||
|
||||
TimeAxisView *tv = row[_columns.tv];
|
||||
|
||||
int y_pos = tv->y_position();
|
||||
|
||||
//Clamp the y pos so that we do not extend beyond the canvas full height.
|
||||
if (_editor->_full_canvas_height - y_pos < _editor->_visible_canvas_height){
|
||||
y_pos = _editor->_full_canvas_height - _editor->_visible_canvas_height;
|
||||
}
|
||||
|
||||
//Only scroll to if the track is visible
|
||||
if(y_pos != -1){
|
||||
_editor->reset_y_origin (y_pos);
|
||||
if (tv) {
|
||||
_editor->ensure_time_axis_view_is_visible (*tv, true);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
EditorRoutes::selection_changed ()
|
||||
{
|
||||
if (_display.get_selection()->count_selected_rows() > 0) {
|
||||
|
||||
TreeIter iter;
|
||||
TreeView::Selection::ListHandle_Path rows = _display.get_selection()->get_selected_rows ();
|
||||
TrackViewList selected;
|
||||
|
||||
_editor->get_selection().clear_regions ();
|
||||
|
||||
for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
|
||||
|
||||
if ((iter = _model->get_iter (*i))) {
|
||||
|
||||
TimeAxisView* tv = (*iter)[_columns.tv];
|
||||
selected.push_back (tv);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_editor->get_selection().set (selected);
|
||||
_editor->ensure_time_axis_view_is_visible (*(selected.front()), true);
|
||||
|
||||
} else {
|
||||
_editor->get_selection().clear_tracks ();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const&, bool /*selected*/)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ private:
|
|||
void show_all_miditracks ();
|
||||
void hide_all_miditracks ();
|
||||
void show_tracks_with_regions_at_playhead ();
|
||||
void selection_changed ();
|
||||
|
||||
void display_drag_data_received (
|
||||
Glib::RefPtr<Gdk::DragContext> const &, gint, gint, Gtk::SelectionData const &, guint, guint
|
||||
|
|
|
|||
|
|
@ -1608,7 +1608,7 @@ EngineControl::EngineControl ()
|
|||
uint32_t il = (uint32_t) input_latency.get_value ();
|
||||
uint32_t ol = (uint32_t) input_latency.get_value ();
|
||||
|
||||
/* reset to zero so that our new test instance of JACK
|
||||
/* reset to zero so that our new test instance
|
||||
will be clean of any existing latency measures.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@
|
|||
; (gtk_accel_path "<Actions>/Snap/snap-to-eighths" "")
|
||||
(gtk_accel_path "<Actions>/Editor/select-all-after-playhead" "<@TERTIARY@><@PRIMARY@>p")
|
||||
(gtk_accel_path "<Actions>/Common/ToggleMaximalEditor" "F11")
|
||||
(gtk_accel_path "<Actions>/Common/ToggleMaximalMixer" "F12")
|
||||
; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileLength" "")
|
||||
; (gtk_accel_path "<Actions>/Editor/Timecode" "")
|
||||
; (gtk_accel_path "<Actions>/Transport/PlaySelection" "")
|
||||
|
|
|
|||
|
|
@ -1022,6 +1022,7 @@ GainMeter::get_gm_width ()
|
|||
{
|
||||
Gtk::Requisition sz;
|
||||
int min_w = 0;
|
||||
sz.width = 0;
|
||||
meter_metric_area.size_request (sz);
|
||||
min_w += sz.width;
|
||||
level_meter->size_request (sz);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@
|
|||
|
||||
#include "i18n.h"
|
||||
|
||||
#ifdef COMPILER_MSVC
|
||||
#include <fcntl.h> // Needed for '_fmode'
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace Gtk;
|
||||
|
|
@ -138,8 +141,15 @@ sigpipe_handler (int /*signal*/)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef WINDOWS_VST_SUPPORT
|
||||
#if (defined(COMPILER_MSVC) && defined(NDEBUG) && !defined(RDC_BUILD))
|
||||
/*
|
||||
* Release build with MSVC uses ardour_main()
|
||||
*/
|
||||
int ardour_main (int argc, char *argv[])
|
||||
|
||||
#elif (defined WINDOWS_VST_SUPPORT && !defined PLATFORM_WINDOWS)
|
||||
|
||||
// prototype for function in windows_vst_plugin_ui.cc
|
||||
extern int windows_vst_gui_init (int* argc, char** argv[]);
|
||||
|
||||
/* this is called from the entry point of a wine-compiled
|
||||
|
|
@ -147,14 +157,22 @@ extern int windows_vst_gui_init (int* argc, char** argv[]);
|
|||
as a shared library.
|
||||
*/
|
||||
extern "C" {
|
||||
|
||||
int ardour_main (int argc, char *argv[])
|
||||
|
||||
#else
|
||||
int main (int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
#ifdef COMPILER_MSVC
|
||||
// Essential!! Make sure that any files used by Ardour
|
||||
// will be created or opened in BINARY mode!
|
||||
_fmode = O_BINARY;
|
||||
#endif
|
||||
|
||||
fixup_bundle_environment (argc, argv, &localedir);
|
||||
|
||||
load_custom_fonts(); /* needs to happend before any gtk and pango init calls */
|
||||
load_custom_fonts(); /* needs to happen before any gtk and pango init calls */
|
||||
|
||||
if (!Glib::thread_supported()) {
|
||||
Glib::thread_init();
|
||||
|
|
@ -164,15 +182,15 @@ int main (int argc, char *argv[])
|
|||
gtk_set_locale ();
|
||||
#endif
|
||||
|
||||
#ifdef WINDOWS_VST_SUPPORT
|
||||
/* this does some magic that is needed to make GTK and Wine's own
|
||||
X11 client interact properly.
|
||||
#if (defined WINDOWS_VST_SUPPORT && !defined PLATFORM_WINDOWS)
|
||||
/* this does some magic that is needed to make GTK and X11 client interact properly.
|
||||
* the platform dependent code is in windows_vst_plugin_ui.cc
|
||||
*/
|
||||
windows_vst_gui_init (&argc, &argv);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
cerr << "bnd txt domain [" << PACKAGE << "] to " << localedir << endl;
|
||||
cerr << "bind txt domain [" << PACKAGE << "] to " << localedir << endl;
|
||||
|
||||
(void) bindtextdomain (PACKAGE, localedir);
|
||||
/* our i18n translations are all in UTF-8, so make sure
|
||||
|
|
@ -198,6 +216,16 @@ int main (int argc, char *argv[])
|
|||
#endif
|
||||
|
||||
if (parse_opts (argc, argv)) {
|
||||
#if (defined(COMPILER_MSVC) && defined(NDEBUG) && !defined(RDC_BUILD))
|
||||
// Since we don't ordinarily have access to stdout and stderr with
|
||||
// an MSVC app, let the user know we encountered a parsing error.
|
||||
Gtk::Main app(&argc, &argv); // Calls 'gtk_init()'
|
||||
|
||||
Gtk::MessageDialog dlgReportParseError (_("\n Ardour could not understand your command line "),
|
||||
false, MESSAGE_ERROR, BUTTONS_CLOSE, true);
|
||||
dlgReportParseError.set_title (_("An error was encountered while launching Ardour"));
|
||||
dlgReportParseError.run ();
|
||||
#endif
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
|
@ -260,7 +288,6 @@ int main (int argc, char *argv[])
|
|||
|
||||
return 0;
|
||||
}
|
||||
#ifdef WINDOWS_VST_SUPPORT
|
||||
} // end of extern C block
|
||||
#if (defined WINDOWS_VST_SUPPORT && !defined PLATFORM_WINDOWS)
|
||||
} // end of extern "C" block
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &
|
|||
void
|
||||
MidiRegionView::parameter_changed (std::string const & p)
|
||||
{
|
||||
if (p == "diplay-first-midi-bank-as-zero") {
|
||||
if (p == "display-first-midi-bank-as-zero") {
|
||||
if (_enable_display) {
|
||||
redisplay_model();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1521,8 +1521,7 @@ MidiTimeAxisView::add_region (framepos_t pos, framecnt_t length, bool commit)
|
|||
|
||||
real_editor->snap_to (pos, 0);
|
||||
|
||||
boost::shared_ptr<Source> src = _session->create_midi_source_for_session (
|
||||
view()->trackview().track().get(), view()->trackview().track()->name());
|
||||
boost::shared_ptr<Source> src = _session->create_midi_source_by_stealing_name (view()->trackview().track());
|
||||
PropertyList plist;
|
||||
|
||||
plist.add (ARDOUR::Properties::start, 0);
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ MissingFileDialog::add_chosen ()
|
|||
break;
|
||||
}
|
||||
|
||||
split (str, dirs, ':');
|
||||
split (str, dirs, G_SEARCHPATH_SEPARATOR);
|
||||
|
||||
newdir = chooser.get_filename ();
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ MissingFileDialog::add_chosen ()
|
|||
}
|
||||
|
||||
if (!str.empty()) {
|
||||
str += ':';
|
||||
str += G_SEARCHPATH_SEPARATOR;
|
||||
}
|
||||
|
||||
str += newdir;
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ MixerStrip::init ()
|
|||
button_size_group->add_widget (*monitor_input_button);
|
||||
}
|
||||
|
||||
name_button.add_elements ( ArdourButton::FlatFace );
|
||||
name_button.add_elements ( ArdourButton::Inset );
|
||||
top_button_table.attach (name_button, 0, 2, 2, 3);
|
||||
auto_n_io_table.attach (automation_label, 0, 1, 0, 1);
|
||||
automation_label.show();
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@ Mixer_UI::Mixer_UI ()
|
|||
group_display.show();
|
||||
|
||||
_in_group_rebuild_or_clear = false;
|
||||
_maximised = false;
|
||||
|
||||
MixerStrip::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::remove_strip, this, _1), gui_context());
|
||||
|
||||
|
|
@ -1562,6 +1563,19 @@ Mixer_UI::set_state (const XMLNode& node)
|
|||
}
|
||||
}
|
||||
|
||||
if ((prop = node.property ("maximised"))) {
|
||||
bool yn = string_is_affirmative (prop->value());
|
||||
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalMixer"));
|
||||
assert (act);
|
||||
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
|
||||
bool fs = tact && tact->get_active();
|
||||
if (yn ^ fs) {
|
||||
ActionManager::do_action ("Common",
|
||||
"ToggleMaximalMixer");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1604,6 +1618,8 @@ Mixer_UI::get_state (void)
|
|||
|
||||
node->add_property ("show-mixer", _visible ? "yes" : "no");
|
||||
|
||||
node->add_property ("maximised", _maximised ? "yes" : "no");
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
|
|
@ -1945,3 +1961,26 @@ Mixer_UI::toggle_midi_input_active (bool flip_others)
|
|||
_session->set_exclusive_input_active (rl, onoff, flip_others);
|
||||
}
|
||||
|
||||
void
|
||||
Mixer_UI::maximise_mixer_space ()
|
||||
{
|
||||
if (_maximised) {
|
||||
return;
|
||||
}
|
||||
|
||||
fullscreen ();
|
||||
|
||||
_maximised = true;
|
||||
}
|
||||
|
||||
void
|
||||
Mixer_UI::restore_mixer_space ()
|
||||
{
|
||||
if (!_maximised) {
|
||||
return;
|
||||
}
|
||||
|
||||
unfullscreen();
|
||||
|
||||
_maximised = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,9 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
|
|||
void show_strip (MixerStrip *);
|
||||
void hide_strip (MixerStrip *);
|
||||
|
||||
void maximise_mixer_space();
|
||||
void restore_mixer_space();
|
||||
|
||||
void ensure_float (Gtk::Window&);
|
||||
|
||||
MonitorSection* monitor_section() const { return _monitor_section; }
|
||||
|
|
@ -279,6 +282,9 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
|
|||
bool _following_editor_selection;
|
||||
|
||||
void monitor_section_going_away ();
|
||||
|
||||
/// true if we are in fullscreen mode
|
||||
bool _maximised;
|
||||
};
|
||||
|
||||
#endif /* __ardour_mixer_ui_h__ */
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ This mode provides many different operations on both regions and control points,
|
|||
@trans|Editor/toggle-follow-playhead|<@PRIMARY@>f|toggle playhead tracking
|
||||
@trans|Transport/ToggleFollowEdits|<@TERTIARY@>f|toggle playhead follows edits
|
||||
@wvis|Common/ToggleMaximalEditor|<@PRIMARY@><@SECONDARY@>f|maximise editor space
|
||||
@wvis|Common/ToggleMaximalMixer|F12|maximise mixer space
|
||||
@wvis|Region/show-rhythm-ferret|<@WINDOW@>f|show rhythm ferret window
|
||||
@mmode|MouseMode/set-mouse-mode-gain|g|region gain mode
|
||||
@epp|Region/play-selected-regions|h|play selected region(s)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@
|
|||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#else
|
||||
#include <process.h> // Needed for 'getpid()'
|
||||
|
||||
#include <lo/lo_osc_types.h>
|
||||
#define LO_TT_IMMEDIATE lo_get_tt_immediate()
|
||||
lo_timetag lo_get_tt_immediate() { lo_timetag tt = {0U,1U}; return tt; }
|
||||
#endif
|
||||
|
||||
namespace NSM
|
||||
|
|
|
|||
|
|
@ -266,9 +266,14 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
|
|||
virtual framecnt_t current_page_samples() const = 0;
|
||||
virtual double visible_canvas_height () const = 0;
|
||||
virtual void temporal_zoom_step (bool coarser) = 0;
|
||||
virtual void ensure_time_axis_view_is_visible (const TimeAxisView& tav) = 0;
|
||||
virtual void ensure_time_axis_view_is_visible (const TimeAxisView& tav, bool at_top = false) {
|
||||
_ensure_time_axis_view_is_visible (tav, at_top);
|
||||
}
|
||||
virtual void override_visible_track_count () = 0;
|
||||
virtual void scroll_tracks_down_line () = 0;
|
||||
virtual void scroll_tracks_up_line () = 0;
|
||||
virtual bool scroll_down_one_track () = 0;
|
||||
virtual bool scroll_up_one_track () = 0;
|
||||
virtual void prepare_for_cleanup () = 0;
|
||||
virtual void finish_cleanup () = 0;
|
||||
virtual void reset_x_origin (framepos_t frame) = 0;
|
||||
|
|
@ -302,8 +307,6 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
|
|||
virtual void get_equivalent_regions (RegionView* rv, std::vector<RegionView*>&, PBD::PropertyID) const = 0;
|
||||
|
||||
sigc::signal<void> ZoomChanged;
|
||||
/** Emitted when the horizontal position of the editor view changes */
|
||||
sigc::signal<void> HorizontalPositionChanged;
|
||||
sigc::signal<void> Realized;
|
||||
sigc::signal<void,framepos_t> UpdateAllTransportClocks;
|
||||
|
||||
|
|
@ -381,8 +384,9 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
|
|||
virtual Gtkmm2ext::TearOff* tools_tearoff () const = 0;
|
||||
|
||||
virtual DragManager* drags () const = 0;
|
||||
virtual void maybe_autoscroll (bool, bool, bool, bool) = 0;
|
||||
virtual void maybe_autoscroll (bool, bool, bool from_headers) = 0;
|
||||
virtual void stop_canvas_autoscroll () = 0;
|
||||
virtual bool autoscroll_active() const = 0;
|
||||
|
||||
virtual MouseCursors const * cursors () const = 0;
|
||||
virtual VerboseCursor * verbose_cursor () const = 0;
|
||||
|
|
@ -407,6 +411,9 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
|
|||
|
||||
PBD::Signal0<void> SnapChanged;
|
||||
PBD::Signal0<void> MouseModeChanged;
|
||||
|
||||
protected:
|
||||
virtual void _ensure_time_axis_view_is_visible (const TimeAxisView& tav, bool at_top) = 0;
|
||||
};
|
||||
|
||||
#endif // __gtk_ardour_public_editor_h__
|
||||
|
|
|
|||
|
|
@ -1795,6 +1795,8 @@ RCOptionEditor::RCOptionEditor ()
|
|||
sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
|
||||
));
|
||||
|
||||
add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
|
||||
|
||||
add_option (_("Audio"),
|
||||
new BoolOption (
|
||||
"auto-analyse-audio",
|
||||
|
|
@ -2016,7 +2018,7 @@ RCOptionEditor::RCOptionEditor ()
|
|||
|
||||
add_option (_("MIDI"),
|
||||
new BoolOption (
|
||||
"diplay-first-midi-bank-as-zero",
|
||||
"display-first-midi-bank-as-zero",
|
||||
_("Display first MIDI bank/program as 0"),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
|
||||
|
|
@ -2122,6 +2124,14 @@ RCOptionEditor::RCOptionEditor ()
|
|||
sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_tooltips)
|
||||
));
|
||||
|
||||
add_option (S_("Preferences|GUI"),
|
||||
new BoolOption (
|
||||
"show-name-highlight",
|
||||
_("use name highlight bars in region displays"),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_name_highlight),
|
||||
sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_name_highlight)
|
||||
));
|
||||
|
||||
#ifndef GTKOSX
|
||||
/* font scaling does nothing with GDK/Quartz */
|
||||
add_option (S_("Preferences|GUI"), new FontScalingOptions (_rc_config));
|
||||
|
|
@ -2142,6 +2152,7 @@ RCOptionEditor::RCOptionEditor ()
|
|||
_mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
|
||||
_mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
|
||||
_mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
|
||||
_mixer_strip_visibility.add (0, X_("Group"), _("Group"));
|
||||
_mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
|
||||
|
||||
add_option (
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ RegionView::init (Gdk::Color const & basic_color, bool wfd)
|
|||
if (name_highlight) {
|
||||
name_highlight->set_data ("regionview", this);
|
||||
name_highlight->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_name_highlight_event), name_highlight, this));
|
||||
}
|
||||
|
||||
if (frame_handle_start) {
|
||||
frame_handle_start->set_data ("regionview", this);
|
||||
|
|
@ -182,7 +183,6 @@ RegionView::init (Gdk::Color const & basic_color, bool wfd)
|
|||
frame_handle_end->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_frame_handle_event), frame_handle_end, this));
|
||||
frame_handle_end->raise_to_top();
|
||||
}
|
||||
}
|
||||
|
||||
if (name_text) {
|
||||
name_text->set_data ("regionview", this);
|
||||
|
|
|
|||
|
|
@ -206,9 +206,10 @@ RouteTimeAxisView::set_route (boost::shared_ptr<Route> rt)
|
|||
if (!_route->is_master()) {
|
||||
controls_table.attach (*solo_button, 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
|
||||
}
|
||||
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
controls_table.attach (route_group_button, 7, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
|
||||
// controls_table.attach (gm.get_gain_slider(), 0, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::AttachOptions (0), 3, 0);
|
||||
}
|
||||
|
||||
ARDOUR_UI::instance()->set_tip(*solo_button,_("Solo"));
|
||||
ARDOUR_UI::instance()->set_tip(*mute_button,_("Mute"));
|
||||
|
|
@ -222,9 +223,11 @@ RouteTimeAxisView::set_route (boost::shared_ptr<Route> rt)
|
|||
|
||||
label_view ();
|
||||
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
controls_table.attach (automation_button, 6, 7, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
|
||||
}
|
||||
|
||||
if (is_track() && track()->mode() == ARDOUR::Normal) {
|
||||
if (!ARDOUR::Profile->get_trx() && is_track() && track()->mode() == ARDOUR::Normal) {
|
||||
controls_table.attach (playlist_button, 5, 6, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
|
||||
}
|
||||
|
||||
|
|
@ -725,7 +728,7 @@ RouteTimeAxisView::set_track_mode (TrackMode mode, bool apply_to_selection)
|
|||
_editor.get_selection().tracks.foreach_route_time_axis (boost::bind (&RouteTimeAxisView::set_track_mode, _1, mode, false));
|
||||
} else {
|
||||
|
||||
bool needs_bounce;
|
||||
bool needs_bounce = false;
|
||||
|
||||
if (!track()->can_use_mode (mode, needs_bounce)) {
|
||||
|
||||
|
|
|
|||
|
|
@ -588,7 +588,7 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
|
|||
}
|
||||
|
||||
if (!_session->engine().connected()) {
|
||||
MessageDialog msg (_("Not connected to JACK - cannot engage record"));
|
||||
MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
|
||||
msg.run ();
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ SearchPathOption::set_state_from_config ()
|
|||
clear ();
|
||||
path_box.pack_start (session_label);
|
||||
|
||||
split (str, dirs, ':');
|
||||
split (str, dirs, G_SEARCHPATH_SEPARATOR);
|
||||
|
||||
for (vector<string>::iterator d = dirs.begin(); d != dirs.end(); ++d) {
|
||||
add_path (*d);
|
||||
|
|
@ -118,7 +118,7 @@ SearchPathOption::changed ()
|
|||
for (list<PathEntry*>::iterator p = paths.begin(); p != paths.end(); ++p) {
|
||||
|
||||
if (!str.empty()) {
|
||||
str += ':';
|
||||
str += G_SEARCHPATH_SEPARATOR;
|
||||
}
|
||||
str += (*p)->entry.get_text ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ SessionOptionEditor::SessionOptionEditor (Session* s)
|
|||
|
||||
add_option (_("Sync"), new BoolOption (
|
||||
"videotimeline-pullup",
|
||||
_("Apply Pull-Up/Down to Video Timeline and Video Monitor (Unless in JACK-sync)."),
|
||||
_("Apply Pull-Up/Down to Video Timeline and Video Monitor (Unless using JACK-sync)."),
|
||||
sigc::mem_fun (*_session_config, &SessionConfiguration::get_videotimeline_pullup),
|
||||
sigc::mem_fun (*_session_config, &SessionConfiguration::set_videotimeline_pullup)
|
||||
));
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include "gtk2ardour-config.h"
|
||||
#endif
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
#include <map>
|
||||
#include <cerrno>
|
||||
#include <sstream>
|
||||
|
|
@ -69,8 +71,6 @@
|
|||
|
||||
#include "sfdb_freesound_mootcher.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
using namespace std;
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ TimeAxisView::controls_ebox_scroll (GdkEventScroll* ev)
|
|||
e.stepping_axis_view()->step_height (false);
|
||||
return true;
|
||||
} else if (Keyboard::no_modifiers_active (ev->state)) {
|
||||
_editor.scroll_tracks_up_line();
|
||||
_editor.scroll_up_one_track();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
|
@ -313,7 +313,7 @@ TimeAxisView::controls_ebox_scroll (GdkEventScroll* ev)
|
|||
e.stepping_axis_view()->step_height (true);
|
||||
return true;
|
||||
} else if (Keyboard::no_modifiers_active (ev->state)) {
|
||||
_editor.scroll_tracks_down_line();
|
||||
_editor.scroll_down_one_track();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
|
@ -370,32 +370,11 @@ TimeAxisView::controls_ebox_motion (GdkEventMotion* ev)
|
|||
* are pretending that the drag is taking place over the canvas
|
||||
* (which perhaps in the glorious future, when track headers
|
||||
* and the canvas are unified, will actually be true.)
|
||||
*
|
||||
* First, translate the event coordinates into the canvas
|
||||
* coordinate space that DragManager::motion_handler is
|
||||
* expecting (this requires translation into the *window*
|
||||
* coordinates for the track canvas window, and then conversion
|
||||
* from window to canvas coordinate spaces).
|
||||
*
|
||||
* Then fake a DragManager motion event so that when
|
||||
* maybe_autoscroll asks DragManager for the current pointer
|
||||
* position it will get the correct answers.
|
||||
*/
|
||||
|
||||
int tx, ty;
|
||||
controls_ebox.translate_coordinates (*_editor.get_track_canvas(), ev->x, ev->y, tx, ty);
|
||||
_editor.maybe_autoscroll (false, true, true);
|
||||
|
||||
/* x-axis of track headers is not shared with the canvas, but
|
||||
the y-axis is, so we we can get a valid translation here.
|
||||
*/
|
||||
|
||||
Duple canvas_coord = _editor.get_track_canvas()->canvas()->window_to_canvas (Duple (tx, ty));
|
||||
ev->y = (int) floor (canvas_coord.y);
|
||||
|
||||
_editor.drags()->motion_handler ((GdkEvent *) ev, false);
|
||||
_editor.maybe_autoscroll (false, true, false, ev->y_root < _resize_drag_start);
|
||||
|
||||
/* now do the actual TAV resize */
|
||||
/* now schedule the actual TAV resize */
|
||||
int32_t const delta = (int32_t) floor (ev->y_root - _resize_drag_start);
|
||||
_editor.add_to_idle_resize (this, delta);
|
||||
_resize_drag_start = ev->y_root;
|
||||
|
|
@ -545,6 +524,8 @@ TimeAxisView::set_height (uint32_t h)
|
|||
/* resize the selection rect */
|
||||
show_selection (_editor.get_selection().time);
|
||||
}
|
||||
|
||||
_editor.override_visible_track_count ();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
#include "canvas/text.h"
|
||||
#include "canvas/utils.h"
|
||||
|
||||
#include "ardour/profile.h"
|
||||
|
||||
#include "ardour_ui.h"
|
||||
/*
|
||||
* ardour_ui.h was moved up in the include list
|
||||
|
|
@ -87,8 +89,20 @@ TimeAxisViewItem::set_constant_heights ()
|
|||
layout = foo.create_pango_layout (X_("H")); /* just the ascender */
|
||||
|
||||
NAME_HEIGHT = height;
|
||||
|
||||
/* Config->get_show_name_highlight) == true:
|
||||
Y_OFFSET is measured from bottom of the time axis view item.
|
||||
Config->get_show_name_highlight) == false:
|
||||
Y_OFFSET is measured from the top of the time axis view item.
|
||||
*/
|
||||
|
||||
if (Config->get_show_name_highlight()) {
|
||||
NAME_Y_OFFSET = height + 1;
|
||||
NAME_HIGHLIGHT_SIZE = height + 2;
|
||||
} else {
|
||||
NAME_Y_OFFSET = 3;
|
||||
NAME_HIGHLIGHT_SIZE = 0;
|
||||
}
|
||||
NAME_HIGHLIGHT_THRESH = NAME_HIGHLIGHT_SIZE * 3;
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +203,7 @@ TimeAxisViewItem::init (ArdourCanvas::Group* parent, double fpp, Gdk::Color cons
|
|||
|
||||
if (visibility & ShowFrame) {
|
||||
frame = new ArdourCanvas::Rectangle (group,
|
||||
ArdourCanvas::Rect (0.0, 1.0,
|
||||
ArdourCanvas::Rect (0.0, 0.0,
|
||||
trackview.editor().sample_to_pixel(duration) + RIGHT_EDGE_SHIFT,
|
||||
trackview.current_height() - 1.0));
|
||||
|
||||
|
|
@ -203,14 +217,14 @@ TimeAxisViewItem::init (ArdourCanvas::Group* parent, double fpp, Gdk::Color cons
|
|||
frame->set_outline_color (ARDOUR_UI::config()->get_canvasvar_TimeAxisFrame());
|
||||
}
|
||||
|
||||
// frame->set_outline_what (ArdourCanvas::Rectangle::What (ArdourCanvas::Rectangle::RIGHT|ArdourCanvas::Rectangle::LEFT));
|
||||
frame->set_outline_what (ArdourCanvas::Rectangle::What (ArdourCanvas::Rectangle::RIGHT|ArdourCanvas::Rectangle::LEFT));
|
||||
|
||||
} else {
|
||||
|
||||
frame = 0;
|
||||
}
|
||||
|
||||
if (visibility & ShowNameHighlight) {
|
||||
if (Config->get_show_name_highlight() && (visibility & ShowNameHighlight)) {
|
||||
|
||||
double width;
|
||||
double start;
|
||||
|
|
@ -240,7 +254,11 @@ TimeAxisViewItem::init (ArdourCanvas::Group* parent, double fpp, Gdk::Color cons
|
|||
if (visibility & ShowNameText) {
|
||||
name_text = new ArdourCanvas::Text (group);
|
||||
CANVAS_DEBUG_NAME (name_text, string_compose ("name text for %1", get_item_name()));
|
||||
if (Config->get_show_name_highlight()) {
|
||||
name_text->set_position (ArdourCanvas::Duple (NAME_X_OFFSET, trackview.current_height() - NAME_Y_OFFSET));
|
||||
} else {
|
||||
name_text->set_position (ArdourCanvas::Duple (NAME_X_OFFSET, NAME_Y_OFFSET));
|
||||
}
|
||||
name_text->set_font_description (NAME_FONT);
|
||||
} else {
|
||||
name_text = 0;
|
||||
|
|
@ -570,7 +588,11 @@ TimeAxisViewItem::set_height (double height)
|
|||
manage_name_highlight ();
|
||||
|
||||
if (visibility & ShowNameText) {
|
||||
if (Config->get_show_name_highlight()) {
|
||||
name_text->set_y_position (height - NAME_Y_OFFSET);
|
||||
} else {
|
||||
name_text->set_y_position (NAME_Y_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
if (frame) {
|
||||
|
|
@ -834,6 +856,13 @@ TimeAxisViewItem::set_frame_gradient ()
|
|||
void
|
||||
TimeAxisViewItem::set_trim_handle_colors()
|
||||
{
|
||||
#if 1
|
||||
/* Leave them transparent for now */
|
||||
if (frame_handle_start) {
|
||||
frame_handle_start->set_fill_color (0x00000000);
|
||||
frame_handle_end->set_fill_color (0x00000000);
|
||||
}
|
||||
#else
|
||||
if (frame_handle_start) {
|
||||
if (position_locked) {
|
||||
frame_handle_start->set_fill_color (ARDOUR_UI::config()->get_canvasvar_TrimHandleLocked());
|
||||
|
|
@ -843,6 +872,7 @@ TimeAxisViewItem::set_trim_handle_colors()
|
|||
frame_handle_end->set_fill_color (ARDOUR_UI::config()->get_canvasvar_TrimHandle());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "gtkmm2ext/actions.h"
|
||||
|
||||
#include "ardour/location.h"
|
||||
#include "ardour/profile.h"
|
||||
#include "ardour/session.h"
|
||||
|
||||
#include "time_info_box.h"
|
||||
|
|
@ -71,7 +72,9 @@ TimeInfoBox::TimeInfoBox ()
|
|||
set_border_width (2);
|
||||
|
||||
pack_start (left, true, true);
|
||||
if (!ARDOUR::Profile->get_trx()) {
|
||||
pack_start (right, true, true);
|
||||
}
|
||||
|
||||
left.set_homogeneous (false);
|
||||
left.set_spacings (0);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ TranscodeFfmpeg::TranscodeFfmpeg (std::string f)
|
|||
m_avoffset = m_lead_in = m_lead_out = 0;
|
||||
m_width = m_height = 0;
|
||||
m_aspect = m_fps = 0;
|
||||
m_sar = "";
|
||||
#if 1 /* tentative debug mode */
|
||||
debug_enable = false;
|
||||
#endif
|
||||
|
|
@ -138,6 +139,7 @@ TranscodeFfmpeg::probe ()
|
|||
m_width = m_height = 0;
|
||||
m_fps = m_aspect = 0;
|
||||
m_duration = 0;
|
||||
m_sar.clear();
|
||||
m_codec.clear();
|
||||
m_audio.clear();
|
||||
|
||||
|
|
@ -199,6 +201,13 @@ TranscodeFfmpeg::probe ()
|
|||
m_duration = atof(value) * m_fps * timebase;
|
||||
} else if (key == X_("duration") && m_fps != 0 && m_duration == 0) {
|
||||
m_duration = atof(value) * m_fps;
|
||||
} else if (key == X_("sample_aspect_ratio")) {
|
||||
std::string::size_type pos;
|
||||
pos = value.find_first_of(':');
|
||||
if (pos != std::string::npos && atof(value.substr(pos+1)) != 0) {
|
||||
m_sar = value;
|
||||
m_sar.replace(pos, 1, "/");
|
||||
}
|
||||
} else if (key == X_("display_aspect_ratio")) {
|
||||
std::string::size_type pos;
|
||||
pos = value.find_first_of(':');
|
||||
|
|
@ -340,20 +349,28 @@ TranscodeFfmpeg::encode (std::string outfile, std::string inf_a, std::string inf
|
|||
if (m_lead_in != 0 && m_lead_out != 0) {
|
||||
std::ostringstream osstream;
|
||||
argp[a++] = strdup("-vf");
|
||||
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_in << X_(" [pre]; ");
|
||||
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_out << X_(" [post]; ");
|
||||
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_in;
|
||||
if (!m_sar.empty()) osstream << X_(":sar=") << m_sar;
|
||||
osstream << X_(" [pre]; ");
|
||||
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_out;
|
||||
if (!m_sar.empty()) osstream << X_(":sar=") << m_sar;
|
||||
osstream << X_(" [post]; ");
|
||||
osstream << X_("[pre] [in] [post] concat=n=3");
|
||||
argp[a++] = strdup(osstream.str().c_str());
|
||||
} else if (m_lead_in != 0) {
|
||||
std::ostringstream osstream;
|
||||
argp[a++] = strdup("-vf");
|
||||
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_in << X_(" [pre]; ");
|
||||
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_in;
|
||||
if (!m_sar.empty()) osstream << X_(":sar=") << m_sar;
|
||||
osstream << X_(" [pre]; ");
|
||||
osstream << X_("[pre] [in] concat=n=2");
|
||||
argp[a++] = strdup(osstream.str().c_str());
|
||||
} else if (m_lead_out != 0) {
|
||||
std::ostringstream osstream;
|
||||
argp[a++] = strdup("-vf");
|
||||
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_out << X_(" [post]; ");
|
||||
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_out;
|
||||
if (!m_sar.empty()) osstream << X_(":sar=") << m_sar;
|
||||
osstream << X_(" [post]; ");
|
||||
osstream << X_("[in] [post] concat=n=2");
|
||||
argp[a++] = strdup(osstream.str().c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ class TranscodeFfmpeg : public sigc::trackable
|
|||
|
||||
double m_fps;
|
||||
double m_aspect;
|
||||
std::string m_sar;
|
||||
ARDOUR::framecnt_t m_duration;
|
||||
int m_width;
|
||||
int m_height;
|
||||
|
|
|
|||
|
|
@ -179,16 +179,18 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
|
|||
options_box->pack_start (*l, false, true, 4);
|
||||
|
||||
video_combo.set_name ("PaddedButton");
|
||||
video_combo.append_text(_("Do Not Import Video"));
|
||||
video_combo.append_text(_("Reference From Current Location"));
|
||||
video_combo.append_text(_("Reference From Current Location (Previously Transcoded Files Only)"));
|
||||
if (ffok) {
|
||||
video_combo.append_text(_("Import/Transcode Video to Session"));
|
||||
video_combo.set_active(2);
|
||||
} else {
|
||||
video_combo.set_active(1);
|
||||
} else {
|
||||
video_combo.set_active(0);
|
||||
video_combo.set_sensitive(false);
|
||||
audio_combo.set_sensitive(false);
|
||||
}
|
||||
if (as.size() > 0) {
|
||||
video_combo.append_text(_("Do Not Import Video (Audio Import Only)"));
|
||||
}
|
||||
|
||||
options_box->pack_start (video_combo, false, false, 4);
|
||||
|
||||
|
|
@ -227,8 +229,11 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
|
|||
t->attach (*l, 0, 1, 2, 3);
|
||||
audio_combo.set_name ("PaddedButton");
|
||||
t->attach (audio_combo, 1, 4, 2, 3);
|
||||
audio_combo.append_text("No audio");
|
||||
if (as.size() > 0) {
|
||||
if (as.size() == 0) {
|
||||
audio_combo.append_text(_("No Audio Track Present"));
|
||||
audio_combo.set_sensitive(false);
|
||||
} else {
|
||||
audio_combo.append_text(_("Do Not Extract Audio"));
|
||||
for (TranscodeFfmpeg::FFAudioStreams::iterator it = as.begin(); it < as.end(); ++it) {
|
||||
audio_combo.append_text((*it).name);
|
||||
}
|
||||
|
|
@ -366,7 +371,7 @@ TranscodeVideoDialog::dialog_progress_mode ()
|
|||
void
|
||||
TranscodeVideoDialog::launch_transcode ()
|
||||
{
|
||||
if (video_combo.get_active_row_number() != 2) {
|
||||
if (video_combo.get_active_row_number() != 1) {
|
||||
launch_audioonly();
|
||||
return;
|
||||
}
|
||||
|
|
@ -415,8 +420,8 @@ TranscodeVideoDialog::launch_transcode ()
|
|||
void
|
||||
TranscodeVideoDialog::video_combo_changed ()
|
||||
{
|
||||
int i = video_combo.get_active_row_number();
|
||||
if (i != 2) {
|
||||
const int i = video_combo.get_active_row_number();
|
||||
if (i != 1) {
|
||||
scale_combo.set_sensitive(false);
|
||||
aspect_checkbox.set_sensitive(false);
|
||||
height_spinner.set_sensitive(false);
|
||||
|
|
@ -429,12 +434,19 @@ TranscodeVideoDialog::video_combo_changed ()
|
|||
bitrate_checkbox.set_sensitive(true);
|
||||
bitrate_spinner.set_sensitive(true);
|
||||
}
|
||||
if (i == 2 && audio_combo.get_active_row_number() == 0) {
|
||||
audio_combo.set_active(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TranscodeVideoDialog::audio_combo_changed ()
|
||||
{
|
||||
;
|
||||
if (video_combo.get_active_row_number() == 2
|
||||
&& audio_combo.get_active_row_number() == 0)
|
||||
{
|
||||
audio_combo.set_active(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@
|
|||
#include "transcode_ffmpeg.h"
|
||||
|
||||
enum VtlTranscodeOption {
|
||||
VTL_IMPORT_NO_VIDEO = 0,
|
||||
VTL_IMPORT_REFERENCE = 1,
|
||||
VTL_IMPORT_TRANSCODED = 2
|
||||
VTL_IMPORT_REFERENCE = 0,
|
||||
VTL_IMPORT_TRANSCODED = 1,
|
||||
VTL_IMPORT_NO_VIDEO = 2
|
||||
};
|
||||
|
||||
/** @class TranscodeVideoDialog
|
||||
|
|
|
|||
|
|
@ -716,7 +716,7 @@ void
|
|||
VideoTimeLine::find_xjadeo () {
|
||||
std::string xjadeo_file_path;
|
||||
if (getenv("XJREMOTE")) {
|
||||
_xjadeo_bin = strdup(getenv("XJREMOTE")); // XXX TODO: free it?!
|
||||
_xjadeo_bin = getenv("XJREMOTE");
|
||||
} else if (find_file_in_search_path (Searchpath(Glib::getenv("PATH")), X_("xjremote"), xjadeo_file_path)) {
|
||||
_xjadeo_bin = xjadeo_file_path;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -377,7 +377,6 @@ def build(bld):
|
|||
# here using winegcc, and link it to the GTK front-end library
|
||||
obj = bld (features = 'cxx c cxxprogram wine')
|
||||
obj.source = (
|
||||
'../libs/fst/fst.c',
|
||||
'../libs/fst/vstwin.c',
|
||||
'../vst/winmain.c',
|
||||
)
|
||||
|
|
@ -398,7 +397,7 @@ def build(bld):
|
|||
obj.includes = [ '../libs/fst', '.' ]
|
||||
obj.linkflags = ['-mwindows', '-Wl,--export-dynamic']
|
||||
obj.defines = ['_POSIX_SOURCE', 'USE_WS_PREFIX']
|
||||
obj.install_path = os.path.join(bld.env['LIBDIR'], 'ardour3')
|
||||
obj.install_path = bld.env['DLLDIR']
|
||||
# end of the wine executable
|
||||
|
||||
# now the shared library containing the GTK GUI for ardour
|
||||
|
|
@ -439,7 +438,7 @@ def build(bld):
|
|||
'CONFIG_DIR="' + os.path.normpath(bld.env['SYSCONFDIR']) + '"',
|
||||
'LOCALEDIR="' + os.path.join(os.path.normpath(bld.env['DATADIR']), 'locale') + '"',
|
||||
]
|
||||
obj.install_path = os.path.join(bld.env['LIBDIR'], 'ardour3')
|
||||
obj.install_path = os.path.join(bld.env['DLLDIR'])
|
||||
obj.uselib = 'UUID FLAC FONTCONFIG GLIBMM GTHREAD GTK OGG CURL DL'
|
||||
obj.uselib += ' GTKMM CANVAS FFTW3F'
|
||||
obj.uselib += ' AUDIOUNITS OSX GTKOSX LO '
|
||||
|
|
@ -493,11 +492,15 @@ def build(bld):
|
|||
|
||||
# Wrappers
|
||||
|
||||
print 'DLL = ' + bld.env['DLLDIR'], '\n'
|
||||
print 'DATADIR = ' + bld.env['DATADIR'], '\n'
|
||||
print 'CONF = ' + bld.env['CONFDIR'], '\n'
|
||||
|
||||
wrapper_subst_dict = {
|
||||
'INSTALL_PREFIX' : bld.env['PREFIX'],
|
||||
'LIBDIR' : os.path.normpath(bld.env['LIBDIR']),
|
||||
'LIBDIR' : os.path.normpath(bld.env['DLLDIR']),
|
||||
'DATADIR' : os.path.normpath(bld.env['DATADIR']),
|
||||
'SYSCONFDIR' : os.path.normpath(bld.env['SYSCONFDIR']),
|
||||
'SYSCONFDIR' : os.path.normpath(bld.env['CONFDIR']),
|
||||
'LIBS' : 'build/libs',
|
||||
'VERSION' : bld.env['VERSION'],
|
||||
'EXECUTABLE' : 'build/gtk2_ardour/tracks'
|
||||
|
|
@ -662,14 +665,14 @@ def build(bld):
|
|||
# find and add all ##include dependencies as sources
|
||||
obj.source += _doPyp (bld.path.find_resource ('ardour3_ui_dark.rc.in').srcpath(), True)
|
||||
obj.target = 'ardour3_ui_dark.rc'
|
||||
obj.install_path = '${SYSCONFDIR}/ardour3'
|
||||
obj.install_path = bld.env['CONFDIR']
|
||||
|
||||
obj = bld (rule = include_processor)
|
||||
obj.source = [ 'ardour3_ui_light.rc.pre' ]
|
||||
# find and add all ##include dependencies as sources
|
||||
obj.source += _doPyp (bld.path.find_resource ('ardour3_ui_light.rc.in').srcpath(), True)
|
||||
obj.target = 'ardour3_ui_light.rc'
|
||||
obj.install_path = '${SYSCONFDIR}/ardour3'
|
||||
obj.install_path = bld.env['CONFDIR']
|
||||
|
||||
# Menus
|
||||
menus_argv = []
|
||||
|
|
@ -704,27 +707,24 @@ def build(bld):
|
|||
source = b + '.bindings.in',
|
||||
rule = a_rule
|
||||
)
|
||||
obj.install_path = os.path.join(bld.env['SYSCONFDIR'], 'ardour3')
|
||||
obj.install_path = os.path.join(bld.env['CONFDIR'])
|
||||
|
||||
# not modified at present
|
||||
bld.install_files(os.path.join(bld.env['SYSCONFDIR'], 'ardour3'),
|
||||
'step_editing.bindings')
|
||||
bld.install_files(os.path.join(bld.env['SYSCONFDIR'], 'ardour3'),
|
||||
'mixer.bindings')
|
||||
bld.install_files(bld.env['CONFDIR'], 'step_editing.bindings')
|
||||
bld.install_files(bld.env['CONFDIR'], 'mixer.bindings')
|
||||
|
||||
# Icons/Images
|
||||
bld.install_files('${DATADIR}/ardour3/icons', bld.path.ant_glob('icons/*.png'))
|
||||
bld.install_files('${DATADIR}/ardour3/pixmaps', bld.path.ant_glob('pixmaps/*.xpm'))
|
||||
bld.install_files('${DATADIR}/ardour3/ui', bld.path.ant_glob('ui/*.*'))
|
||||
bld.install_files('${DATADIR}/ardour3', 'splash.png')
|
||||
bld.install_files('${DATADIR}/ardour3', 'small-splash.png')
|
||||
bld.install_files('${DATADIR}/ardour3', 'ArdourMono.ttf')
|
||||
bld.install_files(os.path.join (bld.env['DATADIR'], 'icons'), bld.path.ant_glob('icons/*.png'))
|
||||
bld.install_files(os.path.join (bld.env['DATADIR'], 'pixmaps'), bld.path.ant_glob('pixmaps/*.xpm'))
|
||||
bld.install_files(bld.env['DATADIR'], 'splash.png')
|
||||
bld.install_files(bld.env['DATADIR'], 'small-splash.png')
|
||||
bld.install_files(bld.env['DATADIR'], 'ArdourMono.ttf')
|
||||
|
||||
# Default UI configuration
|
||||
bld.install_files('${SYSCONFDIR}/ardour3', 'ardour3_ui_default.conf')
|
||||
bld.install_files(bld.env['CONFDIR'], 'ardour3_ui_default.conf')
|
||||
|
||||
# Default export stuff
|
||||
bld.install_files('${SYSCONFDIR}/ardour3/export', bld.path.ant_glob('export/*.format'))
|
||||
bld.install_files(os.path.join(bld.env['CONFDIR'],' export'), bld.path.ant_glob('export/*.format'))
|
||||
|
||||
# i18n
|
||||
if bld.is_defined('ENABLE_NLS'):
|
||||
|
|
|
|||
|
|
@ -139,7 +139,6 @@ class LIBARDOUR_API AudioDiskstream : public Diskstream
|
|||
void set_block_size (pframes_t);
|
||||
int internal_playback_seek (framecnt_t distance);
|
||||
int can_internal_playback_seek (framecnt_t distance);
|
||||
std::list<boost::shared_ptr<Source> > steal_write_sources();
|
||||
void reset_write_sources (bool, bool force = false);
|
||||
void non_realtime_input_change ();
|
||||
void non_realtime_locate (framepos_t location);
|
||||
|
|
|
|||
|
|
@ -39,10 +39,6 @@ class LIBARDOUR_API AudioFileSource : public AudioSource, public FileSource {
|
|||
public:
|
||||
virtual ~AudioFileSource ();
|
||||
|
||||
bool set_name (const std::string& newname) {
|
||||
return (set_source_name(newname, destructive()) == 0);
|
||||
}
|
||||
|
||||
std::string peak_path (std::string audio_path);
|
||||
std::string find_broken_peakfile (std::string missing_peak_path,
|
||||
std::string audio_path);
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ class LIBARDOUR_API Diskstream : public SessionObject, public PublicDiskstream
|
|||
|
||||
virtual bool set_name (const std::string& str);
|
||||
|
||||
virtual std::string steal_write_source_name () { return std::string(); }
|
||||
|
||||
boost::shared_ptr<ARDOUR::IO> io() const { return _io; }
|
||||
void set_track (ARDOUR::Track *);
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class LIBARDOUR_API MissingSource : public std::exception
|
|||
/** A source associated with a file on disk somewhere */
|
||||
class LIBARDOUR_API FileSource : virtual public Source {
|
||||
public:
|
||||
virtual ~FileSource () {}
|
||||
virtual ~FileSource ();
|
||||
|
||||
virtual const std::string& path() const { return _path; }
|
||||
|
||||
|
|
@ -82,6 +82,9 @@ public:
|
|||
|
||||
static PBD::Signal2<int,std::string,std::vector<std::string> > AmbiguousFileName;
|
||||
|
||||
void existence_check ();
|
||||
virtual void prevent_deletion ();
|
||||
|
||||
protected:
|
||||
FileSource (Session& session, DataType type,
|
||||
const std::string& path,
|
||||
|
|
@ -103,7 +106,6 @@ protected:
|
|||
std::string _origin;
|
||||
bool _open;
|
||||
|
||||
void prevent_deletion ();
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ class LIBARDOUR_API MidiDiskstream : public Diskstream
|
|||
void set_block_size (pframes_t);
|
||||
int internal_playback_seek (framecnt_t distance);
|
||||
int can_internal_playback_seek (framecnt_t distance);
|
||||
std::list<boost::shared_ptr<Source> > steal_write_sources();
|
||||
std::string steal_write_source_name();
|
||||
void reset_write_sources (bool, bool force = false);
|
||||
void non_realtime_input_change ();
|
||||
void non_realtime_locate (framepos_t location);
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ class LIBARDOUR_API MidiRegion : public Region
|
|||
~MidiRegion();
|
||||
|
||||
boost::shared_ptr<MidiRegion> clone (std::string path = std::string()) const;
|
||||
boost::shared_ptr<MidiRegion> clone (boost::shared_ptr<MidiSource>) const;
|
||||
|
||||
boost::shared_ptr<MidiSource> midi_source (uint32_t n=0) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,19 @@ class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_sha
|
|||
MidiSource (Session& session, const XMLNode&);
|
||||
virtual ~MidiSource ();
|
||||
|
||||
boost::shared_ptr<MidiSource> clone (const std::string& path,
|
||||
/** Write the data in the given time range to another MidiSource
|
||||
* \param newsrc MidiSource to which data will be written. Should be a
|
||||
* new, empty source. If it already has contents, the results are
|
||||
* undefined. Source must be writable.
|
||||
*
|
||||
* \param begin time of earliest event that can be written.
|
||||
* \param end time of latest event that can be written.
|
||||
*
|
||||
* Returns zero on success, non-zero if the write failed for any
|
||||
* reason.
|
||||
*
|
||||
*/
|
||||
int write_to (boost::shared_ptr<MidiSource> newsrc,
|
||||
Evoral::MusicalTime begin = Evoral::MinMusicalTime,
|
||||
Evoral::MusicalTime end = Evoral::MaxMusicalTime);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public:
|
|||
virtual bool destructive () const = 0;
|
||||
virtual std::list<boost::shared_ptr<Source> > & last_capture_sources () = 0;
|
||||
virtual void set_capture_offset () = 0;
|
||||
virtual std::list<boost::shared_ptr<Source> > steal_write_sources () = 0;
|
||||
virtual std::string steal_write_source_name () = 0;
|
||||
virtual void reset_write_sources (bool, bool force = false) = 0;
|
||||
virtual float playback_buffer_load () const = 0;
|
||||
virtual float capture_buffer_load () const = 0;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ CONFIG_VARIABLE (bool, midi_feedback, "midi-feedback", false)
|
|||
CONFIG_VARIABLE (int32_t, mmc_receive_device_id, "mmc-receive-device-id", 0x7f)
|
||||
CONFIG_VARIABLE (int32_t, mmc_send_device_id, "mmc-send-device-id", 0)
|
||||
CONFIG_VARIABLE (int32_t, initial_program_change, "initial-program-change", -1)
|
||||
CONFIG_VARIABLE (bool, first_midi_bank_is_zero, "diplay-first-midi-bank-as-zero", false)
|
||||
CONFIG_VARIABLE (bool, first_midi_bank_is_zero, "display-first-midi-bank-as-zero", false)
|
||||
|
||||
/* Timecode and related */
|
||||
|
||||
|
|
@ -227,6 +227,7 @@ CONFIG_VARIABLE (bool, use_tooltips, "use-tooltips", true)
|
|||
CONFIG_VARIABLE (std::string, mixer_strip_visibility, "mixer-strip-visibility", "PhaseInvert,SoloSafe,SoloIsolated,Group,MeterPoint")
|
||||
CONFIG_VARIABLE (bool, allow_non_quarter_pulse, "allow-non-quarter-pulse", false)
|
||||
CONFIG_VARIABLE (bool, show_region_gain, "show-region-gain", false)
|
||||
CONFIG_VARIABLE (bool, show_name_highlight, "show-name-highlight", false)
|
||||
|
||||
/* web addresses used in the program */
|
||||
|
||||
|
|
|
|||
|
|
@ -194,8 +194,6 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
|
|||
|
||||
std::string peak_path (std::string) const;
|
||||
|
||||
std::string change_source_path_by_name (std::string oldpath, std::string oldname, std::string newname, bool destructive);
|
||||
|
||||
std::string peak_path_from_audio_path (std::string) const;
|
||||
std::string new_audio_source_name (const std::string&, uint32_t nchans, uint32_t chan, bool destructive);
|
||||
std::string new_midi_source_name (const std::string&);
|
||||
|
|
@ -582,11 +580,12 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
|
|||
boost::shared_ptr<AudioFileSource> create_audio_source_for_session (
|
||||
size_t, std::string const &, uint32_t, bool destructive);
|
||||
|
||||
boost::shared_ptr<MidiSource> create_midi_source_for_session (
|
||||
Track*, std::string const &);
|
||||
boost::shared_ptr<MidiSource> create_midi_source_for_session (std::string const &);
|
||||
boost::shared_ptr<MidiSource> create_midi_source_by_stealing_name (boost::shared_ptr<Track>);
|
||||
|
||||
boost::shared_ptr<Source> source_by_id (const PBD::ID&);
|
||||
boost::shared_ptr<Source> source_by_path_and_channel (const std::string&, uint16_t);
|
||||
boost::shared_ptr<AudioFileSource> source_by_path_and_channel (const std::string&, uint16_t) const;
|
||||
boost::shared_ptr<MidiSource> source_by_path (const std::string&) const;
|
||||
uint32_t count_sources_by_origin (const std::string&);
|
||||
|
||||
void add_playlist (boost::shared_ptr<Playlist>, bool unused = false);
|
||||
|
|
|
|||
|
|
@ -45,12 +45,19 @@ public:
|
|||
|
||||
virtual ~SMFSource ();
|
||||
|
||||
/** Rename the file on disk referenced by this source to \param newname
|
||||
*
|
||||
* This method exists only for MIDI file sources, not for audio, which
|
||||
* can never be renamed. It exists for MIDI so that we can get
|
||||
* consistent and sane region/source numbering when regions are added
|
||||
* manually (which never happens with audio).
|
||||
*/
|
||||
int rename (const std::string& name);
|
||||
|
||||
bool safe_file_extension (const std::string& path) const {
|
||||
return safe_midi_file_extension(path);
|
||||
}
|
||||
|
||||
bool set_name (const std::string& newname) { return (set_source_name(newname, false) == 0); }
|
||||
|
||||
void append_event_unlocked_beats (const Evoral::Event<Evoral::MusicalTime>& ev);
|
||||
void append_event_unlocked_frames (const Evoral::Event<framepos_t>& ev, framepos_t source_start);
|
||||
|
||||
|
|
@ -69,6 +76,8 @@ public:
|
|||
|
||||
static bool safe_midi_file_extension (const std::string& path);
|
||||
|
||||
void prevent_deletion ();
|
||||
|
||||
protected:
|
||||
void set_path (const std::string& newpath);
|
||||
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ class LIBARDOUR_API Track : public Route, public PublicDiskstream
|
|||
bool destructive () const;
|
||||
std::list<boost::shared_ptr<Source> > & last_capture_sources ();
|
||||
void set_capture_offset ();
|
||||
std::list<boost::shared_ptr<Source> > steal_write_sources();
|
||||
std::string steal_write_source_name ();
|
||||
void reset_write_sources (bool, bool force = false);
|
||||
float playback_buffer_load () const;
|
||||
float capture_buffer_load () const;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ struct LIBARDOUR_API _VSTHandle
|
|||
{
|
||||
void* dll;
|
||||
char* name;
|
||||
char* nameptr;
|
||||
char* path;
|
||||
|
||||
main_entry_t main_entry;
|
||||
|
|
|
|||
|
|
@ -1926,14 +1926,6 @@ AudioDiskstream::use_new_write_source (uint32_t n)
|
|||
return 0;
|
||||
}
|
||||
|
||||
list<boost::shared_ptr<Source> >
|
||||
AudioDiskstream::steal_write_sources()
|
||||
{
|
||||
/* not possible to steal audio write sources */
|
||||
list<boost::shared_ptr<Source> > ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
AudioDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -105,15 +105,15 @@ AudioLibrary::get_tags (string member)
|
|||
{
|
||||
vector<string> tags;
|
||||
#ifdef HAVE_LRDF
|
||||
char * uri = strdup(Glib::filename_to_uri(member).c_str());
|
||||
|
||||
lrdf_statement pattern;
|
||||
pattern.subject = strdup(Glib::filename_to_uri(member).c_str());
|
||||
pattern.subject = uri;
|
||||
pattern.predicate = const_cast<char*>(TAG);
|
||||
pattern.object = 0;
|
||||
pattern.object_type = lrdf_literal;
|
||||
|
||||
lrdf_statement* matches = lrdf_matches (&pattern);
|
||||
free (pattern.subject);
|
||||
|
||||
lrdf_statement* current = matches;
|
||||
while (current != 0) {
|
||||
|
|
@ -125,6 +125,7 @@ AudioLibrary::get_tags (string member)
|
|||
lrdf_free_statements (matches);
|
||||
|
||||
sort (tags.begin(), tags.end());
|
||||
free (uri);
|
||||
#endif
|
||||
return tags;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ framecnt_t
|
|||
AudioSource::write (Sample *dst, framecnt_t cnt)
|
||||
{
|
||||
Glib::Threads::Mutex::Lock lm (_lock);
|
||||
/* any write makes the fill not removable */
|
||||
/* any write makes the file not removable */
|
||||
_flags = Flag (_flags & ~Removable);
|
||||
return write_unlocked (dst, cnt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,9 +245,32 @@ ControlProtocolManager::discover_control_protocols ()
|
|||
{
|
||||
vector<std::string> cp_modules;
|
||||
|
||||
#ifdef COMPILER_MSVC
|
||||
/**
|
||||
* Different build targets (Debug / Release etc) use different versions
|
||||
* of the 'C' runtime (which can't be 'mixed & matched'). Therefore, in
|
||||
* case the supplied search path contains multiple version(s) of a given
|
||||
* module, only select the one(s) which match the current build target
|
||||
*/
|
||||
#if defined (_DEBUG)
|
||||
Glib::PatternSpec dll_extension_pattern("*D.dll");
|
||||
#elif defined (RDC_BUILD)
|
||||
Glib::PatternSpec dll_extension_pattern("*RDC.dll");
|
||||
#elif defined (_WIN64)
|
||||
Glib::PatternSpec dll_extension_pattern("*64.dll");
|
||||
#else
|
||||
Glib::PatternSpec dll_extension_pattern("*32.dll");
|
||||
#endif
|
||||
#else
|
||||
Glib::PatternSpec dll_extension_pattern("*.dll");
|
||||
#endif
|
||||
|
||||
Glib::PatternSpec so_extension_pattern("*.so");
|
||||
Glib::PatternSpec dylib_extension_pattern("*.dylib");
|
||||
|
||||
find_matching_files_in_search_path (control_protocol_search_path (),
|
||||
dll_extension_pattern, cp_modules);
|
||||
|
||||
find_matching_files_in_search_path (control_protocol_search_path (),
|
||||
so_extension_pattern, cp_modules);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include <appleutility/CAAudioFile.h>
|
||||
#include <appleutility/CAStreamBasicDescription.h>
|
||||
|
||||
#include <glibmm/fileutils.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
#include <AudioToolbox/AudioFormat.h>
|
||||
|
|
@ -36,21 +38,32 @@ using namespace std;
|
|||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
/** Create a new CoreAudioSource using session state, which implies that the
|
||||
* file must already exist.
|
||||
*/
|
||||
CoreAudioSource::CoreAudioSource (Session& s, const XMLNode& node)
|
||||
: Source (s, node)
|
||||
, AudioFileSource (s, node)
|
||||
{
|
||||
init_cafile ();
|
||||
|
||||
assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
|
||||
existence_check ();
|
||||
}
|
||||
|
||||
/** Create a new CoreAudioSource from an existing file. Sources created with this
|
||||
* method are never writable or removable.
|
||||
*/
|
||||
CoreAudioSource::CoreAudioSource (Session& s, const string& path, int chn, Flag flags)
|
||||
/* files created this way are never writable or removable */
|
||||
: Source (s, DataType::AUDIO, path, Source::Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy))),
|
||||
AudioFileSource (s, path,
|
||||
Source::Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
|
||||
{
|
||||
_channel = chn;
|
||||
init_cafile ();
|
||||
|
||||
assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
|
||||
existence_check ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -62,8 +62,6 @@ FileSource::FileSource (Session& session, DataType type, const string& path, con
|
|||
, _open (false)
|
||||
{
|
||||
set_within_session_from_path (path);
|
||||
|
||||
prevent_deletion ();
|
||||
}
|
||||
|
||||
FileSource::FileSource (Session& session, const XMLNode& node, bool /*must_exist*/)
|
||||
|
|
@ -77,24 +75,29 @@ FileSource::FileSource (Session& session, const XMLNode& node, bool /*must_exist
|
|||
|
||||
_path = _name;
|
||||
_within_session = true;
|
||||
}
|
||||
|
||||
FileSource::~FileSource()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
FileSource::existence_check ()
|
||||
{
|
||||
if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS)) {
|
||||
prevent_deletion ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileSource::prevent_deletion ()
|
||||
{
|
||||
/* if this file already exists, it cannot be removed, ever
|
||||
*/
|
||||
|
||||
if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS)) {
|
||||
if (!(_flags & Destructive)) {
|
||||
mark_immutable ();
|
||||
} else {
|
||||
_flags = Flag (_flags & ~(Removable|RemovableIfEmpty|RemoveAtDestroy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
FileSource::removable () const
|
||||
|
|
@ -509,35 +512,6 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
FileSource::set_source_name (const string& newname, bool destructive)
|
||||
{
|
||||
Glib::Threads::Mutex::Lock lm (_lock);
|
||||
string oldpath = _path;
|
||||
string newpath = _session.change_source_path_by_name (oldpath, _name, newname, destructive);
|
||||
|
||||
if (newpath.empty()) {
|
||||
error << string_compose (_("programming error: %1"), "cannot generate a changed file path") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Test whether newpath exists, if yes notify the user but continue.
|
||||
if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
|
||||
error << string_compose (_("Programming error! %1 tried to rename a file over another file! It's safe to continue working, but please report this to the developers."), PROGRAM_NAME) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (::rename (oldpath.c_str(), newpath.c_str()) != 0) {
|
||||
error << string_compose (_("cannot rename file %1 to %2 (%3)"), oldpath, newpath, strerror(errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_name = Glib::path_get_basename (newpath);
|
||||
_path = newpath;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
FileSource::mark_immutable ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ vstfx_new ()
|
|||
void* vstfx_load_vst_library(const char* path)
|
||||
{
|
||||
void* dll;
|
||||
char* full_path;
|
||||
char* full_path = NULL;
|
||||
char* envdup;
|
||||
char* lxvst_path;
|
||||
size_t len1;
|
||||
|
|
@ -160,6 +160,7 @@ void* vstfx_load_vst_library(const char* path)
|
|||
vstfx_error ("\"%s\"", lxvst_path);
|
||||
len1 = strlen(lxvst_path);
|
||||
|
||||
if (full_path) free(full_path);
|
||||
full_path = (char*)malloc(len1 + 1 + len2 + 1);
|
||||
memcpy(full_path, lxvst_path, len1);
|
||||
full_path[len1] = '/';
|
||||
|
|
@ -180,7 +181,7 @@ void* vstfx_load_vst_library(const char* path)
|
|||
}
|
||||
|
||||
/*Free the path*/
|
||||
|
||||
if (full_path) free(full_path);
|
||||
free(envdup);
|
||||
|
||||
return dll;
|
||||
|
|
@ -210,16 +211,12 @@ vstfx_load (const char *path)
|
|||
|
||||
sprintf (buf, "%s.so", path);
|
||||
|
||||
fhandle->nameptr = strdup (path);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/*We already have .so appened to the filename*/
|
||||
|
||||
buf = strdup(path);
|
||||
|
||||
fhandle->nameptr = strdup (path);
|
||||
}
|
||||
|
||||
/* get a name for the plugin based on the path: ye old VST problem where
|
||||
|
|
@ -227,7 +224,7 @@ vstfx_load (const char *path)
|
|||
which we don't want to do at this point
|
||||
*/
|
||||
|
||||
fhandle->name = strdup (PBD::basename_nosuffix (fhandle->nameptr).c_str());
|
||||
fhandle->name = strdup (PBD::basename_nosuffix (path).c_str());
|
||||
|
||||
/*call load_vstfx_library to actually load the .so into memory*/
|
||||
|
||||
|
|
@ -289,9 +286,8 @@ vstfx_unload (VSTHandle* fhandle)
|
|||
fhandle->dll = 0;
|
||||
}
|
||||
|
||||
if (fhandle->nameptr)
|
||||
if (fhandle->name)
|
||||
{
|
||||
free (fhandle->nameptr);
|
||||
free (fhandle->name);
|
||||
}
|
||||
|
||||
|
|
@ -311,6 +307,7 @@ vstfx_instantiate (VSTHandle* fhandle, audioMasterCallback amc, void* userptr)
|
|||
if(fhandle == 0)
|
||||
{
|
||||
vstfx_error( "** ERROR ** VSTFX : The handle was 0\n" );
|
||||
free (vstfx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@
|
|||
#include <cstring>
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
#include <giomm/file.h>
|
||||
#include <glib/gprintf.h>
|
||||
#include <glibmm.h>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include "pbd/clear_dir.h"
|
||||
#include "pbd/pathscanner.h"
|
||||
#include "pbd/compose.h"
|
||||
#include "pbd/error.h"
|
||||
|
|
@ -881,27 +881,6 @@ LV2Plugin::lv2_state_make_path(LV2_State_Make_Path_Handle handle,
|
|||
return g_strndup(abs_path.c_str(), abs_path.length());
|
||||
}
|
||||
|
||||
static void
|
||||
remove_directory(const std::string& path)
|
||||
{
|
||||
if (!Glib::file_test(path, Glib::FILE_TEST_IS_DIR)) {
|
||||
warning << string_compose("\"%1\" is not a directory", path) << endmsg;
|
||||
return;
|
||||
}
|
||||
|
||||
Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path(path);
|
||||
Glib::RefPtr<Gio::FileEnumerator> e = dir->enumerate_children();
|
||||
Glib::RefPtr<Gio::FileInfo> fi;
|
||||
while ((fi = e->next_file())) {
|
||||
if (fi->get_type() == Gio::FILE_TYPE_DIRECTORY) {
|
||||
remove_directory(fi->get_name());
|
||||
} else {
|
||||
dir->get_child(fi->get_name())->remove();
|
||||
}
|
||||
}
|
||||
dir->remove();
|
||||
}
|
||||
|
||||
void
|
||||
LV2Plugin::add_state(XMLNode* root) const
|
||||
{
|
||||
|
|
@ -953,7 +932,7 @@ LV2Plugin::add_state(XMLNode* root) const
|
|||
} else {
|
||||
// State is identical, decrement version and nuke directory
|
||||
lilv_state_free(state);
|
||||
remove_directory(new_dir);
|
||||
PBD::remove_directory(new_dir);
|
||||
--_state_version;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1198,7 +1198,7 @@ MidiDiskstream::use_new_write_source (uint32_t n)
|
|||
|
||||
try {
|
||||
_write_source = boost::dynamic_pointer_cast<SMFSource>(
|
||||
_session.create_midi_source_for_session (0, name ()));
|
||||
_session.create_midi_source_for_session (name ()));
|
||||
|
||||
if (!_write_source) {
|
||||
throw failed_constructor();
|
||||
|
|
@ -1213,25 +1213,36 @@ MidiDiskstream::use_new_write_source (uint32_t n)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
list<boost::shared_ptr<Source> >
|
||||
MidiDiskstream::steal_write_sources()
|
||||
/**
|
||||
* We want to use the name of the existing write source (the one that will be
|
||||
* used by the next capture) for another purpose. So change the name of the
|
||||
* current source, and return its current name.
|
||||
*
|
||||
* Return an empty string if the change cannot be accomplished.
|
||||
*/
|
||||
std::string
|
||||
MidiDiskstream::steal_write_source_name ()
|
||||
{
|
||||
list<boost::shared_ptr<Source> > ret;
|
||||
string our_old_name = _write_source->name();
|
||||
|
||||
/* put some data on the disk, even if its just a header for an empty file */
|
||||
boost::dynamic_pointer_cast<SMFSource> (_write_source)->ensure_disk_file ();
|
||||
/* this will bump the name of the current write source to the next one
|
||||
* (e.g. "MIDI 1-1" gets renamed to "MIDI 1-2"), thus leaving the
|
||||
* current write source name (e.g. "MIDI 1-1" available). See the
|
||||
* comments in Session::create_midi_source_by_stealing_name() about why
|
||||
* we do this.
|
||||
*/
|
||||
|
||||
/* never let it go away */
|
||||
_write_source->mark_nonremovable ();
|
||||
try {
|
||||
string new_name = _session.new_midi_source_name (name());
|
||||
|
||||
ret.push_back (_write_source);
|
||||
if (_write_source->rename (new_name)) {
|
||||
return string();
|
||||
}
|
||||
} catch (...) {
|
||||
return string ();
|
||||
}
|
||||
|
||||
/* get a new one */
|
||||
|
||||
use_new_write_source (0);
|
||||
|
||||
return ret;
|
||||
return our_old_name;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1252,7 +1252,7 @@ MidiModel::PatchChangePtr
|
|||
MidiModel::PatchChangeDiffCommand::unmarshal_patch_change (XMLNode* n)
|
||||
{
|
||||
XMLProperty* prop;
|
||||
Evoral::event_id_t id;
|
||||
Evoral::event_id_t id = 0;
|
||||
Evoral::MusicalTime time = 0;
|
||||
int channel = 0;
|
||||
int program = 0;
|
||||
|
|
@ -1284,6 +1284,7 @@ MidiModel::PatchChangeDiffCommand::unmarshal_patch_change (XMLNode* n)
|
|||
}
|
||||
|
||||
PatchChangePtr p (new Evoral::PatchChange<TimeType> (time, channel, program, bank));
|
||||
assert(id);
|
||||
p->set_id (id);
|
||||
return p;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#include <set>
|
||||
|
||||
#include <glibmm/threads.h>
|
||||
#include <glibmm/fileutils.h>
|
||||
#include <glibmm/miscutils.h>
|
||||
|
||||
#include "pbd/xml++.h"
|
||||
#include "pbd/basename.h"
|
||||
|
|
@ -36,6 +38,7 @@
|
|||
#include "ardour/midi_source.h"
|
||||
#include "ardour/region_factory.h"
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/source_factory.h"
|
||||
#include "ardour/tempo.h"
|
||||
#include "ardour/types.h"
|
||||
|
||||
|
|
@ -126,16 +129,31 @@ MidiRegion::~MidiRegion ()
|
|||
*/
|
||||
boost::shared_ptr<MidiRegion>
|
||||
MidiRegion::clone (string path) const
|
||||
{
|
||||
boost::shared_ptr<MidiSource> newsrc;
|
||||
|
||||
/* caller must check for pre-existing file */
|
||||
assert (!Glib::file_test (path, Glib::FILE_TEST_EXISTS));
|
||||
newsrc = boost::dynamic_pointer_cast<MidiSource>(
|
||||
SourceFactory::createWritable(DataType::MIDI, _session,
|
||||
path, false, _session.frame_rate()));
|
||||
return clone (newsrc);
|
||||
}
|
||||
|
||||
boost::shared_ptr<MidiRegion>
|
||||
MidiRegion::clone (boost::shared_ptr<MidiSource> newsrc) const
|
||||
{
|
||||
BeatsFramesConverter bfc (_session.tempo_map(), _position);
|
||||
Evoral::MusicalTime const bbegin = bfc.from (_start);
|
||||
Evoral::MusicalTime const bend = bfc.from (_start + _length);
|
||||
|
||||
boost::shared_ptr<MidiSource> ms = midi_source(0)->clone (path, bbegin, bend);
|
||||
if (midi_source(0)->write_to (newsrc, bbegin, bend)) {
|
||||
return boost::shared_ptr<MidiRegion> ();
|
||||
}
|
||||
|
||||
PropertyList plist;
|
||||
|
||||
plist.add (Properties::name, PBD::basename_nosuffix (ms->name()));
|
||||
plist.add (Properties::name, PBD::basename_nosuffix (newsrc->name()));
|
||||
plist.add (Properties::whole_file, true);
|
||||
plist.add (Properties::start, _start);
|
||||
plist.add (Properties::start_beats, _start_beats);
|
||||
|
|
@ -143,7 +161,7 @@ MidiRegion::clone (string path) const
|
|||
plist.add (Properties::length_beats, _length_beats);
|
||||
plist.add (Properties::layer, 0);
|
||||
|
||||
return boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (ms, plist, true));
|
||||
return boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (newsrc, plist, true));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "ardour/midi_model.h"
|
||||
#include "ardour/midi_state_tracker.h"
|
||||
#include "ardour/midi_source.h"
|
||||
#include "ardour/file_source.h"
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/session_directory.h"
|
||||
#include "ardour/source_factory.h"
|
||||
|
|
@ -331,31 +332,9 @@ MidiSource::mark_streaming_write_completed ()
|
|||
mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::DeleteStuckNotes);
|
||||
}
|
||||
|
||||
boost::shared_ptr<MidiSource>
|
||||
MidiSource::clone (const string& path, Evoral::MusicalTime begin, Evoral::MusicalTime end)
|
||||
int
|
||||
MidiSource::write_to (boost::shared_ptr<MidiSource> newsrc, Evoral::MusicalTime begin, Evoral::MusicalTime end)
|
||||
{
|
||||
string newname = PBD::basename_nosuffix(_name.val());
|
||||
string newpath;
|
||||
|
||||
if (path.empty()) {
|
||||
|
||||
/* get a new name for the MIDI file we're going to write to
|
||||
*/
|
||||
|
||||
do {
|
||||
newname = bump_name_once (newname, '-');
|
||||
newpath = Glib::build_filename (_session.session_directory().midi_path(), newname + ".mid");
|
||||
|
||||
} while (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS));
|
||||
} else {
|
||||
/* caller must check for pre-existing file */
|
||||
newpath = path;
|
||||
}
|
||||
|
||||
boost::shared_ptr<MidiSource> newsrc = boost::dynamic_pointer_cast<MidiSource>(
|
||||
SourceFactory::createWritable(DataType::MIDI, _session,
|
||||
newpath, false, _session.frame_rate()));
|
||||
|
||||
newsrc->set_timeline_position(_timeline_position);
|
||||
newsrc->copy_interpolation_from (this);
|
||||
newsrc->copy_automation_state_from (this);
|
||||
|
|
@ -368,7 +347,7 @@ MidiSource::clone (const string& path, Evoral::MusicalTime begin, Evoral::Musica
|
|||
}
|
||||
} else {
|
||||
error << string_compose (_("programming error: %1"), X_("no model for MidiSource during ::clone()"));
|
||||
return boost::shared_ptr<MidiSource>();
|
||||
return -1;
|
||||
}
|
||||
|
||||
newsrc->flush_midi();
|
||||
|
|
@ -381,7 +360,11 @@ MidiSource::clone (const string& path, Evoral::MusicalTime begin, Evoral::Musica
|
|||
newsrc->set_model (_model);
|
||||
}
|
||||
|
||||
return newsrc;
|
||||
/* this file is not removable (but since it is MIDI, it is mutable) */
|
||||
|
||||
boost::dynamic_pointer_cast<FileSource> (newsrc)->prevent_deletion ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -116,10 +116,9 @@ PluginManager::PluginManager ()
|
|||
char* s;
|
||||
string lrdf_path;
|
||||
|
||||
if (!PBD::find_file_in_search_path (
|
||||
PBD::Searchpath(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst")),
|
||||
"ardour-vst-scanner", scanner_bin_path)) {
|
||||
PBD::warning << "VST scanner app not found.'" << endmsg;
|
||||
string scan_p = Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst");
|
||||
if (!PBD::find_file_in_search_path ( PBD::Searchpath(scan_p), "ardour-vst-scanner", scanner_bin_path)) {
|
||||
PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << scan_p << endmsg;
|
||||
}
|
||||
|
||||
load_statuses ();
|
||||
|
|
|
|||
|
|
@ -3911,7 +3911,7 @@ Route::setup_invisible_processors ()
|
|||
++amp;
|
||||
}
|
||||
|
||||
assert (amp != _processors.end ());
|
||||
assert (amp != new_processors.end ());
|
||||
|
||||
/* and the processor after the amp */
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@
|
|||
#include "ardour/smf_source.h"
|
||||
#include "ardour/source_factory.h"
|
||||
#include "ardour/speakers.h"
|
||||
#include "ardour/track.h"
|
||||
#include "ardour/utils.h"
|
||||
|
||||
#include "midi++/port.h"
|
||||
|
|
@ -3525,12 +3526,16 @@ Session::source_by_id (const PBD::ID& id)
|
|||
return source;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Source>
|
||||
Session::source_by_path_and_channel (const string& path, uint16_t chn)
|
||||
boost::shared_ptr<AudioFileSource>
|
||||
Session::source_by_path_and_channel (const string& path, uint16_t chn) const
|
||||
{
|
||||
/* Restricted to audio files because only audio sources have channel
|
||||
as a property.
|
||||
*/
|
||||
|
||||
Glib::Threads::Mutex::Lock lm (source_lock);
|
||||
|
||||
for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
|
||||
for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
|
||||
boost::shared_ptr<AudioFileSource> afs
|
||||
= boost::dynamic_pointer_cast<AudioFileSource>(i->second);
|
||||
|
||||
|
|
@ -3538,7 +3543,31 @@ Session::source_by_path_and_channel (const string& path, uint16_t chn)
|
|||
return afs;
|
||||
}
|
||||
}
|
||||
return boost::shared_ptr<Source>();
|
||||
|
||||
return boost::shared_ptr<AudioFileSource>();
|
||||
}
|
||||
|
||||
boost::shared_ptr<MidiSource>
|
||||
Session::source_by_path (const std::string& path) const
|
||||
{
|
||||
/* Restricted to MIDI files because audio sources require a channel
|
||||
for unique identification, in addition to a path.
|
||||
*/
|
||||
|
||||
Glib::Threads::Mutex::Lock lm (source_lock);
|
||||
|
||||
for (SourceMap::const_iterator s = sources.begin(); s != sources.end(); ++s) {
|
||||
boost::shared_ptr<MidiSource> ms
|
||||
= boost::dynamic_pointer_cast<MidiSource>(s->second);
|
||||
boost::shared_ptr<FileSource> fs
|
||||
= boost::dynamic_pointer_cast<FileSource>(s->second);
|
||||
|
||||
if (ms && fs && fs->path() == path) {
|
||||
return ms;
|
||||
}
|
||||
}
|
||||
|
||||
return boost::shared_ptr<MidiSource>();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
|
@ -3559,111 +3588,6 @@ Session::count_sources_by_origin (const string& path)
|
|||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
string
|
||||
Session::change_source_path_by_name (string path, string oldname, string newname, bool destructive)
|
||||
{
|
||||
string look_for;
|
||||
string old_basename = PBD::basename_nosuffix (oldname);
|
||||
string new_legalized = legalize_for_path (newname);
|
||||
|
||||
/* note: we know (or assume) the old path is already valid */
|
||||
|
||||
if (destructive) {
|
||||
|
||||
/* destructive file sources have a name of the form:
|
||||
|
||||
/path/to/Tnnnn-NAME(%[LR])?.wav
|
||||
|
||||
the task here is to replace NAME with the new name.
|
||||
*/
|
||||
|
||||
string dir;
|
||||
string prefix;
|
||||
string::size_type dash;
|
||||
|
||||
dir = Glib::path_get_dirname (path);
|
||||
path = Glib::path_get_basename (path);
|
||||
|
||||
/* '-' is not a legal character for the NAME part of the path */
|
||||
|
||||
if ((dash = path.find_last_of ('-')) == string::npos) {
|
||||
return "";
|
||||
}
|
||||
|
||||
prefix = path.substr (0, dash);
|
||||
|
||||
path += prefix;
|
||||
path += '-';
|
||||
path += new_legalized;
|
||||
path += native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
|
||||
path = Glib::build_filename (dir, path);
|
||||
|
||||
} else {
|
||||
|
||||
/* non-destructive file sources have a name of the form:
|
||||
|
||||
/path/to/NAME-nnnnn(%[LR])?.ext
|
||||
|
||||
the task here is to replace NAME with the new name.
|
||||
*/
|
||||
|
||||
string dir;
|
||||
string suffix;
|
||||
string::size_type dash;
|
||||
string::size_type postfix;
|
||||
|
||||
dir = Glib::path_get_dirname (path);
|
||||
path = Glib::path_get_basename (path);
|
||||
|
||||
/* '-' is not a legal character for the NAME part of the path */
|
||||
|
||||
if ((dash = path.find_last_of ('-')) == string::npos) {
|
||||
return "";
|
||||
}
|
||||
|
||||
suffix = path.substr (dash+1);
|
||||
|
||||
// Suffix is now everything after the dash. Now we need to eliminate
|
||||
// the nnnnn part, which is done by either finding a '%' or a '.'
|
||||
|
||||
postfix = suffix.find_last_of ("%");
|
||||
if (postfix == string::npos) {
|
||||
postfix = suffix.find_last_of ('.');
|
||||
}
|
||||
|
||||
if (postfix != string::npos) {
|
||||
suffix = suffix.substr (postfix);
|
||||
} else {
|
||||
error << "Logic error in Session::change_source_path_by_name(), please report" << endl;
|
||||
return "";
|
||||
}
|
||||
|
||||
const uint32_t limit = 10000;
|
||||
char buf[PATH_MAX+1];
|
||||
|
||||
for (uint32_t cnt = 1; cnt <= limit; ++cnt) {
|
||||
|
||||
snprintf (buf, sizeof(buf), "%s-%u%s", newname.c_str(), cnt, suffix.c_str());
|
||||
|
||||
if (!matching_unsuffixed_filename_exists_in (dir, buf)) {
|
||||
path = Glib::build_filename (dir, buf);
|
||||
break;
|
||||
}
|
||||
|
||||
path = "";
|
||||
}
|
||||
|
||||
if (path.empty()) {
|
||||
fatal << string_compose (_("FATAL ERROR! Could not find a suitable version of %1 for a rename"),
|
||||
newname) << endl;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/** Return the full path (in some session directory) for a new within-session source.
|
||||
* \a name must be a session-unique name that does not contain slashes
|
||||
* (e.g. as returned by new_*_source_name)
|
||||
|
|
@ -3767,6 +3691,22 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha
|
|||
existing++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* it is possible that we have the path already
|
||||
* assigned to a source that has not yet been written
|
||||
* (ie. the write source for a diskstream). we have to
|
||||
* check this in order to make sure that our candidate
|
||||
* path isn't used again, because that can lead to
|
||||
* two Sources point to the same file with different
|
||||
* notions of their removability.
|
||||
*/
|
||||
|
||||
string possible_path = Glib::build_filename (spath, buf);
|
||||
|
||||
if (source_by_path (possible_path)) {
|
||||
existing++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (existing == 0) {
|
||||
|
|
@ -3796,19 +3736,21 @@ Session::create_audio_source_for_session (size_t n_chans, string const & n, uint
|
|||
SourceFactory::createWritable (DataType::AUDIO, *this, path, destructive, frame_rate()));
|
||||
}
|
||||
|
||||
/** Return a unique name based on \a base for a new internal MIDI source */
|
||||
/** Return a unique name based on \a owner_name for a new internal MIDI source */
|
||||
string
|
||||
Session::new_midi_source_name (const string& base)
|
||||
Session::new_midi_source_name (const string& owner_name)
|
||||
{
|
||||
uint32_t cnt;
|
||||
char buf[PATH_MAX+1];
|
||||
const uint32_t limit = 10000;
|
||||
string legalized;
|
||||
string possible_name;
|
||||
|
||||
buf[0] = '\0';
|
||||
legalized = legalize_for_path (base);
|
||||
legalized = legalize_for_path (owner_name);
|
||||
|
||||
// Find a "version" of the file name that doesn't exist in any of the possible directories.
|
||||
|
||||
for (cnt = 1; cnt <= limit; ++cnt) {
|
||||
|
||||
vector<space_and_path>::iterator i;
|
||||
|
|
@ -3818,11 +3760,16 @@ Session::new_midi_source_name (const string& base)
|
|||
|
||||
SessionDirectory sdir((*i).path);
|
||||
|
||||
std::string p = Glib::build_filename (sdir.midi_path(), legalized);
|
||||
snprintf (buf, sizeof(buf), "%s-%u.mid", legalized.c_str(), cnt);
|
||||
possible_name = buf;
|
||||
|
||||
snprintf (buf, sizeof(buf), "%s-%u.mid", p.c_str(), cnt);
|
||||
std::string possible_path = Glib::build_filename (sdir.midi_path(), possible_name);
|
||||
|
||||
if (Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
|
||||
if (Glib::file_test (possible_path, Glib::FILE_TEST_EXISTS)) {
|
||||
existing++;
|
||||
}
|
||||
|
||||
if (source_by_path (possible_path)) {
|
||||
existing++;
|
||||
}
|
||||
}
|
||||
|
|
@ -3834,37 +3781,64 @@ Session::new_midi_source_name (const string& base)
|
|||
if (cnt > limit) {
|
||||
error << string_compose(
|
||||
_("There are already %1 recordings for %2, which I consider too many."),
|
||||
limit, base) << endmsg;
|
||||
limit, owner_name) << endmsg;
|
||||
destroy ();
|
||||
throw failed_constructor();
|
||||
}
|
||||
}
|
||||
|
||||
return Glib::path_get_basename(buf);
|
||||
return possible_name;
|
||||
}
|
||||
|
||||
|
||||
/** Create a new within-session MIDI source */
|
||||
boost::shared_ptr<MidiSource>
|
||||
Session::create_midi_source_for_session (Track* track, string const & n)
|
||||
Session::create_midi_source_for_session (string const & basic_name)
|
||||
{
|
||||
/* try to use the existing write source for the track, to keep numbering sane
|
||||
std::string name;
|
||||
|
||||
if (name.empty()) {
|
||||
name = new_midi_source_name (basic_name);
|
||||
}
|
||||
|
||||
const string path = new_source_path_from_name (DataType::MIDI, name);
|
||||
|
||||
return boost::dynamic_pointer_cast<SMFSource> (
|
||||
SourceFactory::createWritable (
|
||||
DataType::MIDI, *this, path, false, frame_rate()));
|
||||
}
|
||||
|
||||
/** Create a new within-session MIDI source */
|
||||
boost::shared_ptr<MidiSource>
|
||||
Session::create_midi_source_by_stealing_name (boost::shared_ptr<Track> track)
|
||||
{
|
||||
/* the caller passes in the track the source will be used in,
|
||||
so that we can keep the numbering sane.
|
||||
|
||||
Rationale: a track with the name "Foo" that has had N
|
||||
captures carried out so far will ALREADY have a write source
|
||||
named "Foo-N+1.mid" waiting to be used for the next capture.
|
||||
|
||||
If we call new_midi_source_name() we will get "Foo-N+2". But
|
||||
there is no region corresponding to "Foo-N+1", so when
|
||||
"Foo-N+2" appears in the track, the gap presents the user
|
||||
with odd behaviour - why did it skip past Foo-N+1?
|
||||
|
||||
We could explain this to the user in some odd way, but
|
||||
instead we rename "Foo-N+1.mid" as "Foo-N+2.mid", and then
|
||||
use "Foo-N+1" here.
|
||||
|
||||
If that attempted rename fails, we get "Foo-N+2.mid" anyway.
|
||||
*/
|
||||
|
||||
if (track) {
|
||||
/*MidiTrack* mt = dynamic_cast<Track*> (track);
|
||||
boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (track);
|
||||
assert (mt);
|
||||
*/
|
||||
std::string name = track->steal_write_source_name ();
|
||||
|
||||
list<boost::shared_ptr<Source> > l = track->steal_write_sources ();
|
||||
|
||||
if (!l.empty()) {
|
||||
assert (boost::dynamic_pointer_cast<MidiSource> (l.front()));
|
||||
return boost::dynamic_pointer_cast<MidiSource> (l.front());
|
||||
}
|
||||
if (name.empty()) {
|
||||
return boost::shared_ptr<MidiSource>();
|
||||
}
|
||||
|
||||
const string name = new_midi_source_name (n);
|
||||
const string path = new_source_path_from_name (DataType::MIDI, name);
|
||||
|
||||
return boost::dynamic_pointer_cast<SMFSource> (
|
||||
|
|
|
|||
|
|
@ -802,7 +802,7 @@ Session::load_state (string snapshot_name)
|
|||
|
||||
set_dirty();
|
||||
|
||||
_writable = exists_and_writable (xmlpath);
|
||||
_writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
|
||||
|
||||
if (!state_tree->read (xmlpath)) {
|
||||
error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
|
||||
|
|
@ -920,7 +920,7 @@ Session::state (bool full_state)
|
|||
p += (*i).path;
|
||||
|
||||
if (next != session_dirs.end()) {
|
||||
p += ':';
|
||||
p += G_SEARCHPATH_SEPARATOR;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
|
@ -2684,7 +2684,7 @@ Session::cleanup_sources (CleanupReport& rep)
|
|||
audio_path += sdir.sound_path();
|
||||
|
||||
if (nexti != session_dirs.end()) {
|
||||
audio_path += ':';
|
||||
audio_path += G_SEARCHPATH_SEPARATOR;
|
||||
}
|
||||
|
||||
i = nexti;
|
||||
|
|
@ -2702,7 +2702,7 @@ Session::cleanup_sources (CleanupReport& rep)
|
|||
midi_path += sdir.midi_path();
|
||||
|
||||
if (nexti != session_dirs.end()) {
|
||||
midi_path += ':';
|
||||
midi_path += G_SEARCHPATH_SEPARATOR;
|
||||
}
|
||||
|
||||
i = nexti;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,9 @@ SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags)
|
|||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
assert (!Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
|
||||
existence_check ();
|
||||
|
||||
/* file is not opened until write */
|
||||
|
||||
if (flags & Writable) {
|
||||
|
|
@ -76,6 +79,7 @@ SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags)
|
|||
if (open (_path)) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
_open = true;
|
||||
}
|
||||
|
||||
|
|
@ -97,6 +101,9 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
|
|||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
|
||||
existence_check ();
|
||||
|
||||
if (open(_path)) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
|
@ -658,3 +665,44 @@ SMFSource::ensure_disk_file ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
SMFSource::prevent_deletion ()
|
||||
{
|
||||
/* Unlike the audio case, the MIDI file remains mutable (because we can
|
||||
edit MIDI data)
|
||||
*/
|
||||
|
||||
_flags = Flag (_flags & ~(Removable|RemovableIfEmpty|RemoveAtDestroy));
|
||||
}
|
||||
|
||||
int
|
||||
SMFSource::rename (const string& newname)
|
||||
{
|
||||
Glib::Threads::Mutex::Lock lm (_lock);
|
||||
string oldpath = _path;
|
||||
string newpath = _session.new_source_path_from_name (DataType::MIDI, newname);
|
||||
|
||||
if (newpath.empty()) {
|
||||
error << string_compose (_("programming error: %1"), "cannot generate a changed file path") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Test whether newpath exists, if yes notify the user but continue.
|
||||
if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
|
||||
error << string_compose (_("Programming error! %1 tried to rename a file over another file! It's safe to continue working, but please report this to the developers."), PROGRAM_NAME) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (Glib::file_test (oldpath.c_str(), Glib::FILE_TEST_EXISTS)) {
|
||||
/* rename only needed if file exists on disk */
|
||||
if (::rename (oldpath.c_str(), newpath.c_str()) != 0) {
|
||||
error << string_compose (_("cannot rename file %1 to %2 (%3)"), oldpath, newpath, strerror(errno)) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
_name = Glib::path_get_basename (newpath);
|
||||
_path = newpath;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#ifdef PLATFORM_WINDOWS
|
||||
#include <glibmm/convert.h>
|
||||
#endif
|
||||
#include <glibmm/fileutils.h>
|
||||
#include <glibmm/miscutils.h>
|
||||
|
||||
#include "ardour/sndfilesource.h"
|
||||
|
|
@ -57,39 +58,70 @@ const Source::Flag SndFileSource::default_writable_flags = Source::Flag (
|
|||
SndFileSource::SndFileSource (Session& s, const XMLNode& node)
|
||||
: Source(s, node)
|
||||
, AudioFileSource (s, node)
|
||||
, _descriptor (0)
|
||||
, _broadcast_info (0)
|
||||
, _capture_start (false)
|
||||
, _capture_end (false)
|
||||
, file_pos (0)
|
||||
, xfade_buf (0)
|
||||
{
|
||||
init_sndfile ();
|
||||
|
||||
assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
|
||||
existence_check ();
|
||||
|
||||
if (open()) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
||||
/** Files created this way are never writable or removable */
|
||||
/** Constructor for existing external-to-session files.
|
||||
Files created this way are never writable or removable
|
||||
*/
|
||||
SndFileSource::SndFileSource (Session& s, const string& path, int chn, Flag flags)
|
||||
: Source(s, DataType::AUDIO, path, flags)
|
||||
/* note that the origin of an external file is itself */
|
||||
, AudioFileSource (s, path, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
|
||||
, _descriptor (0)
|
||||
, _broadcast_info (0)
|
||||
, _capture_start (false)
|
||||
, _capture_end (false)
|
||||
, file_pos (0)
|
||||
, xfade_buf (0)
|
||||
{
|
||||
_channel = chn;
|
||||
|
||||
init_sndfile ();
|
||||
|
||||
assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
|
||||
existence_check ();
|
||||
|
||||
if (open()) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
||||
/** This constructor is used to construct new files, not open existing ones. */
|
||||
/** This constructor is used to construct new internal-to-session files,
|
||||
not open existing ones.
|
||||
*/
|
||||
SndFileSource::SndFileSource (Session& s, const string& path, const string& origin,
|
||||
SampleFormat sfmt, HeaderFormat hf, framecnt_t rate, Flag flags)
|
||||
: Source(s, DataType::AUDIO, path, flags)
|
||||
, AudioFileSource (s, path, origin, flags, sfmt, hf)
|
||||
, _descriptor (0)
|
||||
, _broadcast_info (0)
|
||||
, _capture_start (false)
|
||||
, _capture_end (false)
|
||||
, file_pos (0)
|
||||
, xfade_buf (0)
|
||||
{
|
||||
int fmt = 0;
|
||||
|
||||
init_sndfile ();
|
||||
|
||||
assert (!Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
|
||||
existence_check ();
|
||||
|
||||
_file_is_new = true;
|
||||
|
||||
switch (hf) {
|
||||
|
|
@ -156,24 +188,12 @@ SndFileSource::SndFileSource (Session& s, const string& path, const string& orig
|
|||
void
|
||||
SndFileSource::init_sndfile ()
|
||||
{
|
||||
string file;
|
||||
|
||||
_descriptor = 0;
|
||||
|
||||
// lets try to keep the object initalizations here at the top
|
||||
xfade_buf = 0;
|
||||
_broadcast_info = 0;
|
||||
|
||||
/* although libsndfile says we don't need to set this,
|
||||
valgrind and source code shows us that we do.
|
||||
*/
|
||||
|
||||
memset (&_info, 0, sizeof(_info));
|
||||
|
||||
_capture_start = false;
|
||||
_capture_end = false;
|
||||
file_pos = 0;
|
||||
|
||||
if (destructive()) {
|
||||
xfade_buf = new Sample[xfade_frames];
|
||||
_timeline_position = header_position_offset;
|
||||
|
|
|
|||
|
|
@ -579,10 +579,10 @@ Track::set_capture_offset ()
|
|||
_diskstream->set_capture_offset ();
|
||||
}
|
||||
|
||||
list<boost::shared_ptr<Source> >
|
||||
Track::steal_write_sources()
|
||||
std::string
|
||||
Track::steal_write_source_name()
|
||||
{
|
||||
return _diskstream->steal_write_sources ();
|
||||
return _diskstream->steal_write_source_name ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ Worker::verify_message_completeness(RingBuffer<uint8_t>* rb)
|
|||
uint32_t size;
|
||||
RingBuffer<uint8_t>::rw_vector vec;
|
||||
rb->get_read_vector (&vec);
|
||||
if (vec.len[0] + vec.len[1] < sizeof(size)) {
|
||||
return false;
|
||||
}
|
||||
if (vec.len[0] >= sizeof(size)) {
|
||||
memcpy (&size, vec.buf[0], sizeof (size));
|
||||
} else {
|
||||
|
|
@ -121,6 +124,7 @@ Worker::run()
|
|||
while (true) {
|
||||
_sem.wait();
|
||||
if (_exit) {
|
||||
if (buf) free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -132,6 +136,7 @@ Worker::run()
|
|||
while (!verify_message_completeness(_requests)) {
|
||||
Glib::usleep(2000);
|
||||
if (_exit) {
|
||||
if (buf) free(buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -143,7 +148,13 @@ Worker::run()
|
|||
|
||||
if (size > buf_size) {
|
||||
buf = realloc(buf, size);
|
||||
if (buf) {
|
||||
buf_size = size;
|
||||
} else {
|
||||
PBD::error << "Worker: Error allocating memory"
|
||||
<< endmsg;
|
||||
buf_size = 0; // TODO: This is probably fatal
|
||||
}
|
||||
}
|
||||
|
||||
if (_requests->read((uint8_t*)buf, size) < size) {
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ def build(bld):
|
|||
obj.includes += [ '../fst' ]
|
||||
obj.defines += [ 'WINDOWS_VST_SUPPORT' ]
|
||||
if bld.env['build_target'] == 'mingw':
|
||||
obj.source += [ '../fst/vstwin.c', '../fst/fst.c']
|
||||
obj.source += [ '../fst/vstwin.c']
|
||||
obj.uselib += ['GDI32']
|
||||
|
||||
if bld.is_defined('LXVST_SUPPORT'):
|
||||
|
|
@ -419,7 +419,7 @@ def build(bld):
|
|||
testcommon.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD',
|
||||
'SAMPLERATE','XML','LRDF','COREAUDIO','TAGLIB','VAMPSDK','VAMPHOSTSDK','RUBBERBAND']
|
||||
testcommon.use = ['libpbd','libmidipp','libevoral',
|
||||
'libaudiographer','ardour']
|
||||
'libaudiographer','libardour']
|
||||
if bld.is_defined('USE_EXTERNAL_LIBS'):
|
||||
testcommon.uselib.extend(['LIBLTC',])
|
||||
else:
|
||||
|
|
@ -499,7 +499,7 @@ def build(bld):
|
|||
session_load_tester.includes.append ('test')
|
||||
session_load_tester.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD',
|
||||
'SAMPLERATE','XML','LRDF','COREAUDIO']
|
||||
session_load_tester.use = ['libpbd','libmidipp','ardour']
|
||||
session_load_tester.use = ['libpbd','libmidipp','libardour']
|
||||
session_load_tester.name = 'libardour-session-load-tester'
|
||||
session_load_tester.target = 'load-session'
|
||||
session_load_tester.install_path = ''
|
||||
|
|
@ -532,7 +532,7 @@ def build(bld):
|
|||
profilingobj.includes.append ('test')
|
||||
profilingobj.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD',
|
||||
'SAMPLERATE','XML','LRDF','COREAUDIO']
|
||||
profilingobj.use = ['libpbd','libmidipp','ardour']
|
||||
profilingobj.use = ['libpbd','libmidipp','libardour']
|
||||
profilingobj.name = 'libardour-profiling'
|
||||
profilingobj.target = p
|
||||
profilingobj.install_path = ''
|
||||
|
|
@ -558,7 +558,7 @@ def create_ardour_test_program(bld, includes, name, target, sources):
|
|||
testobj.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD',
|
||||
'SAMPLERATE','XML','LRDF','COREAUDIO','TAGLIB','VAMPSDK','VAMPHOSTSDK','RUBBERBAND']
|
||||
testobj.use = ['libpbd','libmidipp','libevoral',
|
||||
'libaudiographer','ardour','testcommon']
|
||||
'libaudiographer','libardour','testcommon']
|
||||
if bld.is_defined('USE_EXTERNAL_LIBS'):
|
||||
testobj.uselib.extend(['LIBLTC'])
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -33,7 +33,11 @@ namespace Evoral {
|
|||
* Currently a note is defined as (on event, length, off event).
|
||||
*/
|
||||
template<typename Time>
|
||||
#ifdef COMPILER_MSVC
|
||||
class LIBEVORAL_LOCAL Note {
|
||||
#else
|
||||
class LIBEVORAL_TEMPLATE_API Note {
|
||||
#endif
|
||||
public:
|
||||
Note(uint8_t chan=0, Time time=0, Time len=0, uint8_t note=0, uint8_t vel=0x40);
|
||||
Note(const Note<Time>& copy);
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@
|
|||
#define LIBEVORAL_DLL_IMPORT __declspec(dllimport)
|
||||
#define LIBEVORAL_DLL_EXPORT __declspec(dllexport)
|
||||
#define LIBEVORAL_DLL_LOCAL
|
||||
#define LIBEVORAL_TEMPLATE_DLL_IMPORT
|
||||
#define LIBEVORAL_TEMPLATE_DLL_EXPORT
|
||||
#define LIBEVORAL_TEMPLATE_DLL_IMPORT __declspec(dllimport)
|
||||
#define LIBEVORAL_TEMPLATE_DLL_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define LIBEVORAL_DLL_IMPORT __attribute__ ((visibility ("default")))
|
||||
#define LIBEVORAL_DLL_EXPORT __attribute__ ((visibility ("default")))
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ SMF::append_event_delta(uint32_t delta_t, uint32_t size, const uint8_t* buf, eve
|
|||
/* this should be allocated by malloc(3) because libsmf will
|
||||
call free(3) on it
|
||||
*/
|
||||
event->midi_buffer = (uint8_t*) malloc (sizeof (uint8_t*) * event->midi_buffer_length);
|
||||
event->midi_buffer = (uint8_t*) malloc (sizeof(uint8_t) * event->midi_buffer_length);
|
||||
|
||||
event->midi_buffer[0] = 0xff; // Meta-event
|
||||
event->midi_buffer[1] = 0x7f; // Sequencer-specific
|
||||
|
|
|
|||
|
|
@ -5,50 +5,31 @@
|
|||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "ardour/libardour_visibility.h"
|
||||
#include "ardour/vst_types.h"
|
||||
#include "ardour/vestige/aeffectx.h"
|
||||
|
||||
/**
|
||||
* Display FST error message.
|
||||
*
|
||||
* Set via fst_set_error_function(), otherwise a FST-provided
|
||||
* default will print @a msg (plus a newline) to stderr.
|
||||
*
|
||||
* @param msg error message text (no newline at end).
|
||||
*/
|
||||
extern void (*fst_error_callback)(const char *msg);
|
||||
|
||||
/**
|
||||
* Set the @ref fst_error_callback for error message display.
|
||||
*
|
||||
* The FST library provides two built-in callbacks for this purpose:
|
||||
* default_fst_error_callback() and silent_fst_error_callback().
|
||||
*/
|
||||
void fst_set_error_function (void (*func)(const char *));
|
||||
|
||||
void fst_error (const char *fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int fst_init (void* possible_hmodule);
|
||||
extern void fst_exit (void);
|
||||
LIBARDOUR_API int fst_init (void* possible_hmodule);
|
||||
LIBARDOUR_API void fst_exit (void);
|
||||
|
||||
extern VSTHandle* fst_load (const char*);
|
||||
extern int fst_unload (VSTHandle**);
|
||||
LIBARDOUR_API VSTHandle* fst_load (const char*);
|
||||
LIBARDOUR_API int fst_unload (VSTHandle**);
|
||||
|
||||
extern VSTState * fst_instantiate (VSTHandle *, audioMasterCallback amc, void* userptr);
|
||||
extern void fst_close (VSTState *);
|
||||
LIBARDOUR_API VSTState * fst_instantiate (VSTHandle *, audioMasterCallback amc, void* userptr);
|
||||
LIBARDOUR_API void fst_close (VSTState *);
|
||||
|
||||
extern int fst_run_editor (VSTState *, void* window_parent);
|
||||
extern void fst_destroy_editor (VSTState *);
|
||||
extern void fst_move_window_into_view (VSTState *);
|
||||
LIBARDOUR_API int fst_run_editor (VSTState *, void* window_parent);
|
||||
LIBARDOUR_API void fst_destroy_editor (VSTState *);
|
||||
LIBARDOUR_API void fst_move_window_into_view (VSTState *);
|
||||
|
||||
extern void fst_event_loop_remove_plugin (VSTState* fst);
|
||||
extern void fst_start_threading(void);
|
||||
extern void fst_stop_threading(void);
|
||||
extern void fst_audio_master_idle(void);
|
||||
LIBARDOUR_API void fst_event_loop_remove_plugin (VSTState* fst);
|
||||
LIBARDOUR_API void fst_start_threading(void);
|
||||
LIBARDOUR_API void fst_stop_threading(void);
|
||||
LIBARDOUR_API void fst_audio_master_idle(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@
|
|||
#include <string.h>
|
||||
#include <windows.h>
|
||||
|
||||
#define fst_error(...) fprintf(stderr, __VA_ARGS__)
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
|
||||
#include <pthread.h>
|
||||
static UINT_PTR idle_timer_id = 0;
|
||||
extern char *basename(char *path);
|
||||
|
||||
#else /* linux + wine */
|
||||
|
||||
#include <linux/limits.h> // PATH_MAX
|
||||
#include <libgen.h> // basename
|
||||
#include <winnt.h>
|
||||
#include <wine/exception.h>
|
||||
#include <pthread.h>
|
||||
|
|
@ -489,9 +489,8 @@ fst_load (const char *path)
|
|||
if ((strlen(path)) && (NULL != (fhandle = fst_handle_new ())))
|
||||
{
|
||||
char* period;
|
||||
fhandle->nameptr = strdup (path);
|
||||
fhandle->path = strdup (path);
|
||||
fhandle->name = basename(fhandle->nameptr);
|
||||
fhandle->name = g_path_get_basename(path);
|
||||
if ((period = strrchr (fhandle->name, '.'))) {
|
||||
*period = '\0';
|
||||
}
|
||||
|
|
@ -502,10 +501,10 @@ fst_load (const char *path)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
fhandle->main_entry = (main_entry_t) GetProcAddress (fhandle->dll, "main");
|
||||
fhandle->main_entry = (main_entry_t) GetProcAddress ((HMODULE)fhandle->dll, "main");
|
||||
|
||||
if (fhandle->main_entry == 0) {
|
||||
if ((fhandle->main_entry = (main_entry_t) GetProcAddress (fhandle->dll, "VSTPluginMain"))) {
|
||||
if ((fhandle->main_entry = (main_entry_t) GetProcAddress ((HMODULE)fhandle->dll, "VSTPluginMain"))) {
|
||||
fprintf(stderr, "VST >= 2.4 plugin '%s'\n", path);
|
||||
//PBD::warning << path << _(": is a VST >= 2.4 - this plugin may or may not function correctly with this version of Ardour.") << endmsg;
|
||||
}
|
||||
|
|
@ -540,9 +539,8 @@ fst_unload (VSTHandle** fhandle)
|
|||
(*fhandle)->path = NULL;
|
||||
}
|
||||
|
||||
if ((*fhandle)->nameptr) {
|
||||
free ((*fhandle)->nameptr);
|
||||
(*fhandle)->nameptr = NULL;
|
||||
if ((*fhandle)->name) {
|
||||
free ((*fhandle)->name);
|
||||
(*fhandle)->name = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ def build(bld):
|
|||
obj = bld (features = 'c cxx cxxprogram wine')
|
||||
obj.source = (
|
||||
'scanner.cc',
|
||||
'fst.c',
|
||||
'vstwin.c',
|
||||
)
|
||||
obj.linkflags = ['-mwindows', '-Wl,--export-dynamic']
|
||||
|
|
@ -69,7 +68,7 @@ def build(bld):
|
|||
else:
|
||||
obj = bld (features = 'cxx c cxxprogram')
|
||||
if bld.is_defined('WINDOWS_VST_SUPPORT'):
|
||||
obj.source = ( 'scanner.cc', 'fst.c', 'vstwin.c' )
|
||||
obj.source = ( 'scanner.cc', 'vstwin.c' )
|
||||
obj.uselib = ['GIOMM', 'DL', 'GDI32']
|
||||
else:
|
||||
obj.source = ( 'scanner.cc' )
|
||||
|
|
|
|||
|
|
@ -94,3 +94,38 @@ PBD::clear_directory (const string& dir, size_t* size, vector<string>* paths)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// rm -rf <dir> -- used to remove saved plugin state
|
||||
void
|
||||
PBD::remove_directory (const std::string& dir) {
|
||||
DIR* dead;
|
||||
struct dirent* dentry;
|
||||
struct stat statbuf;
|
||||
|
||||
if ((dead = ::opendir (dir.c_str())) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while ((dentry = ::readdir (dead)) != 0) {
|
||||
if(!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string fullpath = Glib::build_filename (dir, dentry->d_name);
|
||||
if (::stat (fullpath.c_str(), &statbuf)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR (statbuf.st_mode)) {
|
||||
remove_directory(fullpath);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (::g_unlink (fullpath.c_str())) {
|
||||
error << string_compose (_("cannot remove file %1 (%2)"), fullpath, strerror (errno)) << endmsg;
|
||||
}
|
||||
}
|
||||
if (::g_rmdir(dir.c_str())) {
|
||||
error << string_compose (_("cannot remove directory %1 (%2)"), dir, strerror (errno)) << endmsg;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,9 +78,10 @@ PBD::set_debug_bits (uint64_t bits)
|
|||
int
|
||||
PBD::parse_debug_options (const char* str)
|
||||
{
|
||||
string in_str = str;
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
boost::char_separator<char> sep (",");
|
||||
tokenizer tokens (string(str), sep);
|
||||
tokenizer tokens (in_str, sep);
|
||||
uint64_t bits = 0;
|
||||
|
||||
for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {
|
||||
|
|
|
|||
|
|
@ -131,19 +131,26 @@ EnvironmentalProtectionAgency::restore () const
|
|||
void
|
||||
EnvironmentalProtectionAgency::clear () const
|
||||
{
|
||||
char** the_environ = environ;
|
||||
/* Copy the environment before using (g_)unsetenv() because on some
|
||||
platforms (maybe all?) this directly modifies the environ array,
|
||||
cause complications for iterating through it.
|
||||
*/
|
||||
|
||||
for (size_t i = 0; the_environ[i]; ++i) {
|
||||
vector<string> ecopy;
|
||||
|
||||
string estring = the_environ[i];
|
||||
string::size_type equal = estring.find_first_of ('=');
|
||||
for (size_t i = 0; environ[i]; ++i) {
|
||||
ecopy.push_back (environ[i]);
|
||||
}
|
||||
|
||||
for (vector<string>::const_iterator e = ecopy.begin(); e != ecopy.end(); ++e) {
|
||||
string::size_type equal = (*e).find_first_of ('=');
|
||||
|
||||
if (equal == string::npos) {
|
||||
/* say what? an environ value without = ? */
|
||||
continue;
|
||||
}
|
||||
|
||||
string before = estring.substr (0, equal);
|
||||
g_unsetenv(before.c_str());
|
||||
string var_name = (*e).substr (0, equal);
|
||||
g_unsetenv(var_name.c_str());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,20 @@
|
|||
#include <glibmm/miscutils.h>
|
||||
#include <glibmm/pattern.h>
|
||||
|
||||
#include <giomm/file.h>
|
||||
#include <errno.h>
|
||||
#include <string.h> /* strerror */
|
||||
|
||||
/* open() */
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/* close(), read(), write() */
|
||||
#ifdef COMPILER_MSVC
|
||||
#include <io.h> // Microsoft's nearest equivalent to <unistd.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "pbd/compose.h"
|
||||
#include "pbd/file_utils.h"
|
||||
|
|
@ -153,22 +166,58 @@ copy_file(const std::string & from_path, const std::string & to_path)
|
|||
{
|
||||
if (!Glib::file_test (from_path, Glib::FILE_TEST_EXISTS)) return false;
|
||||
|
||||
Glib::RefPtr<Gio::File> from_file = Gio::File::create_for_path(from_path);
|
||||
Glib::RefPtr<Gio::File> to_file = Gio::File::create_for_path(to_path);
|
||||
int fd_from = -1;
|
||||
int fd_to = -1;
|
||||
char buf[4096]; // BUFSIZ ??
|
||||
ssize_t nread;
|
||||
|
||||
try
|
||||
{
|
||||
from_file->copy (to_file, Gio::FILE_COPY_OVERWRITE);
|
||||
fd_from = ::open(from_path.c_str(), O_RDONLY);
|
||||
if (fd_from < 0) {
|
||||
goto copy_error;
|
||||
}
|
||||
catch(const Glib::Exception& ex)
|
||||
{
|
||||
|
||||
fd_to = ::open(to_path.c_str(), O_WRONLY | O_CREAT, 0666);
|
||||
if (fd_to < 0) {
|
||||
goto copy_error;
|
||||
}
|
||||
|
||||
while (nread = ::read(fd_from, buf, sizeof(buf)), nread > 0) {
|
||||
char *out_ptr = buf;
|
||||
do {
|
||||
ssize_t nwritten = ::write(fd_to, out_ptr, nread);
|
||||
if (nwritten >= 0) {
|
||||
nread -= nwritten;
|
||||
out_ptr += nwritten;
|
||||
} else if (errno != EINTR) {
|
||||
goto copy_error;
|
||||
}
|
||||
} while (nread > 0);
|
||||
}
|
||||
|
||||
if (nread == 0) {
|
||||
if (::close(fd_to)) {
|
||||
fd_to = -1;
|
||||
goto copy_error;
|
||||
}
|
||||
::close(fd_from);
|
||||
return true;
|
||||
}
|
||||
|
||||
copy_error:
|
||||
int saved_errno = errno;
|
||||
|
||||
if (fd_from >= 0) {
|
||||
::close(fd_from);
|
||||
}
|
||||
if (fd_to >= 0) {
|
||||
::close(fd_to);
|
||||
}
|
||||
|
||||
error << string_compose (_("Unable to Copy file %1 to %2 (%3)"),
|
||||
from_path, to_path, ex.what())
|
||||
from_path, to_path, strerror(saved_errno))
|
||||
<< endmsg;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool accept_all_files (string const &, void *)
|
||||
|
|
@ -195,8 +244,8 @@ copy_files(const std::string & from_path, const std::string & to_dir)
|
|||
std::string
|
||||
get_absolute_path (const std::string & p)
|
||||
{
|
||||
Glib::RefPtr<Gio::File> f = Gio::File::create_for_path (p);
|
||||
return f->get_path ();
|
||||
if (Glib::path_is_absolute(p)) return p;
|
||||
return Glib::build_filename (Glib::get_current_dir(), p);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ PBD::search_path_expand (string path)
|
|||
vector<string> s;
|
||||
vector<string> n;
|
||||
|
||||
split (path, s, ':');
|
||||
split (path, s, G_SEARCHPATH_SEPARATOR);
|
||||
|
||||
for (vector<string>::iterator i = s.begin(); i != s.end(); ++i) {
|
||||
string exp = path_expand (*i);
|
||||
|
|
@ -187,7 +187,7 @@ PBD::search_path_expand (string path)
|
|||
|
||||
for (vector<string>::iterator i = n.begin(); i != n.end(); ++i) {
|
||||
if (!r.empty()) {
|
||||
r += ':';
|
||||
r += G_SEARCHPATH_SEPARATOR;
|
||||
}
|
||||
r += *i;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ PathScanner::run_scan_internal (vector<string *> *result,
|
|||
}
|
||||
closedir (dir);
|
||||
|
||||
} while ((limit < 0 || (nfound < limit)) && (thisdir = strtok (0, ":")));
|
||||
} while ((limit < 0 || (nfound < limit)) && (thisdir = strtok (0, G_SEARCHPATH_SEPARATOR_S)));
|
||||
|
||||
free (pathcopy);
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ cleanup_request_buffer (void* ptr)
|
|||
|
||||
/* this is called when the thread for which this request buffer was
|
||||
* allocated dies. That could be before or after the end of the UI
|
||||
* event loop that the request buffer communicates.
|
||||
* event loop for which this request buffer provides communication.
|
||||
*
|
||||
* We are not modifying the UI's thread/buffer map, just marking it
|
||||
* dead. If the UI is currently processing the buffers and misses
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
namespace PBD {
|
||||
LIBPBD_API int clear_directory (const std::string&, size_t* = 0, std::vector<std::string>* = 0);
|
||||
LIBPBD_API void remove_directory (const std::string& dir);
|
||||
}
|
||||
|
||||
#endif /* __pbd_clear_dir_h__ */
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ export_search_path (const string& base_dir, const char* varname, const char* dir
|
|||
|
||||
if (cstr) {
|
||||
path = cstr;
|
||||
path += ':';
|
||||
path += G_SEARCHPATH_SEPARATOR;
|
||||
} else {
|
||||
path = "";
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue