mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-19 13:16:27 +01:00
[Summary] Merging from GIT
[Details] Starting point: Mar 24 2014, 11:47 PM Commit:87184ab80dTarget point: Commit:59e6694405Apr 16 2014, 4:01 PM [git-p4: depot-paths = "//Abdaw/dev_main/tracks/": change = 453690]
This commit is contained in:
parent
0046ee6488
commit
ce2a519afa
103 changed files with 2160 additions and 915 deletions
|
|
@ -85,15 +85,15 @@ ActionManager::load_menus (const string& menus_file)
|
||||||
info << string_compose (_("Loading menus from %1"), ui_file) << endmsg;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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; }
|
||||||
|
|
|
||||||
|
|
@ -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")))));
|
||||||
|
|
|
||||||
|
|
@ -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 ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
497
gtk2_ardour/bundle_env_msvc.cc
Normal file
497
gtk2_ardour/bundle_env_msvc.cc
Normal file
|
|
@ -0,0 +1,497 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2014 John Emmas
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "bundle_env.h"
|
||||||
|
#include "i18n.h"
|
||||||
|
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <glibmm.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
|
||||||
|
#include <fontconfig/fontconfig.h>
|
||||||
|
|
||||||
|
#include "ardour/ardour.h"
|
||||||
|
#include "ardour/search_paths.h"
|
||||||
|
#include "ardour/filesystem_paths.h"
|
||||||
|
|
||||||
|
#include "pbd/file_utils.h"
|
||||||
|
#include "pbd/epa.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace PBD;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
std::string
|
||||||
|
get_windows_drive_volume_letter()
|
||||||
|
{
|
||||||
|
static std::string ret;
|
||||||
|
char path[PATH_MAX+1];
|
||||||
|
LPITEMIDLIST pidl = 0;
|
||||||
|
|
||||||
|
if (!ret.length()) {
|
||||||
|
if (S_OK == SHGetSpecialFolderLocation (0, CSIDL_WINDOWS, &pidl))
|
||||||
|
{
|
||||||
|
if (SHGetPathFromIDListA (pidl, path)) {
|
||||||
|
path[2] = '\0'; // Gives us just the drive letter and colon
|
||||||
|
ret = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoTaskMemFree (pidl);
|
||||||
|
}
|
||||||
|
// The above should never fail - but just in case...
|
||||||
|
else if (char *env_path = getenv ("windir"))
|
||||||
|
{
|
||||||
|
strcpy (path, env_path);
|
||||||
|
path[2] = '\0'; // Gives us just the drive letter and colon
|
||||||
|
ret = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string
|
||||||
|
get_module_folder ()
|
||||||
|
{
|
||||||
|
std::string ret;
|
||||||
|
|
||||||
|
// Gives the top-level Ardour installation folder (on Windows)
|
||||||
|
// Typically, this will be somehwere like "C:\Program Files"
|
||||||
|
|
||||||
|
gchar* pExeRoot = g_win32_get_package_installation_directory_of_module (0);
|
||||||
|
|
||||||
|
if (0 == pExeRoot) {
|
||||||
|
pExeRoot = g_build_filename("C:\\", "Program Files", PROGRAM_NAME, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pExeRoot) {
|
||||||
|
gchar tmp[PATH_MAX+1];
|
||||||
|
gchar* p;
|
||||||
|
|
||||||
|
strcpy(tmp, pExeRoot);
|
||||||
|
if (0 != (p = strrchr (tmp, G_DIR_SEPARATOR))) {
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
if (0 != (p = g_build_filename(tmp, 0))) {
|
||||||
|
ret = p;
|
||||||
|
g_free (p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (pExeRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
fixup_config_file (Glib::ustring str_file_to_fix)
|
||||||
|
{
|
||||||
|
FILE* fd;
|
||||||
|
char buf[4096];
|
||||||
|
bool conversion_needed = false;
|
||||||
|
bool succeeded = false;
|
||||||
|
|
||||||
|
fstream file_to_fix (fd = g_fopen(str_file_to_fix.c_str(), "r+b"));
|
||||||
|
|
||||||
|
if (file_to_fix.is_open()) {
|
||||||
|
vector<std::string> lines;
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
file_to_fix.seekg (0, std::ios::beg);
|
||||||
|
file_to_fix.seekp (0, std::ios::beg);
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (!file_to_fix.eof() && file_to_fix.getline (buf, sizeof(buf))) {
|
||||||
|
line = buf;
|
||||||
|
|
||||||
|
if (!conversion_needed && (std::string::npos != line.find("$(")))
|
||||||
|
conversion_needed = true;
|
||||||
|
lines.push_back(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conversion_needed) {
|
||||||
|
bool error = false;
|
||||||
|
std::string::size_type token_begin, token_end;
|
||||||
|
vector<string>::iterator i;
|
||||||
|
|
||||||
|
for (i = lines.begin(); i != lines.end(); ++i) {
|
||||||
|
if (string::npos != (token_begin = i->find("$("))) {
|
||||||
|
if (string::npos != (token_end = i->find(")", token_begin))) {
|
||||||
|
std::string str_replace_with;
|
||||||
|
std::string str_to_replace = i->substr(token_begin, ((token_end+1)-token_begin));
|
||||||
|
|
||||||
|
if (0 == str_to_replace.compare("$(CWD)")) {
|
||||||
|
// Replace our token with the current working directory
|
||||||
|
if (getcwd(buf, sizeof(buf))) {
|
||||||
|
if (buf[strlen(buf)-1] == G_DIR_SEPARATOR)
|
||||||
|
buf[strlen(buf)-1] = '\0';
|
||||||
|
str_replace_with = buf;
|
||||||
|
|
||||||
|
// Replace the first occurrence of our token with the required string
|
||||||
|
i->erase(token_begin, ((token_end+1)-token_begin));
|
||||||
|
i->insert(token_begin, str_replace_with);
|
||||||
|
} else {
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
} else if (0 == str_to_replace.compare("$(WINDRIVE)")){
|
||||||
|
// Replace our token with the drive letter (and colon) for the user's Windows volume
|
||||||
|
str_replace_with = get_windows_drive_volume_letter();
|
||||||
|
|
||||||
|
// Replace the first occurrence of our token with the required string
|
||||||
|
i->erase(token_begin, ((token_end+1)-token_begin));
|
||||||
|
i->insert(token_begin, str_replace_with);
|
||||||
|
} else {
|
||||||
|
// Assume that our token represents an environment variable
|
||||||
|
std::string envvar_name = str_to_replace.substr(2, str_to_replace.length()-3);
|
||||||
|
|
||||||
|
if (const char *envvar_value = getenv(envvar_name.c_str())) {
|
||||||
|
strcpy(buf, envvar_value);
|
||||||
|
if (buf[strlen(buf)-1] == G_DIR_SEPARATOR)
|
||||||
|
buf[strlen(buf)-1] = '\0';
|
||||||
|
str_replace_with = buf;
|
||||||
|
|
||||||
|
// Replace the first occurrence of our token with the required string
|
||||||
|
i->erase(token_begin, ((token_end+1)-token_begin));
|
||||||
|
i->insert(token_begin, str_replace_with);
|
||||||
|
} else {
|
||||||
|
error = true;
|
||||||
|
cerr << _("ERROR: unknown environment variable") << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
file_to_fix.clear (); // Clear the EOF flag etc
|
||||||
|
file_to_fix.seekg (0, std::ios::beg); // Seek our 'get' ptr to the file start pos
|
||||||
|
// (our 'put' ptr shouldn't have moved yet).
|
||||||
|
chsize(fileno (fd), 0); // Truncate the file, ready for re-writing
|
||||||
|
|
||||||
|
for (i = lines.begin(); i != lines.end(); ++i) {
|
||||||
|
|
||||||
|
// Write the converted contents to our file
|
||||||
|
file_to_fix << (*i).c_str() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
file_to_fix.close();
|
||||||
|
succeeded = true;
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
file_to_fix.close();
|
||||||
|
succeeded = true;
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
file_to_fix.close();
|
||||||
|
succeeded = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cerr << _("ERROR: Could not open config file '") << str_file_to_fix << "'" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fixup_fonts_config ()
|
||||||
|
{
|
||||||
|
string fonts_conf_file;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fonts_conf_file = get_module_folder();
|
||||||
|
|
||||||
|
if (!fonts_conf_file.empty()) {
|
||||||
|
fonts_conf_file += "\\";
|
||||||
|
fonts_conf_file += PROGRAM_NAME;
|
||||||
|
fonts_conf_file += FONTS_CONF_LOCATION;
|
||||||
|
#else
|
||||||
|
if (PBD::find_file_in_search_path (ARDOUR::ardour_config_search_path(), "fonts.conf", fonts_conf_file)) {
|
||||||
|
#endif
|
||||||
|
Glib::setenv ("FONTCONFIG_FILE", fonts_conf_file, true);
|
||||||
|
|
||||||
|
if (0 == fixup_config_file (fonts_conf_file))
|
||||||
|
cerr << _("ERROR: processing error for 'fonts.conf' file") << endl;
|
||||||
|
} else {
|
||||||
|
cerr << _("ERROR: Malformed module folder (fonts.conf)") << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fixup_pango_config ()
|
||||||
|
{
|
||||||
|
string pango_modules_file;
|
||||||
|
|
||||||
|
#if defined(DEBUG) || defined(RDC_BUILD)
|
||||||
|
// Make sure we pick up the debuggable DLLs !!!
|
||||||
|
pango_modules_file = get_module_folder();
|
||||||
|
|
||||||
|
if (!pango_modules_file.empty()) {
|
||||||
|
pango_modules_file += "\\";
|
||||||
|
pango_modules_file += PROGRAM_NAME;
|
||||||
|
pango_modules_file += PANGO_CONF_LOCATION;
|
||||||
|
#if 0
|
||||||
|
// JE - handy for non-English locale testing (Greek, in this case)
|
||||||
|
Glib::ustring pango_modules_path = Glib::locale_to_utf8("C:\\Program Files\\Mixbus3\\etc\\ÄÇÌÇÔÑÇÓ\\pango.modules");
|
||||||
|
/**/
|
||||||
|
#else
|
||||||
|
Glib::ustring pango_modules_path = pango_modules_file;
|
||||||
|
#endif
|
||||||
|
pango_modules_path.resize (pango_modules_path.size()-14); // Remove "/pango.modules" from the end
|
||||||
|
#else
|
||||||
|
if (PBD::find_file_in_search_path (ARDOUR::ardour_config_search_path(), "pango.modules", pango_modules_file)) {
|
||||||
|
|
||||||
|
Glib::ustring pango_modules_path = pango_modules_file;
|
||||||
|
pango_modules_path.resize (pango_modules_path.size()-14); // Remove "/pango.modules" from the end
|
||||||
|
#endif
|
||||||
|
// Set an environment variable so we can find our pango modules. Note
|
||||||
|
// that this requires a modified version of libpango (pango-utils.c)
|
||||||
|
Glib::setenv ("PANGO_MODULE_PATH", Glib::filename_from_utf8(pango_modules_path), true);
|
||||||
|
|
||||||
|
if (0 == fixup_config_file (pango_modules_file))
|
||||||
|
cerr << _("ERROR: processing error for 'pango.modules' file") << endl;
|
||||||
|
} else {
|
||||||
|
cerr << _("ERROR: Malformed module folder (pango.modules)") << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fixup_pixbuf_loaders_config ()
|
||||||
|
{
|
||||||
|
string gdk_pixbuf_loaders_file;
|
||||||
|
|
||||||
|
#if defined(DEBUG) || defined(RDC_BUILD)
|
||||||
|
// Make sure we pick up the debuggable DLLs !!!
|
||||||
|
gdk_pixbuf_loaders_file = get_module_folder();
|
||||||
|
|
||||||
|
if (!gdk_pixbuf_loaders_file.empty()) {
|
||||||
|
gdk_pixbuf_loaders_file += "\\";
|
||||||
|
gdk_pixbuf_loaders_file += PROGRAM_NAME;
|
||||||
|
gdk_pixbuf_loaders_file += PIXBUFLOADERS_CONF_LOCATION;
|
||||||
|
#else
|
||||||
|
if (PBD::find_file_in_search_path (ARDOUR::ardour_config_search_path(), "gdk-pixbuf.loaders", gdk_pixbuf_loaders_file)) {
|
||||||
|
#endif
|
||||||
|
// Set an environment variable so we can find our pixbuf modules.
|
||||||
|
Glib::setenv ("GDK_PIXBUF_MODULE_FILE", Glib::filename_from_utf8(gdk_pixbuf_loaders_file), true);
|
||||||
|
|
||||||
|
if (0 == fixup_config_file (gdk_pixbuf_loaders_file))
|
||||||
|
cerr << _("ERROR: processing error for 'gdk-pixbuf.loaders' file") << endl;
|
||||||
|
} else {
|
||||||
|
cerr << _("ERROR: Malformed module folder (gdk-pixbuf.loaders)") << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fixup_clearlooks_config ()
|
||||||
|
{
|
||||||
|
string clearlooks_la_file;
|
||||||
|
|
||||||
|
#if defined(DEBUG) || defined(RDC_BUILD)
|
||||||
|
// Make sure we pick up the debuggable DLLs !!!
|
||||||
|
clearlooks_la_file = get_module_folder();
|
||||||
|
|
||||||
|
if (!clearlooks_la_file.empty()) {
|
||||||
|
clearlooks_la_file += "\\";
|
||||||
|
clearlooks_la_file += PROGRAM_NAME;
|
||||||
|
clearlooks_la_file += CLEARLOOKS_CONF_LOCATION;
|
||||||
|
#else
|
||||||
|
if (PBD::find_file_in_search_path (ARDOUR::ardour_config_search_path(), "libclearlooks.la", clearlooks_la_file)) {
|
||||||
|
#endif
|
||||||
|
// Set an environment variable so we can find our clearlooks engine.
|
||||||
|
// Note that this requires a modified version of libgtk (gtkthemes.c)
|
||||||
|
Glib::setenv ("GTK_THEME_ENGINE_FILE", Glib::filename_from_utf8(clearlooks_la_file).c_str(), true);
|
||||||
|
|
||||||
|
if (0 == fixup_config_file (clearlooks_la_file))
|
||||||
|
cerr << _("ERROR: processing error for 'clearlooks.la' file") << endl;
|
||||||
|
} else {
|
||||||
|
cerr << _("ERROR: Malformed module folder (clearlooks.la)") << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fixup_bundle_environment (int argc, char* argv[], const char** localedir)
|
||||||
|
{
|
||||||
|
std::string exec_path = argv[0];
|
||||||
|
std::string dir_path = Glib::path_get_dirname (exec_path);
|
||||||
|
|
||||||
|
// Make sure that our runtime CWD is set to Mixbus's install
|
||||||
|
// folder, regardless of where the caller's CWD was set to.
|
||||||
|
g_chdir (dir_path.c_str());
|
||||||
|
|
||||||
|
EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true));
|
||||||
|
|
||||||
|
// Now set 'dir_path' so we can append some relative paths
|
||||||
|
dir_path = Glib::path_get_dirname (dir_path);
|
||||||
|
|
||||||
|
std::string path;
|
||||||
|
const char *cstr;
|
||||||
|
|
||||||
|
// First, set up 'ARDOUR_DLL_PATH'
|
||||||
|
path = dir_path;
|
||||||
|
path += "\\lib\\ardour3\\surfaces;";
|
||||||
|
path += dir_path;
|
||||||
|
path += "\\lib\\ardour3\\panners;";
|
||||||
|
path += dir_path;
|
||||||
|
path += "\\lib\\ardour3\\backends;";
|
||||||
|
path += dir_path;
|
||||||
|
path += "\\bin";
|
||||||
|
Glib::setenv ("ARDOUR_DLL_PATH", path, true);
|
||||||
|
|
||||||
|
|
||||||
|
// Next, set up 'ARDOUR_DATA_PATH'
|
||||||
|
path = get_module_folder() + "\\";
|
||||||
|
path += PROGRAM_NAME;
|
||||||
|
path += "\\share";
|
||||||
|
Glib::setenv ("ARDOUR_DATA_PATH", path, true);
|
||||||
|
|
||||||
|
|
||||||
|
// Next, set up 'ARDOUR_CONFIG_PATH'
|
||||||
|
#ifdef _WIN64
|
||||||
|
path = user_config_directory() + "\\win64;";
|
||||||
|
#else
|
||||||
|
path = user_config_directory() + "\\win32;";
|
||||||
|
#endif
|
||||||
|
Glib::setenv ("ARDOUR_CONFIG_PATH", path, true);
|
||||||
|
|
||||||
|
|
||||||
|
// Next, set up 'ARDOUR_PATH'
|
||||||
|
path = user_config_directory();
|
||||||
|
path = Glib::path_get_dirname (path);
|
||||||
|
path += G_SEARCHPATH_SEPARATOR;
|
||||||
|
path += windows_search_path().to_string();
|
||||||
|
path += "\\icons;";
|
||||||
|
path += windows_search_path().to_string();
|
||||||
|
path += "\\pixmaps;";
|
||||||
|
path += ardour_data_search_path().to_string(); // In fact, adds both the 'data' search
|
||||||
|
path += G_SEARCHPATH_SEPARATOR; // path and our 'config' search path
|
||||||
|
path += dir_path;
|
||||||
|
path += "\\etc";
|
||||||
|
Glib::setenv ("ARDOUR_PATH", path, true);
|
||||||
|
|
||||||
|
|
||||||
|
// Next, set up 'ARDOUR_INSTANT_XML_PATH'
|
||||||
|
path = user_config_directory();
|
||||||
|
Glib::setenv ("ARDOUR_INSTANT_XML_PATH", path, true);
|
||||||
|
|
||||||
|
|
||||||
|
// Next, set up 'LADSPA_PATH'
|
||||||
|
path = ladspa_search_path().to_string();
|
||||||
|
Glib::setenv ("LADSPA_PATH", path, true);
|
||||||
|
|
||||||
|
|
||||||
|
// Next, set up 'VAMP_PATH'
|
||||||
|
cstr = getenv ("VAMP_PATH");
|
||||||
|
if (cstr) {
|
||||||
|
path = cstr;
|
||||||
|
path += G_SEARCHPATH_SEPARATOR;
|
||||||
|
} else {
|
||||||
|
path = "";
|
||||||
|
}
|
||||||
|
path += get_module_folder() + "\\";
|
||||||
|
path += PROGRAM_NAME;
|
||||||
|
path += "\\bin\\vamp";
|
||||||
|
path += G_SEARCHPATH_SEPARATOR;
|
||||||
|
path += "%ProgramFiles%\\Vamp Plugins";
|
||||||
|
Glib::setenv ("VAMP_PATH", path, true);
|
||||||
|
|
||||||
|
|
||||||
|
// Next, set up 'ARDOUR_CONTROL_SURFACE_PATH'
|
||||||
|
cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
|
||||||
|
if (cstr) {
|
||||||
|
path = cstr;
|
||||||
|
path += G_SEARCHPATH_SEPARATOR;
|
||||||
|
} else {
|
||||||
|
path = "";
|
||||||
|
}
|
||||||
|
path += control_protocol_search_path().to_string();
|
||||||
|
Glib::setenv ("ARDOUR_CONTROL_SURFACE_PATH", path, true);
|
||||||
|
|
||||||
|
|
||||||
|
// Next, set up 'GTK_LOCALEDIR'
|
||||||
|
if (ARDOUR::translations_are_enabled ()) {
|
||||||
|
path = windows_search_path().to_string();
|
||||||
|
path += "\\locale";
|
||||||
|
Glib::setenv ("GTK_LOCALEDIR", path, true);
|
||||||
|
|
||||||
|
// and return the same path to our caller
|
||||||
|
(*localedir) = strdup (path.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Next, set up 'GTK_PATH'
|
||||||
|
cstr = getenv ("GTK_PATH");
|
||||||
|
if (cstr) {
|
||||||
|
path = cstr;
|
||||||
|
path += G_SEARCHPATH_SEPARATOR;
|
||||||
|
} else {
|
||||||
|
path = "";
|
||||||
|
}
|
||||||
|
path += user_config_directory();
|
||||||
|
path += "\\.gtk-2.0";
|
||||||
|
Glib::setenv ("GTK_PATH", path, true);
|
||||||
|
|
||||||
|
|
||||||
|
// Unset GTK_RC_FILES so that we only load the RC files that we define
|
||||||
|
Glib::unsetenv ("GTK_RC_FILES");
|
||||||
|
|
||||||
|
|
||||||
|
// and set a '$HOME' environment variable. This variable changes the value returned
|
||||||
|
// by 'g_get_home_dir()' so to prevent that function from unexpectedly changing its
|
||||||
|
// mind, we'll set '$HOME' to whatever 'g_get_home_dir()' is already returning!!
|
||||||
|
if (NULL == getenv("HOME")) {
|
||||||
|
Glib::setenv ("HOME", Glib::locale_from_utf8(g_get_home_dir()), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
fixup_fonts_config();
|
||||||
|
fixup_pango_config();
|
||||||
|
fixup_clearlooks_config();
|
||||||
|
fixup_pixbuf_loaders_config();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void load_custom_fonts()
|
||||||
|
{
|
||||||
|
std::string ardour_mono_file;
|
||||||
|
|
||||||
|
if (!find_file_in_search_path (ardour_data_search_path(), "ArdourMono.ttf", ardour_mono_file)) {
|
||||||
|
cerr << _("Cannot find ArdourMono TrueType font") << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
FcConfig *config = FcInitLoadConfigAndFonts();
|
||||||
|
FcBool ret = FcConfigAppFontAddFile(config, reinterpret_cast<const FcChar8*>(ardour_mono_file.c_str()));
|
||||||
|
|
||||||
|
if (ret == FcFalse) {
|
||||||
|
cerr << _("Cannot load ArdourMono TrueType font.") << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = FcConfigSetCurrent(config);
|
||||||
|
|
||||||
|
if (ret == FcFalse) {
|
||||||
|
cerr << _("Failed to set fontconfig configuration.") << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -167,6 +167,7 @@
|
||||||
<Binding action="Editor/pitch-shift-region" key="F5"/>
|
<Binding action="Editor/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"/>
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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"));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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*/)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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" "")
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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__ */
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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__
|
||||||
|
|
|
||||||
|
|
@ -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 (
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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)) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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'):
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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 *);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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).
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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*/)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 ();
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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> (
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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")))
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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' )
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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__ */
|
||||||
|
|
|
||||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue