[Summary] Merging from GIT

[Details] Starting point:
Mar 24 2014, 11:47 PM
Commit: 87184ab80d

Target point:
Commit: 59e6694405
Apr 16 2014, 4:01 PM

[git-p4: depot-paths = "//Abdaw/dev_main/tracks/": change = 453690]
This commit is contained in:
Grygorii Zharun 2014-04-18 04:21:54 -05:00
parent 0046ee6488
commit ce2a519afa
103 changed files with 2160 additions and 915 deletions

View file

@ -85,15 +85,15 @@ ActionManager::load_menus (const string& menus_file)
info << string_compose (_("Loading menus from %1"), ui_file) << endmsg; info << string_compose (_("Loading menus from %1"), ui_file) << endmsg;
loaded = true; loaded = true;
} catch (Glib::MarkupError& err) { } catch (Glib::MarkupError& err) {
error << string_compose (_("badly formatted UI definition file: %1"), err.what()) << endmsg; error << string_compose (_("badly formatted menu definition file: %1"), err.what()) << endmsg;
cerr << string_compose (_("badly formatted UI definition file: %1"), err.what()) << endl; cerr << string_compose (_("badly formatted menu definition file: %1"), err.what()) << endl;
} catch (...) { } catch (...) {
error << string_compose (_("%1 menu definition file not found"), PROGRAM_NAME) << endmsg; error << string_compose (_("%1 menu definition file not found"), PROGRAM_NAME) << endmsg;
} }
if (!loaded) { if (!loaded) {
cerr << string_compose (_("%1 will not work without a valid ardour.menus file"), PROGRAM_NAME) << endl; 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 ardour.menus file"), PROGRAM_NAME) << endmsg; error << string_compose (_("%1 will not work without a valid menu definition file"), PROGRAM_NAME) << endmsg;
exit(1); exit(1);
} }
} }

View file

@ -374,6 +374,7 @@ AnalysisWindow::analyze_data (Gtk::Button * /*button*/)
free(buf); free(buf);
free(mixbuf); free(mixbuf);
free(gain);
track_list_ready = true; track_list_ready = true;
} /* end lock */ } /* end lock */

View file

@ -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 ) { if ( !_flat_buttons ) {
float rheight = get_height()*0.5-REFLECTION_HEIGHT; float rheight = get_height()*0.5-REFLECTION_HEIGHT;

View file

@ -37,7 +37,7 @@ class ArdourButton : public CairoWidget , public Gtkmm2ext::Activatable
Body = 0x2, Body = 0x2,
Text = 0x4, Text = 0x4,
Indicator = 0x8, Indicator = 0x8,
FlatFace = 0x10, Inset = 0x10,
}; };
static Element default_elements; static Element default_elements;

View file

@ -1659,10 +1659,10 @@ ARDOUR_UI::session_add_mixed_track (const ChanCount& input, const ChanCount& out
catch (...) { catch (...) {
MessageDialog msg (*editor, 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\ to create a new track or bus.\n\
You should save %1, exit and\n\ You should save %1, exit and\n\
restart JACK with more ports."), PROGRAM_NAME)); restart with more ports."), PROGRAM_NAME));
msg.run (); msg.run ();
} }
} }
@ -1720,10 +1720,10 @@ ARDOUR_UI::session_add_audio_route (
catch (...) { catch (...) {
MessageDialog msg (*editor, 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\ to create a new track or bus.\n\
You should save %1, exit and\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); pop_back_splash (msg);
msg.run (); msg.run ();
} }
@ -1885,12 +1885,25 @@ ARDOUR_UI::transport_roll ()
bool rolling = _session->transport_rolling(); bool rolling = _session->transport_rolling();
if (_session->get_play_loop()) { if (_session->get_play_loop()) {
/* XXX it is not possible to just leave seamless loop and keep
playing at present (nov 4th 2009) /* 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_seamless_loop()) {
_session->request_play_loop (false, true); 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()) { } else if (_session->get_play_range () && !Config->get_always_play_range()) {
/* stop playing a range if we currently are */ /* stop playing a range if we currently are */
_session->request_play_range (0, true); _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 */ /* disk buffers are normal, so we can keep playing */
affect_transport = false; affect_transport = false;
} }
_session->request_play_loop (false, true); _session->request_play_loop (false, affect_transport);
} else if (_session->get_play_range ()) { } else if (_session->get_play_range ()) {
affect_transport = false; affect_transport = false;
_session->request_play_range (0, true); _session->request_play_range (0, true);
@ -1978,16 +1991,23 @@ ARDOUR_UI::toggle_session_auto_loop ()
if (_session->get_play_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);
_session->request_play_loop (false);
} else {
_session->request_play_loop (false);
}
} else { } else {
_session->request_play_loop (true);
/* 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);
}
} }
//show the loop markers //show the loop markers
@ -2115,7 +2135,11 @@ ARDOUR_UI::map_transport_state ()
auto_loop_button.set_active (true); auto_loop_button.set_active (true);
play_selection_button.set_active (false); play_selection_button.set_active (false);
roll_button.set_active (false); if (Config->get_loop_is_mode()) {
roll_button.set_active (true);
} else {
roll_button.set_active (false);
}
} else { } else {
@ -2137,7 +2161,11 @@ ARDOUR_UI::map_transport_state ()
stop_button.set_active (true); stop_button.set_active (true);
roll_button.set_active (false); roll_button.set_active (false);
play_selection_button.set_active (false); play_selection_button.set_active (false);
auto_loop_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 (); update_disk_space ();
} }
} }

View file

@ -175,6 +175,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
void new_midi_tracer_window (); void new_midi_tracer_window ();
void toggle_editing_space(); void toggle_editing_space();
void toggle_mixer_space();
void toggle_keep_tearoffs(); void toggle_keep_tearoffs();
Gtk::Tooltips& tooltips() { return _tooltips; } Gtk::Tooltips& tooltips() { return _tooltips; }

View file

@ -387,20 +387,29 @@ ARDOUR_UI::setup_transport ()
HBox* clock_box = manage (new HBox); HBox* clock_box = manage (new HBox);
clock_box->pack_start (*primary_clock, false, false); 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->pack_start (*secondary_clock, false, false);
} }
clock_box->set_spacing (3); clock_box->set_spacing (3);
shuttle_box = new ShuttleControl; shuttle_box = new ShuttleControl;
shuttle_box->show (); shuttle_box->show ();
VBox* transport_vbox = manage (new VBox); VBox* transport_vbox = manage (new VBox);
transport_vbox->set_name ("TransportBase"); transport_vbox->set_name ("TransportBase");
transport_vbox->set_border_width (0); transport_vbox->set_border_width (0);
transport_vbox->set_spacing (3); transport_vbox->set_spacing (3);
transport_vbox->pack_start (*tbox, true, true, 0); transport_vbox->pack_start (*tbox, true, true, 0);
transport_vbox->pack_start (*shuttle_box, false, false, 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); 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_homogeneous (true);
auto_box->set_spacing (2); auto_box->set_spacing (2);
auto_box->pack_start (sync_button, false, false); auto_box->pack_start (sync_button, false, false);
auto_box->pack_start (follow_edits_button, false, false); if (!ARDOUR::Profile->get_trx()) {
auto_box->pack_start (auto_return_button, false, false); auto_box->pack_start (follow_edits_button, false, false);
auto_box->pack_start (auto_return_button, false, false);
}
transport_tearoff_hbox.pack_start (*auto_box, 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); transport_tearoff_hbox.pack_start (*clock_box, true, true);
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 (*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); transport_tearoff_hbox.pack_start (_editor_transport_box, false, false);
} }
transport_tearoff_hbox.pack_start (alert_box, false, false);
transport_tearoff_hbox.pack_start (meter_box, false, false); if (!ARDOUR::Profile->get_trx()) {
transport_tearoff_hbox.pack_start (editor_meter_peak_display, false, false); 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()) { if (Profile->get_sae()) {
Image* img = manage (new Image ((::get_icon (X_("sae"))))); Image* img = manage (new Image ((::get_icon (X_("sae")))));

View file

@ -23,9 +23,10 @@
This is to cut down on the compile times. It also helps with my sanity. 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/audioengine.h"
#include "ardour/automation_watch.h" #include "ardour/automation_watch.h"
#include "ardour/profile.h"
#include "ardour/session.h"
#ifdef interface #ifdef interface
#undef interface #undef interface
@ -210,13 +211,15 @@ ARDOUR_UI::set_session (Session *s)
_session->master_out() && _session->master_out() &&
_session->master_out()->n_outputs().n(DataType::AUDIO) > 0) { _session->master_out()->n_outputs().n(DataType::AUDIO) > 0) {
editor_meter = new LevelMeterHBox(_session); if (!ARDOUR::Profile->get_trx()) {
editor_meter->set_meter (_session->master_out()->shared_peak_meter().get()); editor_meter = new LevelMeterHBox(_session);
editor_meter->clear_meters(); editor_meter->set_meter (_session->master_out()->shared_peak_meter().get());
editor_meter->set_type (_session->master_out()->meter_type()); editor_meter->clear_meters();
editor_meter->setup_meters (30, 12, 6); editor_meter->set_type (_session->master_out()->meter_type());
editor_meter->show(); editor_meter->setup_meters (30, 12, 6);
meter_box.pack_start(*editor_meter); editor_meter->show();
meter_box.pack_start(*editor_meter);
}
ArdourMeter::ResetAllPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_peak_display)); 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)); 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_max_peak = -INFINITY;
editor_meter_peak_display.signal_button_release_event().connect (sigc::mem_fun(*this, &ARDOUR_UI::editor_meter_peak_button_release), false); 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 (meter_box, false, false);
transport_tearoff_hbox.pack_start (editor_meter_peak_display, false, false); transport_tearoff_hbox.pack_start (editor_meter_peak_display, false, false);
meter_box.show(); meter_box.show();
@ -574,3 +577,18 @@ ARDOUR_UI::editor_meter_peak_button_release (GdkEventButton* ev)
} }
return true; 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 ();
}
}
}

View file

@ -191,6 +191,7 @@ ARDOUR_UI::install_actions ()
/* windows visibility 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_("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)); 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); ActionManager::session_sensitive_actions.push_back (act);

View 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;
}
}

View file

@ -167,6 +167,7 @@
<Binding action="Editor/pitch-shift-region" key="F5"/> <Binding action="Editor/pitch-shift-region" key="F5"/>
<Binding action="Editor/select-range-between-cursors" key="F6"/> <Binding action="Editor/select-range-between-cursors" key="F6"/>
<Binding action="Common/ToggleMaximalEditor" key="F11"/> <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-1" key="Primary-F1"/>
<Binding action="Editor/save-visual-state-2" key="Primary-F2"/> <Binding action="Editor/save-visual-state-2" key="Primary-F2"/>
<Binding action="Editor/save-visual-state-3" key="Primary-F3"/> <Binding action="Editor/save-visual-state-3" key="Primary-F3"/>

View file

@ -259,10 +259,11 @@ Editor::Editor ()
/* tool bar related */ /* tool bar related */
, zoom_range_clock (new AudioClock (X_("zoomrange"), false, X_("zoom range"), true, false, true)) , zoom_range_clock (new AudioClock (X_("zoomrange"), false, X_("zoom range"), true, false, true))
, toolbar_selection_clock_table (2,3) , toolbar_selection_clock_table (2,3)
, _mouse_mode_tearoff (0)
, automation_mode_button (_("mode")) , 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))) , _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; rb_current_opt = 4;
#endif #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; snap_threshold = 5.0;
bbt_beat_subdivision = 4; bbt_beat_subdivision = 4;
_visible_canvas_width = 0; _visible_canvas_width = 0;
_visible_canvas_height = 0; _visible_canvas_height = 0;
last_autoscroll_x = 0; autoscroll_horizontal_allowed = false;
last_autoscroll_y = 0; autoscroll_vertical_allowed = false;
autoscroll_active = false;
autoscroll_timeout_tag = -1;
logo_item = 0; logo_item = 0;
analysis_window = 0; analysis_window = 0;
@ -374,6 +380,7 @@ Editor::Editor ()
_edit_point = EditAtMouse; _edit_point = EditAtMouse;
_internal_editing = false; _internal_editing = false;
current_canvas_cursor = 0; current_canvas_cursor = 0;
_visible_track_count = 16;
samples_per_pixel = 2048; /* too early to use reset_zoom () */ samples_per_pixel = 2048; /* too early to use reset_zoom () */
@ -475,7 +482,9 @@ Editor::Editor ()
HBox* h = manage (new HBox); HBox* h = manage (new HBox);
_group_tabs = new EditorGroupTabs (this); _group_tabs = new EditorGroupTabs (this);
h->pack_start (*_group_tabs, PACK_SHRINK); if (!ARDOUR::Profile->get_trx()) {
h->pack_start (*_group_tabs, PACK_SHRINK);
}
h->pack_start (edit_controls_vbox); h->pack_start (edit_controls_vbox);
controls_layout.add (*h); controls_layout.add (*h);
@ -594,10 +603,14 @@ Editor::Editor ()
_summary_hbox.pack_start (*summary_frame, true, true); _summary_hbox.pack_start (*summary_frame, true, true);
_summary_hbox.pack_start (*summary_arrows_right, false, false); _summary_hbox.pack_start (*summary_arrows_right, false, false);
editor_summary_pane.pack2 (_summary_hbox); if (!ARDOUR::Profile->get_trx()) {
editor_summary_pane.pack2 (_summary_hbox);
}
edit_pane.pack1 (editor_summary_pane, true, true); edit_pane.pack1 (editor_summary_pane, true, true);
edit_pane.pack2 (_the_notebook, false, 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))); 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 (); setup_toolbar ();
set_zoom_focus (zoom_focus); set_zoom_focus (zoom_focus);
set_visible_track_count (_visible_track_count);
_snap_type = SnapToBeat; _snap_type = SnapToBeat;
set_snap_to (_snap_type); set_snap_to (_snap_type);
_snap_mode = SnapOff; _snap_mode = SnapOff;
@ -656,12 +670,12 @@ Editor::Editor ()
/* nudge stuff */ /* nudge stuff */
nudge_forward_button.set_name ("zoom button"); nudge_forward_button.set_name ("nudge button");
nudge_forward_button.add_elements (ArdourButton::FlatFace); nudge_forward_button.add_elements (ArdourButton::Inset);
nudge_forward_button.set_image(::get_icon("nudge_right")); nudge_forward_button.set_image(::get_icon("nudge_right"));
nudge_backward_button.set_name ("zoom button"); nudge_backward_button.set_name ("nudge button");
nudge_backward_button.add_elements (ArdourButton::FlatFace); nudge_backward_button.add_elements (ArdourButton::Inset);
nudge_backward_button.set_image(::get_icon("nudge_left")); nudge_backward_button.set_image(::get_icon("nudge_left"));
fade_context_menu.set_name ("ArdourContextMenu"); fade_context_menu.set_name ("ArdourContextMenu");
@ -2255,6 +2269,10 @@ Editor::set_state (const XMLNode& node, int /*version*/)
reset_zoom (samples_per_pixel); 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"))) { if ((prop = node.property ("snap-to"))) {
set_snap_to ((SnapType) string_2_enum (prop->value(), _snap_type)); 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-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 ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
node->add_property ("edit-point", enum_2_string (_edit_point)); 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 ()); snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
node->add_property ("playhead", buf); node->add_property ("playhead", buf);
@ -2851,15 +2871,21 @@ Editor::setup_toolbar ()
mouse_mode_hbox->set_spacing (2); mouse_mode_hbox->set_spacing (2);
mouse_mode_hbox->pack_start (smart_mode_button, false, false); 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_move_button, false, false);
mouse_mode_hbox->pack_start (mouse_select_button, false, false); mouse_mode_hbox->pack_start (mouse_select_button, false, false);
mouse_mode_hbox->pack_start (mouse_zoom_button, false, false); mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
mouse_mode_hbox->pack_start (mouse_timefx_button, false, false); if (!ARDOUR::Profile->get_trx()) {
mouse_mode_hbox->pack_start (mouse_audition_button, false, false); mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
mouse_mode_hbox->pack_start (mouse_draw_button, false, false); mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
mouse_mode_hbox->pack_start (internal_edit_button, false, false, 8); 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); mouse_mode_vbox->pack_start (*mouse_mode_hbox);
@ -2878,7 +2904,9 @@ Editor::setup_toolbar ()
set_popdown_strings (edit_mode_selector, edit_mode_strings); set_popdown_strings (edit_mode_selector, edit_mode_strings);
edit_mode_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::edit_mode_selection_done)); edit_mode_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::edit_mode_selection_done));
mode_box->pack_start (edit_mode_selector, false, false); if (!ARDOUR::Profile->get_trx()) {
mode_box->pack_start (edit_mode_selector, false, false);
}
mode_box->pack_start (*mouse_mode_box, false, false); mode_box->pack_start (*mouse_mode_box, false, false);
_mouse_mode_tearoff = manage (new TearOff (*mode_box)); _mouse_mode_tearoff = manage (new TearOff (*mode_box));
@ -2906,21 +2934,21 @@ Editor::setup_toolbar ()
RefPtr<Action> act; RefPtr<Action> act;
zoom_in_button.set_name ("zoom button"); 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_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
zoom_in_button.set_image(::get_icon ("zoom_in")); zoom_in_button.set_image(::get_icon ("zoom_in"));
act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in")); act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
zoom_in_button.set_related_action (act); zoom_in_button.set_related_action (act);
zoom_out_button.set_name ("zoom button"); 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_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
zoom_out_button.set_image(::get_icon ("zoom_out")); zoom_out_button.set_image(::get_icon ("zoom_out"));
act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out")); act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
zoom_out_button.set_related_action (act); zoom_out_button.set_related_action (act);
zoom_out_full_button.set_name ("zoom button"); 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_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
zoom_out_full_button.set_image(::get_icon ("zoom_full")); zoom_out_full_button.set_image(::get_icon ("zoom_full"));
act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session")); 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); set_popdown_strings (zoom_focus_selector, zoom_focus_strings);
zoom_focus_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done)); zoom_focus_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done));
_zoom_box.pack_start (zoom_out_button, false, false); if (!ARDOUR::Profile->get_trx()) {
_zoom_box.pack_start (zoom_in_button, false, false); _zoom_box.pack_start (zoom_out_button, false, false);
_zoom_box.pack_start (zoom_out_full_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); _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 */ /* 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.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_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
tav_expand_button.set_size_request (-1, 20); tav_expand_button.set_size_request (-1, 20);
tav_expand_button.set_image(::get_icon ("tav_exp")); tav_expand_button.set_image(::get_icon ("tav_exp"));
@ -2946,26 +2982,31 @@ Editor::setup_toolbar ()
tav_expand_button.set_related_action (act); tav_expand_button.set_related_action (act);
tav_shrink_button.set_name ("zoom button"); 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_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
tav_shrink_button.set_size_request (-1, 20); tav_shrink_button.set_size_request (-1, 20);
tav_shrink_button.set_image(::get_icon ("tav_shrink")); tav_shrink_button.set_image(::get_icon ("tav_shrink"));
act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks")); act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
tav_shrink_button.set_related_action (act); 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_shrink_button);
_zoom_box.pack_start (tav_expand_button); _zoom_box.pack_start (tav_expand_button);
_zoom_tearoff = manage (new TearOff (_zoom_box)); 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),
&_zoom_tearoff->tearoff_window())); _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
_zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), &_zoom_tearoff->tearoff_window()));
&_zoom_tearoff->tearoff_window(), 0)); _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
_zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), &_zoom_tearoff->tearoff_window(), 0));
&_zoom_tearoff->tearoff_window())); _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
_zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), &_zoom_tearoff->tearoff_window()));
&_zoom_tearoff->tearoff_window(), 0)); _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_spacing (2);
snap_box.set_border_width (2); snap_box.set_border_width (2);
@ -3029,15 +3070,19 @@ Editor::setup_toolbar ()
toolbar_hbox.set_border_width (1); toolbar_hbox.set_border_width (1);
toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false); toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
toolbar_hbox.pack_start (*_zoom_tearoff, false, false); if (!ARDOUR::Profile->get_trx()) {
toolbar_hbox.pack_start (*_tools_tearoff, false, false); toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
toolbar_hbox.pack_start (*_tools_tearoff, false, false);
}
hbox->pack_start (snap_box, false, false); if (!ARDOUR::Profile->get_trx()) {
if (!Profile->get_small_screen()) { hbox->pack_start (snap_box, false, false);
hbox->pack_start (*nudge_box, false, false); if (!Profile->get_small_screen()) {
} else { hbox->pack_start (*nudge_box, false, false);
ARDOUR_UI::instance()->editor_transport_box().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->pack_start (panic_box, false, false);
hbox->show_all (); hbox->show_all ();
@ -3054,6 +3099,81 @@ Editor::setup_toolbar ()
toolbar_frame.add (_toolbar_viewport); 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 void
Editor::setup_tooltips () 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 (zoom_focus_selector, _("Zoom focus"));
ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks")); 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 (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_type_selector, _("Snap/Grid Units"));
ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode")); ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point")); 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 void
Editor::zoom_focus_selection_done () 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 bool
Editor::edit_controls_button_release (GdkEventButton* ev) 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()) && if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) &&
(_mouse_mode_tearoff->torn_off() || !_mouse_mode_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); top_hbox.remove (toolbar_frame);
} }
} }
@ -3952,7 +4158,9 @@ Editor::update_tearoff_visibility()
bool visible = Config->get_keep_tearoffs(); bool visible = Config->get_keep_tearoffs();
_mouse_mode_tearoff->set_visible (visible); _mouse_mode_tearoff->set_visible (visible);
_tools_tearoff->set_visible (visible); _tools_tearoff->set_visible (visible);
_zoom_tearoff->set_visible (visible); if (_zoom_tearoff) {
_zoom_tearoff->set_visible (visible);
}
} }
void void
@ -4291,35 +4499,45 @@ Editor::idle_visual_changer ()
pending_visual_change.idle_handler_id = -1; pending_visual_change.idle_handler_id = -1;
pending_visual_change.being_handled = true; 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; 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 (); double const last_time_origin = horizontal_position ();
if (vc.pending & VisualChange::ZoomLevel) {
if (p & VisualChange::ZoomLevel) { set_samples_per_pixel (vc.samples_per_pixel);
set_samples_per_pixel (pending_visual_change.samples_per_pixel);
compute_fixed_ruler_scale (); compute_fixed_ruler_scale ();
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin; ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end; 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); 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); current_bbt_points_begin, current_bbt_points_end);
update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end); update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
update_video_timeline(); update_video_timeline();
} }
if (p & VisualChange::TimeOrigin) { if (vc.pending & VisualChange::TimeOrigin) {
set_horizontal_position (pending_visual_change.time_origin / samples_per_pixel); set_horizontal_position (vc.time_origin / samples_per_pixel);
} }
if (p & VisualChange::YOrigin) { if (vc.pending & VisualChange::YOrigin) {
vertical_adjustment.set_value (pending_visual_change.y_origin); vertical_adjustment.set_value (vc.y_origin);
} }
if (last_time_origin == horizontal_position ()) { if (last_time_origin == horizontal_position ()) {
@ -4328,14 +4546,11 @@ Editor::idle_visual_changer ()
redisplay_tempo (true); redisplay_tempo (true);
} }
if (!(p & VisualChange::ZoomLevel)) { if (!(vc.pending & VisualChange::ZoomLevel)) {
update_video_timeline(); update_video_timeline();
} }
_summary->set_overlays_dirty (); _summary->set_overlays_dirty ();
pending_visual_change.being_handled = false;
return 0; /* this is always a one-shot call */
} }
struct EditorOrderTimeAxisSorter { struct EditorOrderTimeAxisSorter {

View file

@ -177,6 +177,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void set_internal_edit (bool yn); void set_internal_edit (bool yn);
bool toggle_internal_editing_from_double_click (GdkEvent*); 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 foreach_time_axis_view (sigc::slot<void,TimeAxisView&>);
void add_to_idle_resize (TimeAxisView*, int32_t); 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. 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 /* pixel can be less than zero when motion events
are processed. since we've already run the world->canvas 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 { double sample_to_pixel (framepos_t sample) const {
return sample / samples_per_pixel; return sample / samples_per_pixel;
} }
@ -345,9 +350,10 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void show_window (); void show_window ();
void ensure_time_axis_view_is_visible (const TimeAxisView& tav);
void scroll_tracks_down_line (); void scroll_tracks_down_line ();
void scroll_tracks_up_line (); void scroll_tracks_up_line ();
bool scroll_up_one_track ();
bool scroll_down_one_track ();
void prepare_for_cleanup (); void prepare_for_cleanup ();
void finish_cleanup (); void finish_cleanup ();
@ -408,7 +414,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
return _drags; 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; } Gdk::Cursor* get_canvas_cursor () const { return current_canvas_cursor; }
void set_canvas_cursor (Gdk::Cursor*, bool save=false); 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_time_bars_canvas () const;
ArdourCanvas::GtkCanvasViewport* get_track_canvas () const; ArdourCanvas::GtkCanvasViewport* get_track_canvas () const;
void override_visible_track_count ();
protected: protected:
void map_transport_state (); 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 */ /* The group used for region motion. Sits on top of _trackview_group */
ArdourCanvas::Group* _region_motion_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 { enum RulerType {
ruler_metric_timecode = 0, ruler_metric_timecode = 0,
ruler_metric_bbt = 1, ruler_metric_bbt = 1,
@ -1022,6 +1036,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
static int _idle_visual_changer (void *arg); static int _idle_visual_changer (void *arg);
int idle_visual_changer (); int idle_visual_changer ();
void visual_changer (const VisualChange&);
void ensure_visual_change_idle_handler (); void ensure_visual_change_idle_handler ();
/* track views */ /* track views */
@ -1440,7 +1455,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
Gtk::Allocation _canvas_viewport_allocation; Gtk::Allocation _canvas_viewport_allocation;
void track_canvas_viewport_allocate (Gtk::Allocation alloc); 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_drag_motion (Glib::RefPtr<Gdk::DragContext> const &, int, int, guint);
bool track_canvas_key_press (GdkEventKey *); bool track_canvas_key_press (GdkEventKey *);
bool track_canvas_key_release (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_expand_button;
ArdourButton tav_shrink_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_clock_vbox;
Gtk::VBox toolbar_selection_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::VBox automation_box;
Gtk::Button automation_mode_button; Gtk::Button automation_mode_button;
Gtk::ComboBoxText edit_mode_selector; //edit mode menu stuff
Gtk::ComboBoxText edit_mode_selector;
void build_edit_mode_menu ();
Gtk::VBox edit_mode_box; Gtk::VBox edit_mode_box;
std::vector<std::string> edit_mode_strings; 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 (); void edit_mode_selection_done ();
Gtk::ComboBoxText snap_type_selector; Gtk::ComboBoxText snap_type_selector;
void build_snap_type_menu ();
Gtk::ComboBoxText snap_mode_selector; Gtk::ComboBoxText snap_mode_selector;
void build_snap_mode_menu ();
Gtk::HBox snap_box; Gtk::HBox snap_box;
std::vector<std::string> snap_type_strings; 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::ComboBoxText zoom_focus_selector;
Gtk::VBox zoom_focus_box; Gtk::VBox zoom_focus_box;
void build_zoom_focus_menu ();
std::vector<std::string> zoom_focus_strings; std::vector<std::string> zoom_focus_strings;
void zoom_focus_selection_done (); void zoom_focus_selection_done ();
@ -1722,22 +1747,15 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
/* autoscrolling */ /* autoscrolling */
bool autoscroll_active; sigc::connection autoscroll_connection;
int autoscroll_timeout_tag; bool autoscroll_horizontal_allowed;
int autoscroll_x; bool autoscroll_vertical_allowed;
int autoscroll_y; uint32_t autoscroll_cnt;
int last_autoscroll_x; Gtk::Widget* autoscroll_widget;
int last_autoscroll_y; ArdourCanvas::Rect autoscroll_boundary;
uint32_t autoscroll_cnt;
framecnt_t autoscroll_x_distance;
double autoscroll_y_distance;
bool _autoscroll_fudging;
int autoscroll_fudge_threshold () const;
static gint _autoscroll_canvas (void *);
bool autoscroll_canvas (); 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 (); void stop_canvas_autoscroll ();
/* trimming */ /* trimming */
@ -1945,6 +1963,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
Editing::EditPoint _edit_point; Editing::EditPoint _edit_point;
Gtk::ComboBoxText edit_point_selector; Gtk::ComboBoxText edit_point_selector;
void build_edit_point_menu();
void set_edit_point_preference (Editing::EditPoint ep, bool force = false); void set_edit_point_preference (Editing::EditPoint ep, bool force = false);
void cycle_edit_point (bool with_marker); void cycle_edit_point (bool with_marker);

View file

@ -414,49 +414,49 @@ Editor::register_actions ()
smart_mode_action = Glib::RefPtr<ToggleAction>::cast_static (act); smart_mode_action = Glib::RefPtr<ToggleAction>::cast_static (act);
smart_mode_button.set_related_action (smart_mode_action); smart_mode_button.set_related_action (smart_mode_action);
smart_mode_button.set_text (_("Smart")); 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"); 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)); 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_related_action (act);
mouse_move_button.set_image (::get_icon("tool_object")); 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"); 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)); 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_related_action (act);
mouse_select_button.set_image (::get_icon("tool_range")); 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"); 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)); 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_related_action (act);
mouse_draw_button.set_image (::get_icon("midi_tool_pencil")); 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"); 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)); 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_related_action (act);
mouse_gain_button.set_image (::get_icon("tool_gain")); 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"); 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)); 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_related_action (act);
mouse_zoom_button.set_image (::get_icon("tool_zoom")); 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"); 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)); 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_related_action (act);
mouse_audition_button.set_image (::get_icon("tool_audition")); 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"); 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)); 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_related_action (act);
mouse_timefx_button.set_image (::get_icon("tool_stretch")); 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"); 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)); 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)); 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_related_action (act);
internal_edit_button.set_image (::get_icon("tool_note")); 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"); internal_edit_button.set_name ("mouse mode button");
RadioAction::Group edit_point_group; RadioAction::Group edit_point_group;
@ -1650,7 +1650,9 @@ Editor::parameter_changed (std::string p)
} else if (p == "timecode-offset" || p == "timecode-offset-negative") { } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
update_just_timecode (); update_just_timecode ();
} else if (p == "show-zoom-tools") { } else if (p == "show-zoom-tools") {
_zoom_tearoff->set_visible (Config->get_show_zoom_tools(), true); if (_zoom_tearoff) {
_zoom_tearoff->set_visible (Config->get_show_zoom_tools(), true);
}
} else if (p == "sound-midi-notes") { } else if (p == "sound-midi-notes") {
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("sound-midi-notes")); Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("sound-midi-notes"));

View file

@ -84,7 +84,7 @@ Editor::initialize_canvas ()
// logo_item->property_width_in_pixels() = true; // logo_item->property_width_in_pixels() = true;
// logo_item->property_height_set() = true; // logo_item->property_height_set() = true;
// logo_item->property_width_set() = true; // logo_item->property_width_set() = true;
logo_item->show (); // logo_item->show ();
} }
/*a group to hold global rects like punch/loop indicators */ /*a group to hold global rects like punch/loop indicators */
@ -192,12 +192,10 @@ Editor::initialize_canvas ()
// used to show zoom mode active zooming // 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 = new ArdourCanvas::Rectangle (_track_canvas->root(), ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
zoom_rect->hide(); zoom_rect->hide();
zoom_rect->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_zoom_rect_event), (ArdourCanvas::Item*) 0)); zoom_rect->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_zoom_rect_event), (ArdourCanvas::Item*) 0));
// used as rubberband rect // used as rubberband rect
rubberband_rect = new ArdourCanvas::Rectangle (_trackview_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0)); rubberband_rect = new ArdourCanvas::Rectangle (_trackview_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
rubberband_rect->hide(); rubberband_rect->hide();
tempo_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_tempo_bar_event), tempo_bar)); 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) { if (logo_item) {
logo_item->lower_to_bottom (); 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_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)); _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 (); track_canvas_viewport_size_allocated ();
} }
bool void
Editor::track_canvas_viewport_size_allocated () Editor::track_canvas_viewport_size_allocated ()
{ {
bool height_changed = _visible_canvas_height != _canvas_viewport_allocation.get_height(); 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); vertical_adjustment.set_value (_full_canvas_height - _visible_canvas_height);
} }
set_visible_track_count (_visible_track_count);
} }
update_fixed_rulers(); update_fixed_rulers();
redisplay_tempo (false); redisplay_tempo (false);
_summary->set_overlays_dirty (); _summary->set_overlays_dirty ();
return false;
} }
void void
@ -315,12 +323,24 @@ Editor::reset_controls_layout_width ()
void void
Editor::reset_controls_layout_height (int32_t h) 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) /* 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; controls_layout.property_height() = h;
/* size request is set elsewhere, see ::track_canvas_allocate() */
} }
bool bool
@ -448,245 +468,265 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
context->drag_finish (true, false, time); 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_horiz true to allow horizontal autoscroll, otherwise false.
* *
* @param allow_vert true to allow vertical 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 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 ()) { if (!Config->get_autoscroll_editor ()) {
return; return;
} }
ArdourCanvas::Rect scrolling_boundary;
Gtk::Allocation alloc;
bool startit = false; if (from_headers) {
alloc = controls_layout.get_allocation ();
/* Work out the distance between the right hand edge of the trackview and the edge of } else {
the monitor that it is on. alloc = _track_canvas_viewport->get_allocation ();
*/
/* the effective width of the autoscroll boundary so
Glib::RefPtr<Gdk::Window> gdk_window = get_window (); that we start scrolling before we hit the edge.
Gdk::Rectangle window_rect;
gdk_window->get_frame_extents (window_rect); this helps when the window is slammed up against the
right edge of the screen, making it hard to scroll
effectively.
*/
if (alloc.get_width() > 20) {
alloc.set_width (alloc.get_width() - 20);
alloc.set_x (alloc.get_x() + 10);
}
}
Glib::RefPtr<Gdk::Screen> screen = get_screen (); scrolling_boundary = ArdourCanvas::Rect (alloc.get_x(), alloc.get_y(),
Gdk::Rectangle root_rect; alloc.get_x() + alloc.get_width(),
screen->get_root_window()->get_frame_extents (root_rect); alloc.get_y() + alloc.get_height());
int x, y;
Gdk::ModifierType mask;
Gtk::Allocation editor_list = _the_notebook.get_allocation (); get_window()->get_pointer (x, y, mask);
framecnt_t distance = pixel_to_sample (root_rect.get_x() + root_rect.get_width() - window_rect.get_x() - window_rect.get_width()); if ((allow_horiz && (x < scrolling_boundary.x0 || x >= scrolling_boundary.x1)) ||
if (_the_notebook.is_visible ()) { (allow_vert && (y < scrolling_boundary.y0 || y >= scrolling_boundary.y1))) {
distance += pixel_to_sample (editor_list.get_width()); start_canvas_autoscroll (allow_horiz, allow_vert, scrolling_boundary);
} }
/* 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 (autoscroll_active && ((autoscroll_x != last_autoscroll_x) || (autoscroll_y != last_autoscroll_y) || (autoscroll_x == 0 && autoscroll_y == 0))) {
stop_canvas_autoscroll ();
}
if (startit && autoscroll_timeout_tag < 0) {
start_canvas_autoscroll (autoscroll_x, autoscroll_y);
}
last_autoscroll_x = autoscroll_x;
last_autoscroll_y = autoscroll_y;
} }
gint bool
Editor::_autoscroll_canvas (void *arg) Editor::autoscroll_active () const
{ {
return ((Editor *) arg)->autoscroll_canvas (); return autoscroll_connection.connected ();
} }
bool bool
Editor::autoscroll_canvas () Editor::autoscroll_canvas ()
{ {
framepos_t new_frame; int x, y;
framepos_t limit = max_framepos - current_page_samples(); Gdk::ModifierType mask;
double new_pixel; 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) { VisualChange vc;
autoscroll_x_distance = (_drags->current_pointer_frame() - (leftmost_frame + current_page_samples())) / 3;
if (_autoscroll_fudging) { if (autoscroll_horizontal_allowed) {
autoscroll_x_distance += autoscroll_fudge_threshold () / 3;
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;
} }
} else if (autoscroll_x < 0) {
autoscroll_x_distance = (leftmost_frame - _drags->current_pointer_frame()) / 3;
no_stop = true;
} else if (x < autoscroll_boundary.x0) {
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;
}
no_stop = true;
}
if (new_frame != leftmost_frame) {
vc.time_origin = new_frame;
vc.add (VisualChange::TimeOrigin);
} }
} }
if (autoscroll_y_distance != 0) { if (autoscroll_vertical_allowed) {
if (autoscroll_y > 0) {
autoscroll_y_distance = (_drags->current_pointer_y() - _visible_canvas_height) / 3; const double vertical_pos = vertical_adjustment.get_value();
} else if (autoscroll_y < 0) { double new_pixel = vertical_pos;
const int speed_factor = 20;
autoscroll_y_distance = (vertical_adjustment.get_value () - _drags->current_pointer_y()) / 3; /* vertical */
}
}
if (autoscroll_x < 0) {
if (leftmost_frame < autoscroll_x_distance) {
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; 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 ();
}
} else if (y > autoscroll_boundary.y1) {
if (autoscroll_cnt && (autoscroll_cnt % speed_factor == 0)) {
y_motion = scroll_down_one_track ();
}
}
no_stop = true;
} }
if ((new_frame == 0 || new_frame == limit) && (new_pixel == 0 || new_pixel == DBL_MAX)) { if (vc.pending) {
/* we are done */
/* 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)
*/
GdkEventMotion ev;
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 */
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 if (no_stop) {
/* not changing visual state but pointer is outside the scrolling boundary
* so we still need to deliver a fake motion event
*/
GdkEventMotion ev;
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 false;
} }
if (new_frame != leftmost_frame) {
reset_x_origin (new_frame);
}
if (new_pixel != vertical_pos) {
vertical_adjustment.set_value (new_pixel);
}
/* fake an event. */
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));
ev.x = d.x;
ev.y = d.y;
motion_handler (0, (GdkEvent*) &ev, true);
autoscroll_cnt++; autoscroll_cnt++;
if (autoscroll_cnt == 1) { return true; /* call me again */
}
/* connect the timeout so that we get called repeatedly */
autoscroll_timeout_tag = g_idle_add ( _autoscroll_canvas, this);
return false;
}
return true;
}
void 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; return;
} }
stop_canvas_autoscroll (); 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_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 (); autoscroll_canvas ();
/* scroll again at very very roughly 30FPS */
autoscroll_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::autoscroll_canvas), 30);
} }
void void
Editor::stop_canvas_autoscroll () Editor::stop_canvas_autoscroll ()
{ {
if (autoscroll_timeout_tag >= 0) { autoscroll_connection.disconnect ();
g_source_remove (autoscroll_timeout_tag);
autoscroll_timeout_tag = -1;
}
autoscroll_active = false;
} }
bool bool
@ -709,19 +749,26 @@ Editor::entered_track_canvas (GdkEventCrossing */*ev*/)
} }
void 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 begin = tav.y_position();
double v = vertical_adjustment.get_value (); 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 */ /* try to put the TimeAxisView roughly central */
if (begin >= _visible_canvas_height/2.0) { if (begin >= _visible_canvas_height/2.0) {
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 */ /** Called when the main vertical_adjustment has changed */
@ -748,8 +795,6 @@ Editor::set_horizontal_position (double p)
} }
update_video_timeline(); update_video_timeline();
HorizontalPositionChanged (); /* EMIT SIGNAL */
} }
void void

View file

@ -1009,6 +1009,13 @@ Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
return typed_event (item, event, NoteItem); return typed_event (item, event, NoteItem);
} }
bool
Editor::canvas_bottom_rect_event (GdkEvent* event)
{
cerr << "CBR event, type " << event << endl;
return true;
}
bool bool
Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const& context, int x, int y, guint time) Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const& context, int x, int y, guint time)
{ {

View file

@ -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 (event->motion.state & Gdk::BUTTON1_MASK || event->motion.state & Gdk::BUTTON2_MASK) {
if (!from_autoscroll) { if (!from_autoscroll) {
bool const moving_left = _drags->current_pointer_x() < _last_pointer_x; _editor->maybe_autoscroll (true, allow_vertical_autoscroll (), false);
bool const moving_up = _drags->current_pointer_y() < _last_pointer_y;
_editor->maybe_autoscroll (true, allow_vertical_autoscroll (), moving_left, moving_up);
} }
motion (event, _move_threshold_passed != old_move_threshold_passed); 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_x = _drags->current_pointer_x ();
_last_pointer_frame = adjusted_current_frame (event); _last_pointer_y = _drags->current_pointer_y ();
_last_pointer_frame = adjusted_current_frame (event);
}
return true; return true;
} }
@ -3912,9 +3912,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
break; break;
} }
if (event->button.x >= _editor->horizontal_position() + _editor->_visible_canvas_width) { _editor->maybe_autoscroll (true, false, false);
_editor->start_canvas_autoscroll (1, 0);
}
if (start != end) { if (start != end) {
switch (_operation) { 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->maybe_autoscroll (true, false, false);
_editor->start_canvas_autoscroll (1, 0);
}
if (start != end) { if (start != end) {
_editor->temp_location->set (start, end); _editor->temp_location->set (start, end);

View file

@ -179,12 +179,12 @@ Editor::canvas_event_sample (GdkEvent const * event, double* pcx, double* pcy) c
*pcy = y; *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), position is negative (as can be the case with motion events in particular),
the frame location is always positive. the frame location is always positive.
*/ */
return pixel_to_sample (x); return pixel_to_sample_from_event (x);
} }
Gdk::Cursor* Gdk::Cursor*
@ -2914,8 +2914,6 @@ Editor::set_canvas_cursor_for_region_view (double x, RegionView* rv)
return; return;
} }
assert (rv);
ArdourCanvas::Group* g = rv->get_canvas_group (); ArdourCanvas::Group* g = rv->get_canvas_group ();
ArdourCanvas::Group* p = g->parent (); ArdourCanvas::Group* p = g->parent ();
@ -2927,21 +2925,28 @@ Editor::set_canvas_cursor_for_region_view (double x, RegionView* rv)
assert (item_bbox); assert (item_bbox);
ArdourCanvas::Rect parent_bbox = g->item_to_parent (item_bbox.get ()); ArdourCanvas::Rect parent_bbox = g->item_to_parent (item_bbox.get ());
/* Halfway across the region */ /* First or last 10% of region is used for trimming, if the whole
double const h = (parent_bbox.x0 + parent_bbox.x1) / 2; region is wider than 20 pixels at the current zoom level.
*/
Trimmable::CanTrim ct = rv->region()->can_trim (); double const w = parent_bbox.width();
if (x <= h) {
if (ct & Trimmable::FrontTrimEarlier) { if (w > 20.0 && x >= parent_bbox.x0 && x < parent_bbox.x1) {
set_canvas_cursor (_cursors->left_side_trim, true);
} else { Trimmable::CanTrim ct = rv->region()->can_trim ();
set_canvas_cursor (_cursors->left_side_trim_right_only, true);
} if (((x - parent_bbox.x0) / w) < 0.10) {
} else { if (ct & Trimmable::FrontTrimEarlier) {
if (ct & Trimmable::EndTrimLater) { set_canvas_cursor (_cursors->left_side_trim, true);
set_canvas_cursor (_cursors->right_side_trim, true); } else {
} else { set_canvas_cursor (_cursors->left_side_trim_right_only, true);
set_canvas_cursor (_cursors->right_side_trim_left_only, true); }
} else if (((parent_bbox.x1 - x) / w) < 0.10) {
if (ct & Trimmable::EndTrimLater) {
set_canvas_cursor (_cursors->right_side_trim, true);
} else {
set_canvas_cursor (_cursors->right_side_trim_left_only, true);
}
} }
} }
} }

View file

@ -1276,6 +1276,69 @@ Editor::scroll_tracks_up_line ()
reset_y_origin (vertical_adjustment.get_value() - 60); 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 */ /* ZOOM */
void void
@ -4755,12 +4818,17 @@ Editor::fork_region ()
MidiRegionView* const mrv = dynamic_cast<MidiRegionView*>(*r); MidiRegionView* const mrv = dynamic_cast<MidiRegionView*>(*r);
if (mrv) { if (mrv) {
boost::shared_ptr<Playlist> playlist = mrv->region()->playlist(); try {
boost::shared_ptr<MidiRegion> newregion = mrv->midi_region()->clone (); boost::shared_ptr<Playlist> playlist = mrv->region()->playlist();
boost::shared_ptr<MidiSource> new_source = _session->create_midi_source_by_stealing_name (mrv->midi_view()->track());
playlist->clear_changes (); boost::shared_ptr<MidiRegion> newregion = mrv->midi_region()->clone (new_source);
playlist->replace_region (mrv->region(), newregion, mrv->region()->position());
_session->add_command(new StatefulDiffCommand (playlist)); 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; r = tmp;
@ -6432,12 +6500,13 @@ Editor::remove_tracks ()
for (TrackSelection::iterator x = ts.begin(); x != ts.end(); ++x) { for (TrackSelection::iterator x = ts.begin(); x != ts.end(); ++x) {
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*x); RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*x);
if (rtv) { if (!rtv) {
if (rtv->is_track()) { continue;
ntracks++; }
} else { if (rtv->is_track()) {
nbusses++; ntracks++;
} } else {
nbusses++;
} }
routes.push_back (rtv->_route); routes.push_back (rtv->_route);

View file

@ -222,6 +222,7 @@ EditorRoutes::EditorRoutes (Editor* e)
_display.set_headers_visible (true); _display.set_headers_visible (true);
_display.get_selection()->set_mode (SELECTION_SINGLE); _display.get_selection()->set_mode (SELECTION_SINGLE);
_display.get_selection()->set_select_function (sigc::mem_fun (*this, &EditorRoutes::selection_filter)); _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_reorderable (true);
_display.set_name (X_("EditGroupList")); _display.set_name (X_("EditGroupList"));
_display.set_rules_hint (true); _display.set_rules_hint (true);
@ -1292,27 +1293,46 @@ EditorRoutes::button_press (GdkEventButton* ev)
//Scroll editor canvas to selected track //Scroll editor canvas to selected track
if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
// Get the model row.
Gtk::TreeModel::Row row = *_model->get_iter (path); Gtk::TreeModel::Row row = *_model->get_iter (path);
TimeAxisView *tv = row[_columns.tv]; TimeAxisView *tv = row[_columns.tv];
int y_pos = tv->y_position(); if (tv) {
_editor->ensure_time_axis_view_is_visible (*tv, true);
//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);
} }
} }
return false; 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 bool
EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const&, bool /*selected*/) EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const&, bool /*selected*/)
{ {

View file

@ -98,6 +98,7 @@ private:
void show_all_miditracks (); void show_all_miditracks ();
void hide_all_miditracks (); void hide_all_miditracks ();
void show_tracks_with_regions_at_playhead (); void show_tracks_with_regions_at_playhead ();
void selection_changed ();
void display_drag_data_received ( void display_drag_data_received (
Glib::RefPtr<Gdk::DragContext> const &, gint, gint, Gtk::SelectionData const &, guint, guint Glib::RefPtr<Gdk::DragContext> const &, gint, gint, Gtk::SelectionData const &, guint, guint

View file

@ -1608,7 +1608,7 @@ EngineControl::EngineControl ()
uint32_t il = (uint32_t) input_latency.get_value (); uint32_t il = (uint32_t) input_latency.get_value ();
uint32_t ol = (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. will be clean of any existing latency measures.
*/ */

View file

@ -163,6 +163,7 @@
; (gtk_accel_path "<Actions>/Snap/snap-to-eighths" "") ; (gtk_accel_path "<Actions>/Snap/snap-to-eighths" "")
(gtk_accel_path "<Actions>/Editor/select-all-after-playhead" "<@TERTIARY@><@PRIMARY@>p") (gtk_accel_path "<Actions>/Editor/select-all-after-playhead" "<@TERTIARY@><@PRIMARY@>p")
(gtk_accel_path "<Actions>/Common/ToggleMaximalEditor" "F11") (gtk_accel_path "<Actions>/Common/ToggleMaximalEditor" "F11")
(gtk_accel_path "<Actions>/Common/ToggleMaximalMixer" "F12")
; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileLength" "") ; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileLength" "")
; (gtk_accel_path "<Actions>/Editor/Timecode" "") ; (gtk_accel_path "<Actions>/Editor/Timecode" "")
; (gtk_accel_path "<Actions>/Transport/PlaySelection" "") ; (gtk_accel_path "<Actions>/Transport/PlaySelection" "")

View file

@ -1022,6 +1022,7 @@ GainMeter::get_gm_width ()
{ {
Gtk::Requisition sz; Gtk::Requisition sz;
int min_w = 0; int min_w = 0;
sz.width = 0;
meter_metric_area.size_request (sz); meter_metric_area.size_request (sz);
min_w += sz.width; min_w += sz.width;
level_meter->size_request (sz); level_meter->size_request (sz);

View file

@ -57,6 +57,9 @@
#include "i18n.h" #include "i18n.h"
#ifdef COMPILER_MSVC
#include <fcntl.h> // Needed for '_fmode'
#endif
using namespace std; using namespace std;
using namespace Gtk; 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[]); extern int windows_vst_gui_init (int* argc, char** argv[]);
/* this is called from the entry point of a wine-compiled /* 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. as a shared library.
*/ */
extern "C" { extern "C" {
int ardour_main (int argc, char *argv[]) int ardour_main (int argc, char *argv[])
#else #else
int main (int argc, char *argv[]) int main (int argc, char *argv[])
#endif #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); 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()) { if (!Glib::thread_supported()) {
Glib::thread_init(); Glib::thread_init();
@ -164,15 +182,15 @@ int main (int argc, char *argv[])
gtk_set_locale (); gtk_set_locale ();
#endif #endif
#ifdef WINDOWS_VST_SUPPORT #if (defined WINDOWS_VST_SUPPORT && !defined PLATFORM_WINDOWS)
/* this does some magic that is needed to make GTK and Wine's own /* this does some magic that is needed to make GTK and X11 client interact properly.
X11 client interact properly. * the platform dependent code is in windows_vst_plugin_ui.cc
*/ */
windows_vst_gui_init (&argc, &argv); windows_vst_gui_init (&argc, &argv);
#endif #endif
#ifdef ENABLE_NLS #ifdef ENABLE_NLS
cerr << "bnd txt domain [" << PACKAGE << "] to " << localedir << endl; cerr << "bind txt domain [" << PACKAGE << "] to " << localedir << endl;
(void) bindtextdomain (PACKAGE, localedir); (void) bindtextdomain (PACKAGE, localedir);
/* our i18n translations are all in UTF-8, so make sure /* our i18n translations are all in UTF-8, so make sure
@ -198,6 +216,16 @@ int main (int argc, char *argv[])
#endif #endif
if (parse_opts (argc, argv)) { 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); exit (1);
} }
@ -260,7 +288,6 @@ int main (int argc, char *argv[])
return 0; return 0;
} }
#ifdef WINDOWS_VST_SUPPORT #if (defined WINDOWS_VST_SUPPORT && !defined PLATFORM_WINDOWS)
} // end of extern C block } // end of extern "C" block
#endif #endif

View file

@ -164,7 +164,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &
void void
MidiRegionView::parameter_changed (std::string const & p) 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) { if (_enable_display) {
redisplay_model(); redisplay_model();
} }

View file

@ -1521,8 +1521,7 @@ MidiTimeAxisView::add_region (framepos_t pos, framecnt_t length, bool commit)
real_editor->snap_to (pos, 0); real_editor->snap_to (pos, 0);
boost::shared_ptr<Source> src = _session->create_midi_source_for_session ( boost::shared_ptr<Source> src = _session->create_midi_source_by_stealing_name (view()->trackview().track());
view()->trackview().track().get(), view()->trackview().track()->name());
PropertyList plist; PropertyList plist;
plist.add (ARDOUR::Properties::start, 0); plist.add (ARDOUR::Properties::start, 0);

View file

@ -133,7 +133,7 @@ MissingFileDialog::add_chosen ()
break; break;
} }
split (str, dirs, ':'); split (str, dirs, G_SEARCHPATH_SEPARATOR);
newdir = chooser.get_filename (); newdir = chooser.get_filename ();
@ -144,7 +144,7 @@ MissingFileDialog::add_chosen ()
} }
if (!str.empty()) { if (!str.empty()) {
str += ':'; str += G_SEARCHPATH_SEPARATOR;
} }
str += newdir; str += newdir;

View file

@ -197,7 +197,7 @@ MixerStrip::init ()
button_size_group->add_widget (*monitor_input_button); 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); top_button_table.attach (name_button, 0, 2, 2, 3);
auto_n_io_table.attach (automation_label, 0, 1, 0, 1); auto_n_io_table.attach (automation_label, 0, 1, 0, 1);
automation_label.show(); automation_label.show();

View file

@ -241,6 +241,7 @@ Mixer_UI::Mixer_UI ()
group_display.show(); group_display.show();
_in_group_rebuild_or_clear = false; _in_group_rebuild_or_clear = false;
_maximised = false;
MixerStrip::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::remove_strip, this, _1), gui_context()); 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; return 0;
} }
@ -1604,6 +1618,8 @@ Mixer_UI::get_state (void)
node->add_property ("show-mixer", _visible ? "yes" : "no"); node->add_property ("show-mixer", _visible ? "yes" : "no");
node->add_property ("maximised", _maximised ? "yes" : "no");
return *node; return *node;
} }
@ -1945,3 +1961,26 @@ Mixer_UI::toggle_midi_input_active (bool flip_others)
_session->set_exclusive_input_active (rl, onoff, 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;
}

View file

@ -80,6 +80,9 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
void show_strip (MixerStrip *); void show_strip (MixerStrip *);
void hide_strip (MixerStrip *); void hide_strip (MixerStrip *);
void maximise_mixer_space();
void restore_mixer_space();
void ensure_float (Gtk::Window&); void ensure_float (Gtk::Window&);
MonitorSection* monitor_section() const { return _monitor_section; } 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; bool _following_editor_selection;
void monitor_section_going_away (); void monitor_section_going_away ();
/// true if we are in fullscreen mode
bool _maximised;
}; };
#endif /* __ardour_mixer_ui_h__ */ #endif /* __ardour_mixer_ui_h__ */

View file

@ -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|Editor/toggle-follow-playhead|<@PRIMARY@>f|toggle playhead tracking
@trans|Transport/ToggleFollowEdits|<@TERTIARY@>f|toggle playhead follows edits @trans|Transport/ToggleFollowEdits|<@TERTIARY@>f|toggle playhead follows edits
@wvis|Common/ToggleMaximalEditor|<@PRIMARY@><@SECONDARY@>f|maximise editor space @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 @wvis|Region/show-rhythm-ferret|<@WINDOW@>f|show rhythm ferret window
@mmode|MouseMode/set-mouse-mode-gain|g|region gain mode @mmode|MouseMode/set-mouse-mode-gain|g|region gain mode
@epp|Region/play-selected-regions|h|play selected region(s) @epp|Region/play-selected-regions|h|play selected region(s)

View file

@ -27,6 +27,10 @@
#pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-parameter"
#else #else
#include <process.h> // Needed for 'getpid()' #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 #endif
namespace NSM namespace NSM

View file

@ -266,9 +266,14 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
virtual framecnt_t current_page_samples() const = 0; virtual framecnt_t current_page_samples() const = 0;
virtual double visible_canvas_height () const = 0; virtual double visible_canvas_height () const = 0;
virtual void temporal_zoom_step (bool coarser) = 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_down_line () = 0;
virtual void scroll_tracks_up_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 prepare_for_cleanup () = 0;
virtual void finish_cleanup () = 0; virtual void finish_cleanup () = 0;
virtual void reset_x_origin (framepos_t frame) = 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; virtual void get_equivalent_regions (RegionView* rv, std::vector<RegionView*>&, PBD::PropertyID) const = 0;
sigc::signal<void> ZoomChanged; 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> Realized;
sigc::signal<void,framepos_t> UpdateAllTransportClocks; 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 Gtkmm2ext::TearOff* tools_tearoff () const = 0;
virtual DragManager* drags () 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 void stop_canvas_autoscroll () = 0;
virtual bool autoscroll_active() const = 0;
virtual MouseCursors const * cursors () const = 0; virtual MouseCursors const * cursors () const = 0;
virtual VerboseCursor * verbose_cursor () 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> SnapChanged;
PBD::Signal0<void> MouseModeChanged; 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__ #endif // __gtk_ardour_public_editor_h__

View file

@ -1795,6 +1795,8 @@ RCOptionEditor::RCOptionEditor ()
sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active) sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
)); ));
add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
add_option (_("Audio"), add_option (_("Audio"),
new BoolOption ( new BoolOption (
"auto-analyse-audio", "auto-analyse-audio",
@ -2016,7 +2018,7 @@ RCOptionEditor::RCOptionEditor ()
add_option (_("MIDI"), add_option (_("MIDI"),
new BoolOption ( new BoolOption (
"diplay-first-midi-bank-as-zero", "display-first-midi-bank-as-zero",
_("Display first MIDI bank/program as 0"), _("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::get_first_midi_bank_is_zero),
sigc::mem_fun (*_rc_config, &RCConfiguration::set_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) 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 #ifndef GTKOSX
/* font scaling does nothing with GDK/Quartz */ /* font scaling does nothing with GDK/Quartz */
add_option (S_("Preferences|GUI"), new FontScalingOptions (_rc_config)); 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_("SoloSafe"), _("Solo Safe"));
_mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated")); _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
_mixer_strip_visibility.add (0, X_("Comments"), _("Comments")); _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")); _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
add_option ( add_option (

View file

@ -168,20 +168,20 @@ RegionView::init (Gdk::Color const & basic_color, bool wfd)
if (name_highlight) { if (name_highlight) {
name_highlight->set_data ("regionview", this); 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)); 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); if (frame_handle_start) {
frame_handle_start->set_data ("isleft", (void*) 1); frame_handle_start->set_data ("regionview", this);
frame_handle_start->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_frame_handle_event), frame_handle_start, this)); frame_handle_start->set_data ("isleft", (void*) 1);
frame_handle_start->raise_to_top(); frame_handle_start->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_frame_handle_event), frame_handle_start, this));
} frame_handle_start->raise_to_top();
}
if (frame_handle_end) {
frame_handle_end->set_data ("regionview", this); if (frame_handle_end) {
frame_handle_end->set_data ("isleft", (void*) 0); frame_handle_end->set_data ("regionview", this);
frame_handle_end->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_frame_handle_event), frame_handle_end, this)); frame_handle_end->set_data ("isleft", (void*) 0);
frame_handle_end->raise_to_top(); 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) { if (name_text) {

View file

@ -206,9 +206,10 @@ RouteTimeAxisView::set_route (boost::shared_ptr<Route> rt)
if (!_route->is_master()) { if (!_route->is_master()) {
controls_table.attach (*solo_button, 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0); 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 (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); // 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(*solo_button,_("Solo"));
ARDOUR_UI::instance()->set_tip(*mute_button,_("Mute")); ARDOUR_UI::instance()->set_tip(*mute_button,_("Mute"));
@ -222,9 +223,11 @@ RouteTimeAxisView::set_route (boost::shared_ptr<Route> rt)
label_view (); label_view ();
controls_table.attach (automation_button, 6, 7, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); 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); 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)); _editor.get_selection().tracks.foreach_route_time_axis (boost::bind (&RouteTimeAxisView::set_track_mode, _1, mode, false));
} else { } else {
bool needs_bounce; bool needs_bounce = false;
if (!track()->can_use_mode (mode, needs_bounce)) { if (!track()->can_use_mode (mode, needs_bounce)) {

View file

@ -588,7 +588,7 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
} }
if (!_session->engine().connected()) { if (!_session->engine().connected()) {
MessageDialog msg (_("Not connected to JACK - cannot engage record")); MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
msg.run (); msg.run ();
return true; return true;
} }

View file

@ -103,7 +103,7 @@ SearchPathOption::set_state_from_config ()
clear (); clear ();
path_box.pack_start (session_label); 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) { for (vector<string>::iterator d = dirs.begin(); d != dirs.end(); ++d) {
add_path (*d); add_path (*d);
@ -118,7 +118,7 @@ SearchPathOption::changed ()
for (list<PathEntry*>::iterator p = paths.begin(); p != paths.end(); ++p) { for (list<PathEntry*>::iterator p = paths.begin(); p != paths.end(); ++p) {
if (!str.empty()) { if (!str.empty()) {
str += ':'; str += G_SEARCHPATH_SEPARATOR;
} }
str += (*p)->entry.get_text (); str += (*p)->entry.get_text ();
} }

View file

@ -88,7 +88,7 @@ SessionOptionEditor::SessionOptionEditor (Session* s)
add_option (_("Sync"), new BoolOption ( add_option (_("Sync"), new BoolOption (
"videotimeline-pullup", "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::get_videotimeline_pullup),
sigc::mem_fun (*_session_config, &SessionConfiguration::set_videotimeline_pullup) sigc::mem_fun (*_session_config, &SessionConfiguration::set_videotimeline_pullup)
)); ));

View file

@ -21,6 +21,8 @@
#include "gtk2ardour-config.h" #include "gtk2ardour-config.h"
#endif #endif
#include "i18n.h"
#include <map> #include <map>
#include <cerrno> #include <cerrno>
#include <sstream> #include <sstream>
@ -69,8 +71,6 @@
#include "sfdb_freesound_mootcher.h" #include "sfdb_freesound_mootcher.h"
#include "i18n.h"
using namespace ARDOUR; using namespace ARDOUR;
using namespace PBD; using namespace PBD;
using namespace std; using namespace std;

View file

@ -298,7 +298,7 @@ TimeAxisView::controls_ebox_scroll (GdkEventScroll* ev)
e.stepping_axis_view()->step_height (false); e.stepping_axis_view()->step_height (false);
return true; return true;
} else if (Keyboard::no_modifiers_active (ev->state)) { } else if (Keyboard::no_modifiers_active (ev->state)) {
_editor.scroll_tracks_up_line(); _editor.scroll_up_one_track();
return true; return true;
} }
break; break;
@ -313,7 +313,7 @@ TimeAxisView::controls_ebox_scroll (GdkEventScroll* ev)
e.stepping_axis_view()->step_height (true); e.stepping_axis_view()->step_height (true);
return true; return true;
} else if (Keyboard::no_modifiers_active (ev->state)) { } else if (Keyboard::no_modifiers_active (ev->state)) {
_editor.scroll_tracks_down_line(); _editor.scroll_down_one_track();
return true; return true;
} }
break; break;
@ -370,32 +370,11 @@ TimeAxisView::controls_ebox_motion (GdkEventMotion* ev)
* are pretending that the drag is taking place over the canvas * are pretending that the drag is taking place over the canvas
* (which perhaps in the glorious future, when track headers * (which perhaps in the glorious future, when track headers
* and the canvas are unified, will actually be true.) * 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; _editor.maybe_autoscroll (false, true, true);
controls_ebox.translate_coordinates (*_editor.get_track_canvas(), ev->x, ev->y, tx, ty);
/* x-axis of track headers is not shared with the canvas, but /* now schedule the actual TAV resize */
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 */
int32_t const delta = (int32_t) floor (ev->y_root - _resize_drag_start); int32_t const delta = (int32_t) floor (ev->y_root - _resize_drag_start);
_editor.add_to_idle_resize (this, delta); _editor.add_to_idle_resize (this, delta);
_resize_drag_start = ev->y_root; _resize_drag_start = ev->y_root;
@ -545,6 +524,8 @@ TimeAxisView::set_height (uint32_t h)
/* resize the selection rect */ /* resize the selection rect */
show_selection (_editor.get_selection().time); show_selection (_editor.get_selection().time);
} }
_editor.override_visible_track_count ();
} }
bool bool

View file

@ -35,6 +35,8 @@
#include "canvas/text.h" #include "canvas/text.h"
#include "canvas/utils.h" #include "canvas/utils.h"
#include "ardour/profile.h"
#include "ardour_ui.h" #include "ardour_ui.h"
/* /*
* ardour_ui.h was moved up in the include list * 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 */ layout = foo.create_pango_layout (X_("H")); /* just the ascender */
NAME_HEIGHT = height; NAME_HEIGHT = height;
NAME_Y_OFFSET = height + 1;
NAME_HIGHLIGHT_SIZE = height + 2; /* 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; NAME_HIGHLIGHT_THRESH = NAME_HIGHLIGHT_SIZE * 3;
} }
@ -189,7 +203,7 @@ TimeAxisViewItem::init (ArdourCanvas::Group* parent, double fpp, Gdk::Color cons
if (visibility & ShowFrame) { if (visibility & ShowFrame) {
frame = new ArdourCanvas::Rectangle (group, 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.editor().sample_to_pixel(duration) + RIGHT_EDGE_SHIFT,
trackview.current_height() - 1.0)); 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_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 { } else {
frame = 0; frame = 0;
} }
if (visibility & ShowNameHighlight) { if (Config->get_show_name_highlight() && (visibility & ShowNameHighlight)) {
double width; double width;
double start; double start;
@ -240,7 +254,11 @@ TimeAxisViewItem::init (ArdourCanvas::Group* parent, double fpp, Gdk::Color cons
if (visibility & ShowNameText) { if (visibility & ShowNameText) {
name_text = new ArdourCanvas::Text (group); name_text = new ArdourCanvas::Text (group);
CANVAS_DEBUG_NAME (name_text, string_compose ("name text for %1", get_item_name())); CANVAS_DEBUG_NAME (name_text, string_compose ("name text for %1", get_item_name()));
name_text->set_position (ArdourCanvas::Duple (NAME_X_OFFSET, trackview.current_height() - NAME_Y_OFFSET)); 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); name_text->set_font_description (NAME_FONT);
} else { } else {
name_text = 0; name_text = 0;
@ -570,7 +588,11 @@ TimeAxisViewItem::set_height (double height)
manage_name_highlight (); manage_name_highlight ();
if (visibility & ShowNameText) { if (visibility & ShowNameText) {
name_text->set_y_position (height - NAME_Y_OFFSET); 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) { if (frame) {
@ -834,6 +856,13 @@ TimeAxisViewItem::set_frame_gradient ()
void void
TimeAxisViewItem::set_trim_handle_colors() 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 (frame_handle_start) {
if (position_locked) { if (position_locked) {
frame_handle_start->set_fill_color (ARDOUR_UI::config()->get_canvasvar_TrimHandleLocked()); 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()); frame_handle_end->set_fill_color (ARDOUR_UI::config()->get_canvasvar_TrimHandle());
} }
} }
#endif
} }
bool bool

View file

@ -27,6 +27,7 @@
#include "gtkmm2ext/actions.h" #include "gtkmm2ext/actions.h"
#include "ardour/location.h" #include "ardour/location.h"
#include "ardour/profile.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "time_info_box.h" #include "time_info_box.h"
@ -71,7 +72,9 @@ TimeInfoBox::TimeInfoBox ()
set_border_width (2); set_border_width (2);
pack_start (left, true, true); pack_start (left, true, true);
pack_start (right, true, true); if (!ARDOUR::Profile->get_trx()) {
pack_start (right, true, true);
}
left.set_homogeneous (false); left.set_homogeneous (false);
left.set_spacings (0); left.set_spacings (0);

View file

@ -46,6 +46,7 @@ TranscodeFfmpeg::TranscodeFfmpeg (std::string f)
m_avoffset = m_lead_in = m_lead_out = 0; m_avoffset = m_lead_in = m_lead_out = 0;
m_width = m_height = 0; m_width = m_height = 0;
m_aspect = m_fps = 0; m_aspect = m_fps = 0;
m_sar = "";
#if 1 /* tentative debug mode */ #if 1 /* tentative debug mode */
debug_enable = false; debug_enable = false;
#endif #endif
@ -138,6 +139,7 @@ TranscodeFfmpeg::probe ()
m_width = m_height = 0; m_width = m_height = 0;
m_fps = m_aspect = 0; m_fps = m_aspect = 0;
m_duration = 0; m_duration = 0;
m_sar.clear();
m_codec.clear(); m_codec.clear();
m_audio.clear(); m_audio.clear();
@ -199,6 +201,13 @@ TranscodeFfmpeg::probe ()
m_duration = atof(value) * m_fps * timebase; m_duration = atof(value) * m_fps * timebase;
} else if (key == X_("duration") && m_fps != 0 && m_duration == 0) { } else if (key == X_("duration") && m_fps != 0 && m_duration == 0) {
m_duration = atof(value) * m_fps; 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")) { } else if (key == X_("display_aspect_ratio")) {
std::string::size_type pos; std::string::size_type pos;
pos = value.find_first_of(':'); 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) { if (m_lead_in != 0 && m_lead_out != 0) {
std::ostringstream osstream; std::ostringstream osstream;
argp[a++] = strdup("-vf"); 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;
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_out << X_(" [post]; "); 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"); osstream << X_("[pre] [in] [post] concat=n=3");
argp[a++] = strdup(osstream.str().c_str()); argp[a++] = strdup(osstream.str().c_str());
} else if (m_lead_in != 0) { } else if (m_lead_in != 0) {
std::ostringstream osstream; std::ostringstream osstream;
argp[a++] = strdup("-vf"); 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"); osstream << X_("[pre] [in] concat=n=2");
argp[a++] = strdup(osstream.str().c_str()); argp[a++] = strdup(osstream.str().c_str());
} else if (m_lead_out != 0) { } else if (m_lead_out != 0) {
std::ostringstream osstream; std::ostringstream osstream;
argp[a++] = strdup("-vf"); 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"); osstream << X_("[in] [post] concat=n=2");
argp[a++] = strdup(osstream.str().c_str()); argp[a++] = strdup(osstream.str().c_str());
} }

View file

@ -134,6 +134,7 @@ class TranscodeFfmpeg : public sigc::trackable
double m_fps; double m_fps;
double m_aspect; double m_aspect;
std::string m_sar;
ARDOUR::framecnt_t m_duration; ARDOUR::framecnt_t m_duration;
int m_width; int m_width;
int m_height; int m_height;

View file

@ -179,16 +179,18 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
options_box->pack_start (*l, false, true, 4); options_box->pack_start (*l, false, true, 4);
video_combo.set_name ("PaddedButton"); video_combo.set_name ("PaddedButton");
video_combo.append_text(_("Do Not Import Video")); video_combo.append_text(_("Reference From Current Location (Previously Transcoded Files Only)"));
video_combo.append_text(_("Reference From Current Location"));
if (ffok) { if (ffok) {
video_combo.append_text(_("Import/Transcode Video to Session")); video_combo.append_text(_("Import/Transcode Video to Session"));
video_combo.set_active(2);
} else {
video_combo.set_active(1); video_combo.set_active(1);
} else {
video_combo.set_active(0);
video_combo.set_sensitive(false); video_combo.set_sensitive(false);
audio_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); 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); t->attach (*l, 0, 1, 2, 3);
audio_combo.set_name ("PaddedButton"); audio_combo.set_name ("PaddedButton");
t->attach (audio_combo, 1, 4, 2, 3); 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) { for (TranscodeFfmpeg::FFAudioStreams::iterator it = as.begin(); it < as.end(); ++it) {
audio_combo.append_text((*it).name); audio_combo.append_text((*it).name);
} }
@ -366,7 +371,7 @@ TranscodeVideoDialog::dialog_progress_mode ()
void void
TranscodeVideoDialog::launch_transcode () TranscodeVideoDialog::launch_transcode ()
{ {
if (video_combo.get_active_row_number() != 2) { if (video_combo.get_active_row_number() != 1) {
launch_audioonly(); launch_audioonly();
return; return;
} }
@ -415,8 +420,8 @@ TranscodeVideoDialog::launch_transcode ()
void void
TranscodeVideoDialog::video_combo_changed () TranscodeVideoDialog::video_combo_changed ()
{ {
int i = video_combo.get_active_row_number(); const int i = video_combo.get_active_row_number();
if (i != 2) { if (i != 1) {
scale_combo.set_sensitive(false); scale_combo.set_sensitive(false);
aspect_checkbox.set_sensitive(false); aspect_checkbox.set_sensitive(false);
height_spinner.set_sensitive(false); height_spinner.set_sensitive(false);
@ -429,12 +434,19 @@ TranscodeVideoDialog::video_combo_changed ()
bitrate_checkbox.set_sensitive(true); bitrate_checkbox.set_sensitive(true);
bitrate_spinner.set_sensitive(true); bitrate_spinner.set_sensitive(true);
} }
if (i == 2 && audio_combo.get_active_row_number() == 0) {
audio_combo.set_active(1);
}
} }
void void
TranscodeVideoDialog::audio_combo_changed () 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 void

View file

@ -31,9 +31,9 @@
#include "transcode_ffmpeg.h" #include "transcode_ffmpeg.h"
enum VtlTranscodeOption { enum VtlTranscodeOption {
VTL_IMPORT_NO_VIDEO = 0, VTL_IMPORT_REFERENCE = 0,
VTL_IMPORT_REFERENCE = 1, VTL_IMPORT_TRANSCODED = 1,
VTL_IMPORT_TRANSCODED = 2 VTL_IMPORT_NO_VIDEO = 2
}; };
/** @class TranscodeVideoDialog /** @class TranscodeVideoDialog

View file

@ -716,7 +716,7 @@ void
VideoTimeLine::find_xjadeo () { VideoTimeLine::find_xjadeo () {
std::string xjadeo_file_path; std::string xjadeo_file_path;
if (getenv("XJREMOTE")) { 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)) { } else if (find_file_in_search_path (Searchpath(Glib::getenv("PATH")), X_("xjremote"), xjadeo_file_path)) {
_xjadeo_bin = xjadeo_file_path; _xjadeo_bin = xjadeo_file_path;
} }

View file

@ -377,7 +377,6 @@ def build(bld):
# here using winegcc, and link it to the GTK front-end library # here using winegcc, and link it to the GTK front-end library
obj = bld (features = 'cxx c cxxprogram wine') obj = bld (features = 'cxx c cxxprogram wine')
obj.source = ( obj.source = (
'../libs/fst/fst.c',
'../libs/fst/vstwin.c', '../libs/fst/vstwin.c',
'../vst/winmain.c', '../vst/winmain.c',
) )
@ -398,7 +397,7 @@ def build(bld):
obj.includes = [ '../libs/fst', '.' ] obj.includes = [ '../libs/fst', '.' ]
obj.linkflags = ['-mwindows', '-Wl,--export-dynamic'] obj.linkflags = ['-mwindows', '-Wl,--export-dynamic']
obj.defines = ['_POSIX_SOURCE', 'USE_WS_PREFIX'] 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 # end of the wine executable
# now the shared library containing the GTK GUI for ardour # 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']) + '"', 'CONFIG_DIR="' + os.path.normpath(bld.env['SYSCONFDIR']) + '"',
'LOCALEDIR="' + os.path.join(os.path.normpath(bld.env['DATADIR']), 'locale') + '"', '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 = 'UUID FLAC FONTCONFIG GLIBMM GTHREAD GTK OGG CURL DL'
obj.uselib += ' GTKMM CANVAS FFTW3F' obj.uselib += ' GTKMM CANVAS FFTW3F'
obj.uselib += ' AUDIOUNITS OSX GTKOSX LO ' obj.uselib += ' AUDIOUNITS OSX GTKOSX LO '
@ -493,11 +492,15 @@ def build(bld):
# Wrappers # Wrappers
print 'DLL = ' + bld.env['DLLDIR'], '\n'
print 'DATADIR = ' + bld.env['DATADIR'], '\n'
print 'CONF = ' + bld.env['CONFDIR'], '\n'
wrapper_subst_dict = { wrapper_subst_dict = {
'INSTALL_PREFIX' : bld.env['PREFIX'], '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']), 'DATADIR' : os.path.normpath(bld.env['DATADIR']),
'SYSCONFDIR' : os.path.normpath(bld.env['SYSCONFDIR']), 'SYSCONFDIR' : os.path.normpath(bld.env['CONFDIR']),
'LIBS' : 'build/libs', 'LIBS' : 'build/libs',
'VERSION' : bld.env['VERSION'], 'VERSION' : bld.env['VERSION'],
'EXECUTABLE' : 'build/gtk2_ardour/tracks' 'EXECUTABLE' : 'build/gtk2_ardour/tracks'
@ -662,14 +665,14 @@ def build(bld):
# find and add all ##include dependencies as sources # find and add all ##include dependencies as sources
obj.source += _doPyp (bld.path.find_resource ('ardour3_ui_dark.rc.in').srcpath(), True) obj.source += _doPyp (bld.path.find_resource ('ardour3_ui_dark.rc.in').srcpath(), True)
obj.target = 'ardour3_ui_dark.rc' obj.target = 'ardour3_ui_dark.rc'
obj.install_path = '${SYSCONFDIR}/ardour3' obj.install_path = bld.env['CONFDIR']
obj = bld (rule = include_processor) obj = bld (rule = include_processor)
obj.source = [ 'ardour3_ui_light.rc.pre' ] obj.source = [ 'ardour3_ui_light.rc.pre' ]
# find and add all ##include dependencies as sources # find and add all ##include dependencies as sources
obj.source += _doPyp (bld.path.find_resource ('ardour3_ui_light.rc.in').srcpath(), True) obj.source += _doPyp (bld.path.find_resource ('ardour3_ui_light.rc.in').srcpath(), True)
obj.target = 'ardour3_ui_light.rc' obj.target = 'ardour3_ui_light.rc'
obj.install_path = '${SYSCONFDIR}/ardour3' obj.install_path = bld.env['CONFDIR']
# Menus # Menus
menus_argv = [] menus_argv = []
@ -704,27 +707,24 @@ def build(bld):
source = b + '.bindings.in', source = b + '.bindings.in',
rule = a_rule 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 # not modified at present
bld.install_files(os.path.join(bld.env['SYSCONFDIR'], 'ardour3'), bld.install_files(bld.env['CONFDIR'], 'step_editing.bindings')
'step_editing.bindings') bld.install_files(bld.env['CONFDIR'], 'mixer.bindings')
bld.install_files(os.path.join(bld.env['SYSCONFDIR'], 'ardour3'),
'mixer.bindings')
# Icons/Images # Icons/Images
bld.install_files('${DATADIR}/ardour3/icons', bld.path.ant_glob('icons/*.png')) bld.install_files(os.path.join (bld.env['DATADIR'], 'icons'), bld.path.ant_glob('icons/*.png'))
bld.install_files('${DATADIR}/ardour3/pixmaps', bld.path.ant_glob('pixmaps/*.xpm')) bld.install_files(os.path.join (bld.env['DATADIR'], 'pixmaps'), bld.path.ant_glob('pixmaps/*.xpm'))
bld.install_files('${DATADIR}/ardour3/ui', bld.path.ant_glob('ui/*.*')) bld.install_files(bld.env['DATADIR'], 'splash.png')
bld.install_files('${DATADIR}/ardour3', 'splash.png') bld.install_files(bld.env['DATADIR'], 'small-splash.png')
bld.install_files('${DATADIR}/ardour3', 'small-splash.png') bld.install_files(bld.env['DATADIR'], 'ArdourMono.ttf')
bld.install_files('${DATADIR}/ardour3', 'ArdourMono.ttf')
# Default UI configuration # 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 # 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 # i18n
if bld.is_defined('ENABLE_NLS'): if bld.is_defined('ENABLE_NLS'):

View file

@ -139,7 +139,6 @@ class LIBARDOUR_API AudioDiskstream : public Diskstream
void set_block_size (pframes_t); void set_block_size (pframes_t);
int internal_playback_seek (framecnt_t distance); int internal_playback_seek (framecnt_t distance);
int can_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 reset_write_sources (bool, bool force = false);
void non_realtime_input_change (); void non_realtime_input_change ();
void non_realtime_locate (framepos_t location); void non_realtime_locate (framepos_t location);

View file

@ -39,10 +39,6 @@ class LIBARDOUR_API AudioFileSource : public AudioSource, public FileSource {
public: public:
virtual ~AudioFileSource (); 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 peak_path (std::string audio_path);
std::string find_broken_peakfile (std::string missing_peak_path, std::string find_broken_peakfile (std::string missing_peak_path,
std::string audio_path); std::string audio_path);

View file

@ -71,6 +71,8 @@ class LIBARDOUR_API Diskstream : public SessionObject, public PublicDiskstream
virtual bool set_name (const std::string& str); 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; } boost::shared_ptr<ARDOUR::IO> io() const { return _io; }
void set_track (ARDOUR::Track *); void set_track (ARDOUR::Track *);

View file

@ -44,7 +44,7 @@ class LIBARDOUR_API MissingSource : public std::exception
/** A source associated with a file on disk somewhere */ /** A source associated with a file on disk somewhere */
class LIBARDOUR_API FileSource : virtual public Source { class LIBARDOUR_API FileSource : virtual public Source {
public: public:
virtual ~FileSource () {} virtual ~FileSource ();
virtual const std::string& path() const { return _path; } virtual const std::string& path() const { return _path; }
@ -82,6 +82,9 @@ public:
static PBD::Signal2<int,std::string,std::vector<std::string> > AmbiguousFileName; static PBD::Signal2<int,std::string,std::vector<std::string> > AmbiguousFileName;
void existence_check ();
virtual void prevent_deletion ();
protected: protected:
FileSource (Session& session, DataType type, FileSource (Session& session, DataType type,
const std::string& path, const std::string& path,
@ -103,7 +106,6 @@ protected:
std::string _origin; std::string _origin;
bool _open; bool _open;
void prevent_deletion ();
}; };
} // namespace ARDOUR } // namespace ARDOUR

View file

@ -111,7 +111,7 @@ class LIBARDOUR_API MidiDiskstream : public Diskstream
void set_block_size (pframes_t); void set_block_size (pframes_t);
int internal_playback_seek (framecnt_t distance); int internal_playback_seek (framecnt_t distance);
int can_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 reset_write_sources (bool, bool force = false);
void non_realtime_input_change (); void non_realtime_input_change ();
void non_realtime_locate (framepos_t location); void non_realtime_locate (framepos_t location);

View file

@ -64,6 +64,7 @@ class LIBARDOUR_API MidiRegion : public Region
~MidiRegion(); ~MidiRegion();
boost::shared_ptr<MidiRegion> clone (std::string path = std::string()) const; 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; boost::shared_ptr<MidiSource> midi_source (uint32_t n=0) const;

View file

@ -49,9 +49,21 @@ class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_sha
MidiSource (Session& session, const XMLNode&); MidiSource (Session& session, const XMLNode&);
virtual ~MidiSource (); virtual ~MidiSource ();
boost::shared_ptr<MidiSource> clone (const std::string& path, /** Write the data in the given time range to another MidiSource
Evoral::MusicalTime begin = Evoral::MinMusicalTime, * \param newsrc MidiSource to which data will be written. Should be a
Evoral::MusicalTime end = Evoral::MaxMusicalTime); * 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);
/** Read the data in a given time range from the MIDI source. /** Read the data in a given time range from the MIDI source.
* All time stamps in parameters are in audio frames (even if the source has tempo time). * All time stamps in parameters are in audio frames (even if the source has tempo time).

View file

@ -38,7 +38,7 @@ public:
virtual bool destructive () const = 0; virtual bool destructive () const = 0;
virtual std::list<boost::shared_ptr<Source> > & last_capture_sources () = 0; virtual std::list<boost::shared_ptr<Source> > & last_capture_sources () = 0;
virtual void set_capture_offset () = 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 void reset_write_sources (bool, bool force = false) = 0;
virtual float playback_buffer_load () const = 0; virtual float playback_buffer_load () const = 0;
virtual float capture_buffer_load () const = 0; virtual float capture_buffer_load () const = 0;

View file

@ -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_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, mmc_send_device_id, "mmc-send-device-id", 0)
CONFIG_VARIABLE (int32_t, initial_program_change, "initial-program-change", -1) 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 */ /* 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 (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, allow_non_quarter_pulse, "allow-non-quarter-pulse", false)
CONFIG_VARIABLE (bool, show_region_gain, "show-region-gain", 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 */ /* web addresses used in the program */

View file

@ -194,8 +194,6 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
std::string peak_path (std::string) const; 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 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_audio_source_name (const std::string&, uint32_t nchans, uint32_t chan, bool destructive);
std::string new_midi_source_name (const std::string&); 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 ( boost::shared_ptr<AudioFileSource> create_audio_source_for_session (
size_t, std::string const &, uint32_t, bool destructive); size_t, std::string const &, uint32_t, bool destructive);
boost::shared_ptr<MidiSource> create_midi_source_for_session ( boost::shared_ptr<MidiSource> create_midi_source_for_session (std::string const &);
Track*, 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_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&); uint32_t count_sources_by_origin (const std::string&);
void add_playlist (boost::shared_ptr<Playlist>, bool unused = false); void add_playlist (boost::shared_ptr<Playlist>, bool unused = false);

View file

@ -45,12 +45,19 @@ public:
virtual ~SMFSource (); 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 { bool safe_file_extension (const std::string& path) const {
return safe_midi_file_extension(path); 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_beats (const Evoral::Event<Evoral::MusicalTime>& ev);
void append_event_unlocked_frames (const Evoral::Event<framepos_t>& ev, framepos_t source_start); 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); static bool safe_midi_file_extension (const std::string& path);
void prevent_deletion ();
protected: protected:
void set_path (const std::string& newpath); void set_path (const std::string& newpath);

View file

@ -120,7 +120,7 @@ class LIBARDOUR_API Track : public Route, public PublicDiskstream
bool destructive () const; bool destructive () const;
std::list<boost::shared_ptr<Source> > & last_capture_sources (); std::list<boost::shared_ptr<Source> > & last_capture_sources ();
void set_capture_offset (); 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); void reset_write_sources (bool, bool force = false);
float playback_buffer_load () const; float playback_buffer_load () const;
float capture_buffer_load () const; float capture_buffer_load () const;

View file

@ -62,7 +62,6 @@ struct LIBARDOUR_API _VSTHandle
{ {
void* dll; void* dll;
char* name; char* name;
char* nameptr;
char* path; char* path;
main_entry_t main_entry; main_entry_t main_entry;

View file

@ -1926,14 +1926,6 @@ AudioDiskstream::use_new_write_source (uint32_t n)
return 0; 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 void
AudioDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/) AudioDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/)
{ {

View file

@ -105,15 +105,15 @@ AudioLibrary::get_tags (string member)
{ {
vector<string> tags; vector<string> tags;
#ifdef HAVE_LRDF #ifdef HAVE_LRDF
char * uri = strdup(Glib::filename_to_uri(member).c_str());
lrdf_statement pattern; lrdf_statement pattern;
pattern.subject = strdup(Glib::filename_to_uri(member).c_str()); pattern.subject = uri;
pattern.predicate = const_cast<char*>(TAG); pattern.predicate = const_cast<char*>(TAG);
pattern.object = 0; pattern.object = 0;
pattern.object_type = lrdf_literal; pattern.object_type = lrdf_literal;
lrdf_statement* matches = lrdf_matches (&pattern); lrdf_statement* matches = lrdf_matches (&pattern);
free (pattern.subject);
lrdf_statement* current = matches; lrdf_statement* current = matches;
while (current != 0) { while (current != 0) {
@ -125,6 +125,7 @@ AudioLibrary::get_tags (string member)
lrdf_free_statements (matches); lrdf_free_statements (matches);
sort (tags.begin(), tags.end()); sort (tags.begin(), tags.end());
free (uri);
#endif #endif
return tags; return tags;
} }

View file

@ -303,7 +303,7 @@ framecnt_t
AudioSource::write (Sample *dst, framecnt_t cnt) AudioSource::write (Sample *dst, framecnt_t cnt)
{ {
Glib::Threads::Mutex::Lock lm (_lock); Glib::Threads::Mutex::Lock lm (_lock);
/* any write makes the fill not removable */ /* any write makes the file not removable */
_flags = Flag (_flags & ~Removable); _flags = Flag (_flags & ~Removable);
return write_unlocked (dst, cnt); return write_unlocked (dst, cnt);
} }

View file

@ -245,9 +245,32 @@ ControlProtocolManager::discover_control_protocols ()
{ {
vector<std::string> cp_modules; 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 so_extension_pattern("*.so");
Glib::PatternSpec dylib_extension_pattern("*.dylib"); 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 (), find_matching_files_in_search_path (control_protocol_search_path (),
so_extension_pattern, cp_modules); so_extension_pattern, cp_modules);

View file

@ -28,6 +28,8 @@
#include <appleutility/CAAudioFile.h> #include <appleutility/CAAudioFile.h>
#include <appleutility/CAStreamBasicDescription.h> #include <appleutility/CAStreamBasicDescription.h>
#include <glibmm/fileutils.h>
#include "i18n.h" #include "i18n.h"
#include <AudioToolbox/AudioFormat.h> #include <AudioToolbox/AudioFormat.h>
@ -36,21 +38,32 @@ using namespace std;
using namespace ARDOUR; using namespace ARDOUR;
using namespace PBD; 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) CoreAudioSource::CoreAudioSource (Session& s, const XMLNode& node)
: Source (s, node) : Source (s, node)
, AudioFileSource (s, node) , AudioFileSource (s, node)
{ {
init_cafile (); 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) 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))), : Source (s, DataType::AUDIO, path, Source::Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy))),
AudioFileSource (s, path, AudioFileSource (s, path,
Source::Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy))) Source::Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
{ {
_channel = chn; _channel = chn;
init_cafile (); init_cafile ();
assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
existence_check ();
} }
void void

View file

@ -62,8 +62,6 @@ FileSource::FileSource (Session& session, DataType type, const string& path, con
, _open (false) , _open (false)
{ {
set_within_session_from_path (path); set_within_session_from_path (path);
prevent_deletion ();
} }
FileSource::FileSource (Session& session, const XMLNode& node, bool /*must_exist*/) FileSource::FileSource (Session& session, const XMLNode& node, bool /*must_exist*/)
@ -77,23 +75,28 @@ FileSource::FileSource (Session& session, const XMLNode& node, bool /*must_exist
_path = _name; _path = _name;
_within_session = true; _within_session = true;
}
prevent_deletion (); FileSource::~FileSource()
{
}
void
FileSource::existence_check ()
{
if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS)) {
prevent_deletion ();
}
} }
void void
FileSource::prevent_deletion () FileSource::prevent_deletion ()
{ {
/* if this file already exists, it cannot be removed, ever if (!(_flags & Destructive)) {
*/ mark_immutable ();
} else {
if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS)) { _flags = Flag (_flags & ~(Removable|RemovableIfEmpty|RemoveAtDestroy));
if (!(_flags & Destructive)) { }
mark_immutable ();
} else {
_flags = Flag (_flags & ~(Removable|RemovableIfEmpty|RemoveAtDestroy));
}
}
} }
bool bool
@ -509,35 +512,6 @@ out:
return ret; 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 void
FileSource::mark_immutable () FileSource::mark_immutable ()
{ {

View file

@ -112,7 +112,7 @@ vstfx_new ()
void* vstfx_load_vst_library(const char* path) void* vstfx_load_vst_library(const char* path)
{ {
void* dll; void* dll;
char* full_path; char* full_path = NULL;
char* envdup; char* envdup;
char* lxvst_path; char* lxvst_path;
size_t len1; size_t len1;
@ -160,6 +160,7 @@ void* vstfx_load_vst_library(const char* path)
vstfx_error ("\"%s\"", lxvst_path); vstfx_error ("\"%s\"", lxvst_path);
len1 = strlen(lxvst_path); len1 = strlen(lxvst_path);
if (full_path) free(full_path);
full_path = (char*)malloc(len1 + 1 + len2 + 1); full_path = (char*)malloc(len1 + 1 + len2 + 1);
memcpy(full_path, lxvst_path, len1); memcpy(full_path, lxvst_path, len1);
full_path[len1] = '/'; full_path[len1] = '/';
@ -180,7 +181,7 @@ void* vstfx_load_vst_library(const char* path)
} }
/*Free the path*/ /*Free the path*/
if (full_path) free(full_path);
free(envdup); free(envdup);
return dll; return dll;
@ -209,8 +210,6 @@ vstfx_load (const char *path)
buf = (char *)malloc(strlen(path) + 4); //The .so and a terminating zero buf = (char *)malloc(strlen(path) + 4); //The .so and a terminating zero
sprintf (buf, "%s.so", path); sprintf (buf, "%s.so", path);
fhandle->nameptr = strdup (path);
} }
else else
@ -218,8 +217,6 @@ vstfx_load (const char *path)
/*We already have .so appened to the filename*/ /*We already have .so appened to the filename*/
buf = strdup(path); buf = strdup(path);
fhandle->nameptr = strdup (path);
} }
/* get a name for the plugin based on the path: ye old VST problem where /* 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 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*/ /*call load_vstfx_library to actually load the .so into memory*/
@ -289,9 +286,8 @@ vstfx_unload (VSTHandle* fhandle)
fhandle->dll = 0; fhandle->dll = 0;
} }
if (fhandle->nameptr) if (fhandle->name)
{ {
free (fhandle->nameptr);
free (fhandle->name); free (fhandle->name);
} }
@ -310,8 +306,9 @@ vstfx_instantiate (VSTHandle* fhandle, audioMasterCallback amc, void* userptr)
if(fhandle == 0) if(fhandle == 0)
{ {
vstfx_error( "** ERROR ** VSTFX : The handle was 0\n" ); vstfx_error( "** ERROR ** VSTFX : The handle was 0\n" );
return 0; free (vstfx);
return 0;
} }
if ((vstfx->plugin = fhandle->main_entry (amc)) == 0) if ((vstfx->plugin = fhandle->main_entry (amc)) == 0)

View file

@ -26,12 +26,12 @@
#include <cstring> #include <cstring>
#include <glib/gstdio.h> #include <glib/gstdio.h>
#include <giomm/file.h>
#include <glib/gprintf.h> #include <glib/gprintf.h>
#include <glibmm.h> #include <glibmm.h>
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include "pbd/clear_dir.h"
#include "pbd/pathscanner.h" #include "pbd/pathscanner.h"
#include "pbd/compose.h" #include "pbd/compose.h"
#include "pbd/error.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()); 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 void
LV2Plugin::add_state(XMLNode* root) const LV2Plugin::add_state(XMLNode* root) const
{ {
@ -953,7 +932,7 @@ LV2Plugin::add_state(XMLNode* root) const
} else { } else {
// State is identical, decrement version and nuke directory // State is identical, decrement version and nuke directory
lilv_state_free(state); lilv_state_free(state);
remove_directory(new_dir); PBD::remove_directory(new_dir);
--_state_version; --_state_version;
} }

View file

@ -1198,7 +1198,7 @@ MidiDiskstream::use_new_write_source (uint32_t n)
try { try {
_write_source = boost::dynamic_pointer_cast<SMFSource>( _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) { if (!_write_source) {
throw failed_constructor(); throw failed_constructor();
@ -1213,25 +1213,36 @@ MidiDiskstream::use_new_write_source (uint32_t n)
return 0; return 0;
} }
/**
list<boost::shared_ptr<Source> > * We want to use the name of the existing write source (the one that will be
MidiDiskstream::steal_write_sources() * 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 */ /* this will bump the name of the current write source to the next one
boost::dynamic_pointer_cast<SMFSource> (_write_source)->ensure_disk_file (); * (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 */ try {
_write_source->mark_nonremovable (); string new_name = _session.new_midi_source_name (name());
ret.push_back (_write_source); if (_write_source->rename (new_name)) {
return string();
/* get a new one */ }
} catch (...) {
use_new_write_source (0); return string ();
}
return ret;
return our_old_name;
} }
void void

View file

@ -1252,7 +1252,7 @@ MidiModel::PatchChangePtr
MidiModel::PatchChangeDiffCommand::unmarshal_patch_change (XMLNode* n) MidiModel::PatchChangeDiffCommand::unmarshal_patch_change (XMLNode* n)
{ {
XMLProperty* prop; XMLProperty* prop;
Evoral::event_id_t id; Evoral::event_id_t id = 0;
Evoral::MusicalTime time = 0; Evoral::MusicalTime time = 0;
int channel = 0; int channel = 0;
int program = 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)); PatchChangePtr p (new Evoral::PatchChange<TimeType> (time, channel, program, bank));
assert(id);
p->set_id (id); p->set_id (id);
return p; return p;
} }

View file

@ -25,6 +25,8 @@
#include <set> #include <set>
#include <glibmm/threads.h> #include <glibmm/threads.h>
#include <glibmm/fileutils.h>
#include <glibmm/miscutils.h>
#include "pbd/xml++.h" #include "pbd/xml++.h"
#include "pbd/basename.h" #include "pbd/basename.h"
@ -36,6 +38,7 @@
#include "ardour/midi_source.h" #include "ardour/midi_source.h"
#include "ardour/region_factory.h" #include "ardour/region_factory.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/source_factory.h"
#include "ardour/tempo.h" #include "ardour/tempo.h"
#include "ardour/types.h" #include "ardour/types.h"
@ -126,16 +129,31 @@ MidiRegion::~MidiRegion ()
*/ */
boost::shared_ptr<MidiRegion> boost::shared_ptr<MidiRegion>
MidiRegion::clone (string path) const 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); BeatsFramesConverter bfc (_session.tempo_map(), _position);
Evoral::MusicalTime const bbegin = bfc.from (_start); Evoral::MusicalTime const bbegin = bfc.from (_start);
Evoral::MusicalTime const bend = bfc.from (_start + _length); 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; 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::whole_file, true);
plist.add (Properties::start, _start); plist.add (Properties::start, _start);
plist.add (Properties::start_beats, _start_beats); 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::length_beats, _length_beats);
plist.add (Properties::layer, 0); 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 void

View file

@ -38,6 +38,7 @@
#include "ardour/midi_model.h" #include "ardour/midi_model.h"
#include "ardour/midi_state_tracker.h" #include "ardour/midi_state_tracker.h"
#include "ardour/midi_source.h" #include "ardour/midi_source.h"
#include "ardour/file_source.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/session_directory.h" #include "ardour/session_directory.h"
#include "ardour/source_factory.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); mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::DeleteStuckNotes);
} }
boost::shared_ptr<MidiSource> int
MidiSource::clone (const string& path, Evoral::MusicalTime begin, Evoral::MusicalTime end) 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->set_timeline_position(_timeline_position);
newsrc->copy_interpolation_from (this); newsrc->copy_interpolation_from (this);
newsrc->copy_automation_state_from (this); newsrc->copy_automation_state_from (this);
@ -368,7 +347,7 @@ MidiSource::clone (const string& path, Evoral::MusicalTime begin, Evoral::Musica
} }
} else { } else {
error << string_compose (_("programming error: %1"), X_("no model for MidiSource during ::clone()")); error << string_compose (_("programming error: %1"), X_("no model for MidiSource during ::clone()"));
return boost::shared_ptr<MidiSource>(); return -1;
} }
newsrc->flush_midi(); newsrc->flush_midi();
@ -380,8 +359,12 @@ MidiSource::clone (const string& path, Evoral::MusicalTime begin, Evoral::Musica
} else { } else {
newsrc->set_model (_model); newsrc->set_model (_model);
} }
/* this file is not removable (but since it is MIDI, it is mutable) */
return newsrc; boost::dynamic_pointer_cast<FileSource> (newsrc)->prevent_deletion ();
return 0;
} }
void void

View file

@ -116,10 +116,9 @@ PluginManager::PluginManager ()
char* s; char* s;
string lrdf_path; string lrdf_path;
if (!PBD::find_file_in_search_path ( string scan_p = Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst");
PBD::Searchpath(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)) {
"ardour-vst-scanner", scanner_bin_path)) { PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << scan_p << endmsg;
PBD::warning << "VST scanner app not found.'" << endmsg;
} }
load_statuses (); load_statuses ();

View file

@ -3911,7 +3911,7 @@ Route::setup_invisible_processors ()
++amp; ++amp;
} }
assert (amp != _processors.end ()); assert (amp != new_processors.end ());
/* and the processor after the amp */ /* and the processor after the amp */

View file

@ -88,6 +88,7 @@
#include "ardour/smf_source.h" #include "ardour/smf_source.h"
#include "ardour/source_factory.h" #include "ardour/source_factory.h"
#include "ardour/speakers.h" #include "ardour/speakers.h"
#include "ardour/track.h"
#include "ardour/utils.h" #include "ardour/utils.h"
#include "midi++/port.h" #include "midi++/port.h"
@ -3525,12 +3526,16 @@ Session::source_by_id (const PBD::ID& id)
return source; return source;
} }
boost::shared_ptr<Source> boost::shared_ptr<AudioFileSource>
Session::source_by_path_and_channel (const string& path, uint16_t chn) 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); 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::shared_ptr<AudioFileSource> afs
= boost::dynamic_pointer_cast<AudioFileSource>(i->second); = 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 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 uint32_t
@ -3559,111 +3588,6 @@ Session::count_sources_by_origin (const string& path)
return cnt; 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. /** 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 * \a name must be a session-unique name that does not contain slashes
* (e.g. as returned by new_*_source_name) * (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++; existing++;
break; 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) { 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())); 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 string
Session::new_midi_source_name (const string& base) Session::new_midi_source_name (const string& owner_name)
{ {
uint32_t cnt; uint32_t cnt;
char buf[PATH_MAX+1]; char buf[PATH_MAX+1];
const uint32_t limit = 10000; const uint32_t limit = 10000;
string legalized; string legalized;
string possible_name;
buf[0] = '\0'; 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. // Find a "version" of the file name that doesn't exist in any of the possible directories.
for (cnt = 1; cnt <= limit; ++cnt) { for (cnt = 1; cnt <= limit; ++cnt) {
vector<space_and_path>::iterator i; vector<space_and_path>::iterator i;
@ -3817,12 +3759,17 @@ Session::new_midi_source_name (const string& base)
for (i = session_dirs.begin(); i != session_dirs.end(); ++i) { for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
SessionDirectory sdir((*i).path); SessionDirectory sdir((*i).path);
snprintf (buf, sizeof(buf), "%s-%u.mid", legalized.c_str(), cnt);
possible_name = buf;
std::string p = Glib::build_filename (sdir.midi_path(), legalized); std::string possible_path = Glib::build_filename (sdir.midi_path(), possible_name);
if (Glib::file_test (possible_path, Glib::FILE_TEST_EXISTS)) {
existing++;
}
snprintf (buf, sizeof(buf), "%s-%u.mid", p.c_str(), cnt); if (source_by_path (possible_path)) {
if (Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
existing++; existing++;
} }
} }
@ -3834,37 +3781,64 @@ Session::new_midi_source_name (const string& base)
if (cnt > limit) { if (cnt > limit) {
error << string_compose( error << string_compose(
_("There are already %1 recordings for %2, which I consider too many."), _("There are already %1 recordings for %2, which I consider too many."),
limit, base) << endmsg; limit, owner_name) << endmsg;
destroy (); destroy ();
throw failed_constructor(); throw failed_constructor();
} }
} }
return Glib::path_get_basename(buf); return possible_name;
} }
/** Create a new within-session MIDI source */ /** Create a new within-session MIDI source */
boost::shared_ptr<MidiSource> 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 (track) { if (name.empty()) {
/*MidiTrack* mt = dynamic_cast<Track*> (track); name = new_midi_source_name (basic_name);
assert (mt); }
*/
const string path = new_source_path_from_name (DataType::MIDI, name);
list<boost::shared_ptr<Source> > l = track->steal_write_sources ();
return boost::dynamic_pointer_cast<SMFSource> (
if (!l.empty()) { SourceFactory::createWritable (
assert (boost::dynamic_pointer_cast<MidiSource> (l.front())); DataType::MIDI, *this, path, false, frame_rate()));
return boost::dynamic_pointer_cast<MidiSource> (l.front()); }
}
/** 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.
*/
boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (track);
assert (mt);
std::string name = track->steal_write_source_name ();
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); const string path = new_source_path_from_name (DataType::MIDI, name);
return boost::dynamic_pointer_cast<SMFSource> ( return boost::dynamic_pointer_cast<SMFSource> (

View file

@ -802,7 +802,7 @@ Session::load_state (string snapshot_name)
set_dirty(); 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)) { if (!state_tree->read (xmlpath)) {
error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg; error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
@ -920,7 +920,7 @@ Session::state (bool full_state)
p += (*i).path; p += (*i).path;
if (next != session_dirs.end()) { if (next != session_dirs.end()) {
p += ':'; p += G_SEARCHPATH_SEPARATOR;
} else { } else {
break; break;
} }
@ -2684,7 +2684,7 @@ Session::cleanup_sources (CleanupReport& rep)
audio_path += sdir.sound_path(); audio_path += sdir.sound_path();
if (nexti != session_dirs.end()) { if (nexti != session_dirs.end()) {
audio_path += ':'; audio_path += G_SEARCHPATH_SEPARATOR;
} }
i = nexti; i = nexti;
@ -2702,7 +2702,7 @@ Session::cleanup_sources (CleanupReport& rep)
midi_path += sdir.midi_path(); midi_path += sdir.midi_path();
if (nexti != session_dirs.end()) { if (nexti != session_dirs.end()) {
midi_path += ':'; midi_path += G_SEARCHPATH_SEPARATOR;
} }
i = nexti; i = nexti;

View file

@ -63,9 +63,12 @@ SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags)
{ {
/* note that origin remains empty */ /* note that origin remains empty */
if (init(_path, false)) { if (init (_path, false)) {
throw failed_constructor (); throw failed_constructor ();
} }
assert (!Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
existence_check ();
/* file is not opened until write */ /* file is not opened until write */
@ -73,9 +76,10 @@ SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags)
return; return;
} }
if (open(_path)) { if (open (_path)) {
throw failed_constructor (); throw failed_constructor ();
} }
_open = true; _open = true;
} }
@ -93,10 +97,13 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
throw failed_constructor (); throw failed_constructor ();
} }
if (init(_path, true)) { if (init (_path, true)) {
throw failed_constructor (); throw failed_constructor ();
} }
assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
existence_check ();
if (open(_path)) { if (open(_path)) {
throw failed_constructor (); 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;
}

View file

@ -31,6 +31,7 @@
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
#include <glibmm/convert.h> #include <glibmm/convert.h>
#endif #endif
#include <glibmm/fileutils.h>
#include <glibmm/miscutils.h> #include <glibmm/miscutils.h>
#include "ardour/sndfilesource.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) SndFileSource::SndFileSource (Session& s, const XMLNode& node)
: Source(s, node) : Source(s, node)
, AudioFileSource (s, node) , AudioFileSource (s, node)
, _descriptor (0)
, _broadcast_info (0)
, _capture_start (false)
, _capture_end (false)
, file_pos (0)
, xfade_buf (0)
{ {
init_sndfile (); init_sndfile ();
assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
existence_check ();
if (open()) { if (open()) {
throw failed_constructor (); 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) SndFileSource::SndFileSource (Session& s, const string& path, int chn, Flag flags)
: Source(s, DataType::AUDIO, path, flags) : Source(s, DataType::AUDIO, path, flags)
/* note that the origin of an external file is itself */ /* note that the origin of an external file is itself */
, AudioFileSource (s, path, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy))) , 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; _channel = chn;
init_sndfile (); init_sndfile ();
assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
existence_check ();
if (open()) { if (open()) {
throw failed_constructor (); 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, SndFileSource::SndFileSource (Session& s, const string& path, const string& origin,
SampleFormat sfmt, HeaderFormat hf, framecnt_t rate, Flag flags) SampleFormat sfmt, HeaderFormat hf, framecnt_t rate, Flag flags)
: Source(s, DataType::AUDIO, path, flags) : Source(s, DataType::AUDIO, path, flags)
, AudioFileSource (s, path, origin, flags, sfmt, hf) , 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; int fmt = 0;
init_sndfile (); init_sndfile ();
assert (!Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
existence_check ();
_file_is_new = true; _file_is_new = true;
switch (hf) { switch (hf) {
@ -156,24 +188,12 @@ SndFileSource::SndFileSource (Session& s, const string& path, const string& orig
void void
SndFileSource::init_sndfile () 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, /* although libsndfile says we don't need to set this,
valgrind and source code shows us that we do. valgrind and source code shows us that we do.
*/ */
memset (&_info, 0, sizeof(_info)); memset (&_info, 0, sizeof(_info));
_capture_start = false;
_capture_end = false;
file_pos = 0;
if (destructive()) { if (destructive()) {
xfade_buf = new Sample[xfade_frames]; xfade_buf = new Sample[xfade_frames];
_timeline_position = header_position_offset; _timeline_position = header_position_offset;

View file

@ -579,10 +579,10 @@ Track::set_capture_offset ()
_diskstream->set_capture_offset (); _diskstream->set_capture_offset ();
} }
list<boost::shared_ptr<Source> > std::string
Track::steal_write_sources() Track::steal_write_source_name()
{ {
return _diskstream->steal_write_sources (); return _diskstream->steal_write_source_name ();
} }
void void

View file

@ -34,7 +34,6 @@
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <libgen.h>
#include <glib.h> #include <glib.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>

View file

@ -82,6 +82,9 @@ Worker::verify_message_completeness(RingBuffer<uint8_t>* rb)
uint32_t size; uint32_t size;
RingBuffer<uint8_t>::rw_vector vec; RingBuffer<uint8_t>::rw_vector vec;
rb->get_read_vector (&vec); rb->get_read_vector (&vec);
if (vec.len[0] + vec.len[1] < sizeof(size)) {
return false;
}
if (vec.len[0] >= sizeof(size)) { if (vec.len[0] >= sizeof(size)) {
memcpy (&size, vec.buf[0], sizeof (size)); memcpy (&size, vec.buf[0], sizeof (size));
} else { } else {
@ -121,6 +124,7 @@ Worker::run()
while (true) { while (true) {
_sem.wait(); _sem.wait();
if (_exit) { if (_exit) {
if (buf) free(buf);
return; return;
} }
@ -132,6 +136,7 @@ Worker::run()
while (!verify_message_completeness(_requests)) { while (!verify_message_completeness(_requests)) {
Glib::usleep(2000); Glib::usleep(2000);
if (_exit) { if (_exit) {
if (buf) free(buf);
return; return;
} }
} }
@ -143,7 +148,13 @@ Worker::run()
if (size > buf_size) { if (size > buf_size) {
buf = realloc(buf, size); buf = realloc(buf, size);
buf_size = 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) { if (_requests->read((uint8_t*)buf, size) < size) {

View file

@ -377,7 +377,7 @@ def build(bld):
obj.includes += [ '../fst' ] obj.includes += [ '../fst' ]
obj.defines += [ 'WINDOWS_VST_SUPPORT' ] obj.defines += [ 'WINDOWS_VST_SUPPORT' ]
if bld.env['build_target'] == 'mingw': if bld.env['build_target'] == 'mingw':
obj.source += [ '../fst/vstwin.c', '../fst/fst.c'] obj.source += [ '../fst/vstwin.c']
obj.uselib += ['GDI32'] obj.uselib += ['GDI32']
if bld.is_defined('LXVST_SUPPORT'): if bld.is_defined('LXVST_SUPPORT'):
@ -419,7 +419,7 @@ def build(bld):
testcommon.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD', testcommon.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD',
'SAMPLERATE','XML','LRDF','COREAUDIO','TAGLIB','VAMPSDK','VAMPHOSTSDK','RUBBERBAND'] 'SAMPLERATE','XML','LRDF','COREAUDIO','TAGLIB','VAMPSDK','VAMPHOSTSDK','RUBBERBAND']
testcommon.use = ['libpbd','libmidipp','libevoral', testcommon.use = ['libpbd','libmidipp','libevoral',
'libaudiographer','ardour'] 'libaudiographer','libardour']
if bld.is_defined('USE_EXTERNAL_LIBS'): if bld.is_defined('USE_EXTERNAL_LIBS'):
testcommon.uselib.extend(['LIBLTC',]) testcommon.uselib.extend(['LIBLTC',])
else: else:
@ -499,7 +499,7 @@ def build(bld):
session_load_tester.includes.append ('test') session_load_tester.includes.append ('test')
session_load_tester.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD', session_load_tester.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD',
'SAMPLERATE','XML','LRDF','COREAUDIO'] '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.name = 'libardour-session-load-tester'
session_load_tester.target = 'load-session' session_load_tester.target = 'load-session'
session_load_tester.install_path = '' session_load_tester.install_path = ''
@ -532,7 +532,7 @@ def build(bld):
profilingobj.includes.append ('test') profilingobj.includes.append ('test')
profilingobj.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD', profilingobj.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD',
'SAMPLERATE','XML','LRDF','COREAUDIO'] 'SAMPLERATE','XML','LRDF','COREAUDIO']
profilingobj.use = ['libpbd','libmidipp','ardour'] profilingobj.use = ['libpbd','libmidipp','libardour']
profilingobj.name = 'libardour-profiling' profilingobj.name = 'libardour-profiling'
profilingobj.target = p profilingobj.target = p
profilingobj.install_path = '' profilingobj.install_path = ''
@ -558,7 +558,7 @@ def create_ardour_test_program(bld, includes, name, target, sources):
testobj.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD', testobj.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD',
'SAMPLERATE','XML','LRDF','COREAUDIO','TAGLIB','VAMPSDK','VAMPHOSTSDK','RUBBERBAND'] 'SAMPLERATE','XML','LRDF','COREAUDIO','TAGLIB','VAMPSDK','VAMPHOSTSDK','RUBBERBAND']
testobj.use = ['libpbd','libmidipp','libevoral', testobj.use = ['libpbd','libmidipp','libevoral',
'libaudiographer','ardour','testcommon'] 'libaudiographer','libardour','testcommon']
if bld.is_defined('USE_EXTERNAL_LIBS'): if bld.is_defined('USE_EXTERNAL_LIBS'):
testobj.uselib.extend(['LIBLTC']) testobj.uselib.extend(['LIBLTC'])
else: else:

View file

@ -33,7 +33,11 @@ namespace Evoral {
* Currently a note is defined as (on event, length, off event). * Currently a note is defined as (on event, length, off event).
*/ */
template<typename Time> template<typename Time>
#ifdef COMPILER_MSVC
class LIBEVORAL_LOCAL Note {
#else
class LIBEVORAL_TEMPLATE_API Note { class LIBEVORAL_TEMPLATE_API Note {
#endif
public: public:
Note(uint8_t chan=0, Time time=0, Time len=0, uint8_t note=0, uint8_t vel=0x40); Note(uint8_t chan=0, Time time=0, Time len=0, uint8_t note=0, uint8_t vel=0x40);
Note(const Note<Time>& copy); Note(const Note<Time>& copy);

View file

@ -24,8 +24,8 @@
#define LIBEVORAL_DLL_IMPORT __declspec(dllimport) #define LIBEVORAL_DLL_IMPORT __declspec(dllimport)
#define LIBEVORAL_DLL_EXPORT __declspec(dllexport) #define LIBEVORAL_DLL_EXPORT __declspec(dllexport)
#define LIBEVORAL_DLL_LOCAL #define LIBEVORAL_DLL_LOCAL
#define LIBEVORAL_TEMPLATE_DLL_IMPORT #define LIBEVORAL_TEMPLATE_DLL_IMPORT __declspec(dllimport)
#define LIBEVORAL_TEMPLATE_DLL_EXPORT #define LIBEVORAL_TEMPLATE_DLL_EXPORT __declspec(dllexport)
#else #else
#define LIBEVORAL_DLL_IMPORT __attribute__ ((visibility ("default"))) #define LIBEVORAL_DLL_IMPORT __attribute__ ((visibility ("default")))
#define LIBEVORAL_DLL_EXPORT __attribute__ ((visibility ("default"))) #define LIBEVORAL_DLL_EXPORT __attribute__ ((visibility ("default")))

View file

@ -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 /* this should be allocated by malloc(3) because libsmf will
call free(3) on it 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[0] = 0xff; // Meta-event
event->midi_buffer[1] = 0x7f; // Sequencer-specific event->midi_buffer[1] = 0x7f; // Sequencer-specific

View file

@ -5,50 +5,31 @@
#include <signal.h> #include <signal.h>
#include <pthread.h> #include <pthread.h>
#include "ardour/libardour_visibility.h"
#include "ardour/vst_types.h" #include "ardour/vst_types.h"
#include "ardour/vestige/aeffectx.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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
extern int fst_init (void* possible_hmodule); LIBARDOUR_API int fst_init (void* possible_hmodule);
extern void fst_exit (void); LIBARDOUR_API void fst_exit (void);
extern VSTHandle* fst_load (const char*); LIBARDOUR_API VSTHandle* fst_load (const char*);
extern int fst_unload (VSTHandle**); LIBARDOUR_API int fst_unload (VSTHandle**);
extern VSTState * fst_instantiate (VSTHandle *, audioMasterCallback amc, void* userptr); LIBARDOUR_API VSTState * fst_instantiate (VSTHandle *, audioMasterCallback amc, void* userptr);
extern void fst_close (VSTState *); LIBARDOUR_API void fst_close (VSTState *);
extern int fst_run_editor (VSTState *, void* window_parent); LIBARDOUR_API int fst_run_editor (VSTState *, void* window_parent);
extern void fst_destroy_editor (VSTState *); LIBARDOUR_API void fst_destroy_editor (VSTState *);
extern void fst_move_window_into_view (VSTState *); LIBARDOUR_API void fst_move_window_into_view (VSTState *);
extern void fst_event_loop_remove_plugin (VSTState* fst); LIBARDOUR_API void fst_event_loop_remove_plugin (VSTState* fst);
extern void fst_start_threading(void); LIBARDOUR_API void fst_start_threading(void);
extern void fst_stop_threading(void); LIBARDOUR_API void fst_stop_threading(void);
extern void fst_audio_master_idle(void); LIBARDOUR_API void fst_audio_master_idle(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -2,16 +2,16 @@
#include <string.h> #include <string.h>
#include <windows.h> #include <windows.h>
#define fst_error(...) fprintf(stderr, __VA_ARGS__)
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
#include <pthread.h> #include <pthread.h>
static UINT_PTR idle_timer_id = 0; static UINT_PTR idle_timer_id = 0;
extern char *basename(char *path);
#else /* linux + wine */ #else /* linux + wine */
#include <linux/limits.h> // PATH_MAX #include <linux/limits.h> // PATH_MAX
#include <libgen.h> // basename
#include <winnt.h> #include <winnt.h>
#include <wine/exception.h> #include <wine/exception.h>
#include <pthread.h> #include <pthread.h>
@ -489,9 +489,8 @@ fst_load (const char *path)
if ((strlen(path)) && (NULL != (fhandle = fst_handle_new ()))) if ((strlen(path)) && (NULL != (fhandle = fst_handle_new ())))
{ {
char* period; char* period;
fhandle->nameptr = strdup (path);
fhandle->path = strdup (path); fhandle->path = strdup (path);
fhandle->name = basename(fhandle->nameptr); fhandle->name = g_path_get_basename(path);
if ((period = strrchr (fhandle->name, '.'))) { if ((period = strrchr (fhandle->name, '.'))) {
*period = '\0'; *period = '\0';
} }
@ -502,10 +501,10 @@ fst_load (const char *path)
return NULL; 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 == 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); 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; //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; (*fhandle)->path = NULL;
} }
if ((*fhandle)->nameptr) { if ((*fhandle)->name) {
free ((*fhandle)->nameptr); free ((*fhandle)->name);
(*fhandle)->nameptr = NULL;
(*fhandle)->name = NULL; (*fhandle)->name = NULL;
} }

View file

@ -59,7 +59,6 @@ def build(bld):
obj = bld (features = 'c cxx cxxprogram wine') obj = bld (features = 'c cxx cxxprogram wine')
obj.source = ( obj.source = (
'scanner.cc', 'scanner.cc',
'fst.c',
'vstwin.c', 'vstwin.c',
) )
obj.linkflags = ['-mwindows', '-Wl,--export-dynamic'] obj.linkflags = ['-mwindows', '-Wl,--export-dynamic']
@ -69,7 +68,7 @@ def build(bld):
else: else:
obj = bld (features = 'cxx c cxxprogram') obj = bld (features = 'cxx c cxxprogram')
if bld.is_defined('WINDOWS_VST_SUPPORT'): 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'] obj.uselib = ['GIOMM', 'DL', 'GDI32']
else: else:
obj.source = ( 'scanner.cc' ) obj.source = ( 'scanner.cc' )

View file

@ -94,3 +94,38 @@ PBD::clear_directory (const string& dir, size_t* size, vector<string>* paths)
return ret; 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;
}
}

View file

@ -78,9 +78,10 @@ PBD::set_debug_bits (uint64_t bits)
int int
PBD::parse_debug_options (const char* str) PBD::parse_debug_options (const char* str)
{ {
string in_str = str;
typedef boost::tokenizer<boost::char_separator<char> > tokenizer; typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep (","); boost::char_separator<char> sep (",");
tokenizer tokens (string(str), sep); tokenizer tokens (in_str, sep);
uint64_t bits = 0; uint64_t bits = 0;
for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) { for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {

View file

@ -131,19 +131,26 @@ EnvironmentalProtectionAgency::restore () const
void void
EnvironmentalProtectionAgency::clear () const 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]; for (size_t i = 0; environ[i]; ++i) {
string::size_type equal = estring.find_first_of ('='); 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) { if (equal == string::npos) {
/* say what? an environ value without = ? */ /* say what? an environ value without = ? */
continue; continue;
} }
string before = estring.substr (0, equal); string var_name = (*e).substr (0, equal);
g_unsetenv(before.c_str()); g_unsetenv(var_name.c_str());
} }
} }

View file

@ -31,7 +31,20 @@
#include <glibmm/miscutils.h> #include <glibmm/miscutils.h>
#include <glibmm/pattern.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/compose.h"
#include "pbd/file_utils.h" #include "pbd/file_utils.h"
@ -153,21 +166,57 @@ copy_file(const std::string & from_path, const std::string & to_path)
{ {
if (!Glib::file_test (from_path, Glib::FILE_TEST_EXISTS)) return false; 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); int fd_from = -1;
Glib::RefPtr<Gio::File> to_file = Gio::File::create_for_path(to_path); int fd_to = -1;
char buf[4096]; // BUFSIZ ??
ssize_t nread;
try fd_from = ::open(from_path.c_str(), O_RDONLY);
{ if (fd_from < 0) {
from_file->copy (to_file, Gio::FILE_COPY_OVERWRITE); goto copy_error;
} }
catch(const Glib::Exception& ex)
{ fd_to = ::open(to_path.c_str(), O_WRONLY | O_CREAT, 0666);
error << string_compose (_("Unable to Copy file %1 to %2 (%3)"), if (fd_to < 0) {
from_path, to_path, ex.what()) goto copy_error;
<< endmsg;
return false;
} }
return true;
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, strerror(saved_errno))
<< endmsg;
return false;
} }
static static
@ -195,8 +244,8 @@ copy_files(const std::string & from_path, const std::string & to_dir)
std::string std::string
get_absolute_path (const std::string & p) get_absolute_path (const std::string & p)
{ {
Glib::RefPtr<Gio::File> f = Gio::File::create_for_path (p); if (Glib::path_is_absolute(p)) return p;
return f->get_path (); return Glib::build_filename (Glib::get_current_dir(), p);
} }
bool bool

View file

@ -174,7 +174,7 @@ PBD::search_path_expand (string path)
vector<string> s; vector<string> s;
vector<string> n; vector<string> n;
split (path, s, ':'); split (path, s, G_SEARCHPATH_SEPARATOR);
for (vector<string>::iterator i = s.begin(); i != s.end(); ++i) { for (vector<string>::iterator i = s.begin(); i != s.end(); ++i) {
string exp = path_expand (*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) { for (vector<string>::iterator i = n.begin(); i != n.end(); ++i) {
if (!r.empty()) { if (!r.empty()) {
r += ':'; r += G_SEARCHPATH_SEPARATOR;
} }
r += *i; r += *i;
} }

View file

@ -170,7 +170,7 @@ PathScanner::run_scan_internal (vector<string *> *result,
} }
closedir (dir); closedir (dir);
} while ((limit < 0 || (nfound < limit)) && (thisdir = strtok (0, ":"))); } while ((limit < 0 || (nfound < limit)) && (thisdir = strtok (0, G_SEARCHPATH_SEPARATOR_S)));
free (pathcopy); free (pathcopy);
return result; return result;

View file

@ -46,7 +46,7 @@ cleanup_request_buffer (void* ptr)
/* this is called when the thread for which this request buffer was /* 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 * 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 * We are not modifying the UI's thread/buffer map, just marking it
* dead. If the UI is currently processing the buffers and misses * dead. If the UI is currently processing the buffers and misses

View file

@ -28,6 +28,7 @@
namespace PBD { namespace PBD {
LIBPBD_API int clear_directory (const std::string&, size_t* = 0, std::vector<std::string>* = 0); 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__ */ #endif /* __pbd_clear_dir_h__ */

View file

@ -133,7 +133,7 @@ export_search_path (const string& base_dir, const char* varname, const char* dir
if (cstr) { if (cstr) {
path = cstr; path = cstr;
path += ':'; path += G_SEARCHPATH_SEPARATOR;
} else { } else {
path = ""; path = "";
} }

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