export range markers patch (revisited), change selection model, copy-drag tempo+meter marker patch
git-svn-id: svn://localhost/trunk/ardour2@349 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
caeb564748
commit
5a39bf595c
@ -61,7 +61,6 @@ about.cc
|
||||
actions.cc
|
||||
add_route_dialog.cc
|
||||
ardour_dialog.cc
|
||||
ardour_message.cc
|
||||
ardour_ui.cc
|
||||
ardour_ui2.cc
|
||||
ardour_ui_dependents.cc
|
||||
@ -113,6 +112,9 @@ editor_selection_list.cc
|
||||
editor_tempodisplay.cc
|
||||
editor_timefx.cc
|
||||
export_dialog.cc
|
||||
export_session_dialog.cc
|
||||
export_region_dialog.cc
|
||||
export_range_markers_dialog.cc
|
||||
gain_automation_time_axis.cc
|
||||
gain_meter.cc
|
||||
ghostregion.cc
|
||||
|
@ -42,9 +42,14 @@ using namespace sigc;
|
||||
|
||||
vector<RefPtr<Gtk::Action> > ActionManager::session_sensitive_actions;
|
||||
vector<RefPtr<Gtk::Action> > ActionManager::region_list_selection_sensitive_actions;
|
||||
vector<RefPtr<Gtk::Action> > ActionManager::plugin_selection_sensitive_actions;
|
||||
vector<RefPtr<Gtk::Action> > ActionManager::region_selection_sensitive_actions;
|
||||
vector<RefPtr<Gtk::Action> > ActionManager::track_selection_sensitive_actions;
|
||||
vector<RefPtr<Gtk::Action> > ActionManager::plugin_selection_sensitive_actions;
|
||||
vector<RefPtr<Gtk::Action> > ActionManager::point_selection_sensitive_actions;
|
||||
vector<RefPtr<Gtk::Action> > ActionManager::time_selection_sensitive_actions;
|
||||
vector<RefPtr<Gtk::Action> > ActionManager::line_selection_sensitive_actions;
|
||||
vector<RefPtr<Gtk::Action> > ActionManager::playlist_selection_sensitive_actions;
|
||||
|
||||
vector<RefPtr<Gtk::Action> > ActionManager::range_sensitive_actions;
|
||||
vector<RefPtr<Gtk::Action> > ActionManager::jack_sensitive_actions;
|
||||
vector<RefPtr<Gtk::Action> > ActionManager::jack_opposite_sensitive_actions;
|
||||
|
@ -22,9 +22,15 @@ class ActionManager
|
||||
|
||||
static std::vector<Glib::RefPtr<Gtk::Action> > session_sensitive_actions;
|
||||
static std::vector<Glib::RefPtr<Gtk::Action> > region_list_selection_sensitive_actions;
|
||||
static std::vector<Glib::RefPtr<Gtk::Action> > plugin_selection_sensitive_actions;
|
||||
|
||||
static std::vector<Glib::RefPtr<Gtk::Action> > region_selection_sensitive_actions;
|
||||
static std::vector<Glib::RefPtr<Gtk::Action> > track_selection_sensitive_actions;
|
||||
static std::vector<Glib::RefPtr<Gtk::Action> > plugin_selection_sensitive_actions;
|
||||
static std::vector<Glib::RefPtr<Gtk::Action> > point_selection_sensitive_actions;
|
||||
static std::vector<Glib::RefPtr<Gtk::Action> > time_selection_sensitive_actions;
|
||||
static std::vector<Glib::RefPtr<Gtk::Action> > line_selection_sensitive_actions;
|
||||
static std::vector<Glib::RefPtr<Gtk::Action> > playlist_selection_sensitive_actions;
|
||||
|
||||
static std::vector<Glib::RefPtr<Gtk::Action> > range_sensitive_actions;
|
||||
static std::vector<Glib::RefPtr<Gtk::Action> > transport_sensitive_actions;
|
||||
static std::vector<Glib::RefPtr<Gtk::Action> > jack_sensitive_actions;
|
||||
|
@ -15,7 +15,8 @@
|
||||
<separator/>
|
||||
<menu name='Export' action='Export'>
|
||||
<menuitem action='ExportSession'/>
|
||||
<menuitem action='ExportRange'/>
|
||||
<menuitem action='ExportSelection'/>
|
||||
<menuitem action='ExportRangeMarkers'/>
|
||||
</menu>
|
||||
<separator/>
|
||||
<menu name='Cleanup' action='Cleanup'>
|
||||
|
@ -28,6 +28,8 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <gtkmm/messagedialog.h>
|
||||
|
||||
#include <pbd/error.h>
|
||||
#include <pbd/compose.h>
|
||||
#include <pbd/basename.h>
|
||||
@ -58,7 +60,6 @@
|
||||
|
||||
#include "actions.h"
|
||||
#include "ardour_ui.h"
|
||||
#include "ardour_message.h"
|
||||
#include "public_editor.h"
|
||||
#include "audio_clock.h"
|
||||
#include "keyboard.h"
|
||||
@ -219,7 +220,8 @@ because it has no input connections.\n\
|
||||
You would be wasting space recording silence."),
|
||||
ds->name());
|
||||
|
||||
ArdourMessage message (editor, X_("cannotrecord"), msg);
|
||||
MessageDialog message (*editor, msg);
|
||||
message.run ();
|
||||
}
|
||||
|
||||
void
|
||||
@ -402,11 +404,12 @@ ARDOUR_UI::finish()
|
||||
/* use the default name */
|
||||
if (save_state_canfail ("")) {
|
||||
/* failed - don't quit */
|
||||
ArdourMessage (editor, X_("badsave dialog"),
|
||||
MessageDialog msg (*editor,
|
||||
_("\
|
||||
Ardour was unable to save your session.\n\n\
|
||||
If you still wish to quit, please use the\n\n\
|
||||
\"Just quit\" option."));
|
||||
msg.run ();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -936,11 +939,12 @@ ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t o
|
||||
}
|
||||
|
||||
catch (...) {
|
||||
ArdourMessage msg (editor, X_("noport dialog"),
|
||||
MessageDialog msg (*editor,
|
||||
_("There are insufficient JACK ports available\n\
|
||||
to create a new track or bus.\n\
|
||||
You should save Ardour, exit and\n\
|
||||
restart JACK with more ports."));
|
||||
msg.run ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1044,7 +1048,8 @@ ARDOUR_UI::transport_record ()
|
||||
case Session::Disabled:
|
||||
if (session->ntracks() == 0) {
|
||||
string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
|
||||
ArdourMessage msg (editor, X_("cannotrecenable"), txt);
|
||||
MessageDialog msg (*editor, txt);
|
||||
msg.run ();
|
||||
return;
|
||||
}
|
||||
session->maybe_enable_record ();
|
||||
@ -1278,12 +1283,13 @@ ARDOUR_UI::engine_halted ()
|
||||
|
||||
update_sample_rate (0);
|
||||
|
||||
ArdourMessage msg (editor, X_("halted"),
|
||||
MessageDialog msg (*editor,
|
||||
_("\
|
||||
JACK has either been shutdown or it\n\
|
||||
disconnected Ardour because Ardour\n\
|
||||
was not fast enough. You can save the\n\
|
||||
session and/or try to reconnect to JACK ."));
|
||||
msg.run ();
|
||||
}
|
||||
|
||||
int32_t
|
||||
@ -1781,9 +1787,10 @@ ARDOUR_UI::load_session (const string & path, const string & snap_name, string*
|
||||
/* if it already exists, we must have write access */
|
||||
|
||||
if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
|
||||
ArdourMessage msg (editor, X_("noaccess dialog"), _("\
|
||||
MessageDialog msg (*editor, _("\
|
||||
You do not have write access to this session.\n\
|
||||
This prevents the session from being loaded."));
|
||||
msg.run ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1901,12 +1908,13 @@ ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* l
|
||||
removed = rep.paths.size();
|
||||
|
||||
if (removed == 0) {
|
||||
ArdourMessage msg (editor, X_("cleanupresults"),
|
||||
MessageDialog msg (*editor, X_("cleanupresults"),
|
||||
_("\
|
||||
No audio files were ready for cleanup\n\n\
|
||||
If this seems suprising, check for any existing\n\
|
||||
snapshots. These may still include regions that\n\
|
||||
require some unused files to continue to exist."));
|
||||
msg.run ();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2150,8 +2158,9 @@ ARDOUR_UI::halt_on_xrun_message ()
|
||||
{
|
||||
ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
|
||||
|
||||
ArdourMessage msg (editor, X_("haltonxrun"),
|
||||
MessageDialog msg (*editor,
|
||||
_("Recording was stopped because your system could not keep up."));
|
||||
msg.run ();
|
||||
}
|
||||
|
||||
void
|
||||
@ -2173,12 +2182,13 @@ ARDOUR_UI::disk_overrun_handler ()
|
||||
|
||||
if (!have_disk_overrun_displayed) {
|
||||
have_disk_overrun_displayed = true;
|
||||
ArdourMessage msg (editor, X_("diskrate dialog"), _("\
|
||||
MessageDialog msg (*editor, X_("diskrate dialog"), _("\
|
||||
The disk system on your computer\n\
|
||||
was not able to keep up with Ardour.\n\
|
||||
\n\
|
||||
Specifically, it failed to write data to disk\n\
|
||||
quickly enough to keep up with recording.\n"));
|
||||
msg.run ();
|
||||
have_disk_overrun_displayed = false;
|
||||
}
|
||||
}
|
||||
@ -2190,12 +2200,13 @@ ARDOUR_UI::disk_underrun_handler ()
|
||||
|
||||
if (!have_disk_underrun_displayed) {
|
||||
have_disk_underrun_displayed = true;
|
||||
ArdourMessage msg (editor, X_("diskrate2 dialog"),
|
||||
MessageDialog msg (*editor,
|
||||
(_("The disk system on your computer\n\
|
||||
was not able to keep up with Ardour.\n\
|
||||
\n\
|
||||
Specifically, it failed to read data from disk\n\
|
||||
quickly enough to keep up with playback.\n")));
|
||||
msg.run ();
|
||||
have_disk_underrun_displayed = false;
|
||||
}
|
||||
}
|
||||
@ -2248,8 +2259,8 @@ ARDOUR_UI::disconnect_from_jack ()
|
||||
{
|
||||
if (engine) {
|
||||
if( engine->disconnect_from_jack ()) {
|
||||
ArdourMessage msg (editor, X_("nojack dialog"),
|
||||
_("Could not disconnect from JACK"));
|
||||
MessageDialog msg (*editor, _("Could not disconnect from JACK"));
|
||||
msg.run ();
|
||||
}
|
||||
|
||||
update_sample_rate (0);
|
||||
@ -2261,8 +2272,8 @@ ARDOUR_UI::reconnect_to_jack ()
|
||||
{
|
||||
if (engine) {
|
||||
if (engine->reconnect_to_jack ()) {
|
||||
ArdourMessage msg (editor, X_("nojack dialog"),
|
||||
_("Could not reconnect to JACK"));
|
||||
MessageDialog msg (*editor, _("Could not reconnect to JACK"));
|
||||
msg.run ();
|
||||
}
|
||||
|
||||
update_sample_rate (0);
|
||||
|
@ -587,6 +587,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
|
||||
|
||||
LocationUI *location_ui;
|
||||
int create_location_ui ();
|
||||
void handle_locations_change (ARDOUR::Location*);
|
||||
|
||||
ColorManager* color_manager;
|
||||
|
||||
|
@ -53,6 +53,24 @@ ARDOUR_UI::connect_to_session (Session *s)
|
||||
/* sensitize menu bar options that are now valid */
|
||||
|
||||
ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true);
|
||||
|
||||
if (session->locations()->num_range_markers()) {
|
||||
ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
|
||||
} else {
|
||||
ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
|
||||
}
|
||||
|
||||
/* there are never any selections on startup */
|
||||
|
||||
ActionManager::set_sensitive (ActionManager::region_selection_sensitive_actions, false);
|
||||
ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
|
||||
ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, false);
|
||||
ActionManager::set_sensitive (ActionManager::line_selection_sensitive_actions, false);
|
||||
ActionManager::set_sensitive (ActionManager::point_selection_sensitive_actions, false);
|
||||
ActionManager::set_sensitive (ActionManager::playlist_selection_sensitive_actions, false);
|
||||
|
||||
session->locations()->added.connect (mem_fun (*this, &ARDOUR_UI::handle_locations_change));
|
||||
session->locations()->removed.connect (mem_fun (*this, &ARDOUR_UI::handle_locations_change));
|
||||
|
||||
rec_button.set_sensitive (true);
|
||||
shuttle_box.set_sensitive (true);
|
||||
@ -366,3 +384,14 @@ ARDOUR_UI::toggle_sound_file_browser ()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ARDOUR_UI::handle_locations_change (Location* ignored)
|
||||
{
|
||||
if (session) {
|
||||
if (session->locations()->num_range_markers()) {
|
||||
ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
|
||||
} else {
|
||||
ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,8 +110,13 @@ ARDOUR_UI::install_actions ()
|
||||
act = ActionManager::register_action (main_actions, X_("ExportSession"), _("Export session to audiofile..."), mem_fun (*editor, &PublicEditor::export_session));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
|
||||
act = ActionManager::register_action (main_actions, X_("ExportRange"), _("Export range to audiofile..."), mem_fun (*editor, &PublicEditor::export_selection));
|
||||
act = ActionManager::register_action (main_actions, X_("ExportSelection"), _("Export selection to audiofile..."), mem_fun (*editor, &PublicEditor::export_selection));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
ActionManager::time_selection_sensitive_actions.push_back (act);
|
||||
|
||||
act = ActionManager::register_action (main_actions, X_("ExportRangeMarkers"), _("Export range markers to audiofile..."), mem_fun (*editor, &PublicEditor::export_range_markers));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
ActionManager::range_sensitive_actions.push_back (act);
|
||||
|
||||
act = ActionManager::register_action (main_actions, X_("Export"), _("Export"));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
@ -475,4 +480,3 @@ ARDOUR_UI::build_menu_bar ()
|
||||
menu_bar_base.set_name ("MainMenuBar");
|
||||
menu_bar_base.add (menu_hbox);
|
||||
}
|
||||
|
||||
|
@ -832,6 +832,11 @@ AudioTimeAxisView::rename_current_playlist ()
|
||||
AudioPlaylist *pl;
|
||||
DiskStream *ds;
|
||||
|
||||
/* neither conditions are supposed to be true at this
|
||||
time, but to leave the design flexible, allow
|
||||
them to be in the future without causing crashes
|
||||
*/
|
||||
|
||||
if (((ds = get_diskstream()) == 0) ||((pl = ds->playlist()) == 0)) {
|
||||
return;
|
||||
}
|
||||
@ -852,16 +857,6 @@ AudioTimeAxisView::rename_current_playlist ()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioTimeAxisView::playlist_selected (AudioPlaylist *pl)
|
||||
{
|
||||
DiskStream *ds;
|
||||
|
||||
if ((ds = get_diskstream()) != 0) {
|
||||
ds->use_playlist (pl);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioTimeAxisView::use_copy_playlist ()
|
||||
{
|
||||
@ -869,6 +864,11 @@ AudioTimeAxisView::use_copy_playlist ()
|
||||
DiskStream *ds;
|
||||
string name;
|
||||
|
||||
/* neither conditions are supposed to be true at this
|
||||
time, but to leave the design flexible, allow
|
||||
them to be in the future without causing crashes
|
||||
*/
|
||||
|
||||
if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) {
|
||||
return;
|
||||
}
|
||||
@ -902,6 +902,11 @@ AudioTimeAxisView::use_new_playlist ()
|
||||
DiskStream *ds;
|
||||
string name;
|
||||
|
||||
/* neither conditions are supposed to be true at this
|
||||
time, but to leave the design flexible, allow
|
||||
them to be in the future without causing crashes
|
||||
*/
|
||||
|
||||
if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) {
|
||||
return;
|
||||
}
|
||||
@ -1003,14 +1008,18 @@ AudioTimeAxisView::selection_click (GdkEventButton* ev)
|
||||
{
|
||||
PublicEditor::TrackViewList* tracks = editor.get_valid_views (this, _route.edit_group());
|
||||
|
||||
if (Keyboard::modifier_state_contains (ev->state, Keyboard::Shift)) {
|
||||
if (editor.get_selection().selected (this)) {
|
||||
editor.get_selection().remove (*tracks);
|
||||
} else {
|
||||
editor.get_selection().add (*tracks);
|
||||
}
|
||||
} else {
|
||||
switch (Keyboard::selection_type (ev->state)) {
|
||||
case Selection::Toggle:
|
||||
editor.get_selection().toggle (*tracks);
|
||||
break;
|
||||
|
||||
case Selection::Set:
|
||||
editor.get_selection().set (*tracks);
|
||||
break;
|
||||
|
||||
case Selection::Extend:
|
||||
/* not defined yet */
|
||||
break;
|
||||
}
|
||||
|
||||
delete tracks;
|
||||
|
@ -227,7 +227,6 @@ class AudioTimeAxisView : public RouteUI, public TimeAxisView
|
||||
void playlist_modified ();
|
||||
|
||||
void add_playlist_to_playlist_menu (ARDOUR::Playlist*);
|
||||
void playlist_selected (ARDOUR::AudioPlaylist*);
|
||||
void use_new_playlist ();
|
||||
void use_copy_playlist ();
|
||||
void clear_playlist ();
|
||||
|
@ -1873,8 +1873,8 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
|
||||
MenuList& select_items = select_menu->items();
|
||||
select_menu->set_name ("ArdourContextMenu");
|
||||
|
||||
select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
|
||||
select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
|
||||
select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
|
||||
select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
|
||||
select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
|
||||
select_items.push_back (MenuElem (_("Invert selection"), mem_fun(*this, &Editor::invert_selection)));
|
||||
select_items.push_back (SeparatorElem());
|
||||
@ -1958,8 +1958,8 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
|
||||
MenuList& select_items = select_menu->items();
|
||||
select_menu->set_name ("ArdourContextMenu");
|
||||
|
||||
select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
|
||||
select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
|
||||
select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
|
||||
select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
|
||||
select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
|
||||
select_items.push_back (MenuElem (_("Invert selection"), mem_fun(*this, &Editor::invert_selection)));
|
||||
select_items.push_back (SeparatorElem());
|
||||
@ -2988,7 +2988,7 @@ Editor::commit_reversible_command ()
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
|
||||
Editor::set_selected_track_from_click (Selection::Operation op, bool with_undo, bool no_remove)
|
||||
{
|
||||
if (!clicked_trackview) {
|
||||
return;
|
||||
@ -2997,25 +2997,29 @@ Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
|
||||
if (with_undo) {
|
||||
begin_reversible_command (_("set selected trackview"));
|
||||
}
|
||||
|
||||
if (add) {
|
||||
|
||||
|
||||
switch (op) {
|
||||
case Selection::Toggle:
|
||||
if (selection->selected (clicked_trackview)) {
|
||||
if (!no_remove) {
|
||||
selection->remove (clicked_trackview);
|
||||
}
|
||||
} else {
|
||||
selection->add (clicked_trackview);
|
||||
selection->toggle (clicked_trackview);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
break;
|
||||
case Selection::Set:
|
||||
if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
|
||||
/* no commit necessary */
|
||||
return;
|
||||
}
|
||||
|
||||
selection->set (clicked_trackview);
|
||||
break;
|
||||
|
||||
case Selection::Extend:
|
||||
/* not defined yet */
|
||||
break;
|
||||
}
|
||||
|
||||
if (with_undo) {
|
||||
@ -3024,7 +3028,7 @@ Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
|
||||
Editor::set_selected_control_point_from_click (Selection::Operation op, bool with_undo, bool no_remove)
|
||||
{
|
||||
if (!clicked_control_point) {
|
||||
return;
|
||||
@ -3034,94 +3038,123 @@ Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no
|
||||
begin_reversible_command (_("set selected control point"));
|
||||
}
|
||||
|
||||
if (add) {
|
||||
|
||||
} else {
|
||||
|
||||
switch (op) {
|
||||
case Selection::Set:
|
||||
break;
|
||||
case Selection::Toggle:
|
||||
break;
|
||||
case Selection::Extend:
|
||||
break;
|
||||
}
|
||||
|
||||
if (with_undo) {
|
||||
commit_reversible_command ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
|
||||
Editor::mapover_audio_tracks (slot<void,AudioTimeAxisView&> sl)
|
||||
{
|
||||
set<AudioTimeAxisView*> relevant_tracks;
|
||||
|
||||
/* step one: get all selected tracks and all tracks in the relevant edit groups */
|
||||
|
||||
for (TrackSelection::iterator ti = selection->tracks.begin(); ti != selection->tracks.end(); ++ti) {
|
||||
|
||||
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
|
||||
|
||||
if (!atv) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RouteGroup* group = atv->route().edit_group();
|
||||
|
||||
if (group && group->is_active()) {
|
||||
|
||||
/* active group for this track, loop over all tracks and get every member of the group */
|
||||
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||
|
||||
AudioTimeAxisView* tatv;
|
||||
|
||||
if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
|
||||
|
||||
if (tatv->route().edit_group() == group) {
|
||||
relevant_tracks.insert (tatv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* no active group, or no group */
|
||||
|
||||
relevant_tracks.insert (atv);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* step two: apply operation to each track */
|
||||
|
||||
for (set<AudioTimeAxisView*>::iterator ati = relevant_tracks.begin(); ati != relevant_tracks.end(); ++ati) {
|
||||
sl (**ati);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::track_set_selected_regionview_from_click (AudioTimeAxisView& atv, AudioRegionView* basis, vector<AudioRegionView*>* all_equivs)
|
||||
{
|
||||
AudioPlaylist* pl;
|
||||
vector<AudioRegion*> results;
|
||||
AudioRegionView* marv;
|
||||
DiskStream* ds;
|
||||
|
||||
if ((ds = atv.get_diskstream()) == 0) {
|
||||
/* bus */
|
||||
return;
|
||||
}
|
||||
|
||||
if ((pl = ds->playlist()) != 0) {
|
||||
pl->get_equivalent_regions (basis->region, results);
|
||||
}
|
||||
|
||||
for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
|
||||
if ((marv = atv.view->find_view (**ir)) != 0) {
|
||||
all_equivs->push_back (marv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_selected_regionview_from_click (Selection::Operation op, bool no_track_remove)
|
||||
{
|
||||
vector<AudioRegionView*> all_equivalent_regions;
|
||||
|
||||
if (!clicked_regionview) {
|
||||
return;
|
||||
}
|
||||
|
||||
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
|
||||
|
||||
if (!atv) {
|
||||
return;
|
||||
}
|
||||
|
||||
RouteGroup* group = atv->route().edit_group();
|
||||
vector<AudioRegionView*> all_equivalent_regions;
|
||||
|
||||
if (group && group->is_active()) {
|
||||
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||
|
||||
AudioTimeAxisView* tatv;
|
||||
|
||||
if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
|
||||
|
||||
if (tatv->route().edit_group() != group) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AudioPlaylist* pl;
|
||||
vector<AudioRegion*> results;
|
||||
AudioRegionView* marv;
|
||||
DiskStream* ds;
|
||||
|
||||
if ((ds = tatv->get_diskstream()) == 0) {
|
||||
/* bus */
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((pl = ds->playlist()) != 0) {
|
||||
pl->get_equivalent_regions (clicked_regionview->region,
|
||||
results);
|
||||
}
|
||||
|
||||
for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
|
||||
if ((marv = tatv->view->find_view (**ir)) != 0) {
|
||||
all_equivalent_regions.push_back (marv);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
all_equivalent_regions.push_back (clicked_regionview);
|
||||
|
||||
}
|
||||
mapover_audio_tracks (bind (mem_fun (*this, &Editor::track_set_selected_regionview_from_click),
|
||||
clicked_regionview, &all_equivalent_regions));
|
||||
|
||||
begin_reversible_command (_("set selected regionview"));
|
||||
|
||||
if (add) {
|
||||
|
||||
switch (op) {
|
||||
case Selection::Toggle:
|
||||
if (clicked_regionview->get_selected()) {
|
||||
if (group && group->is_active() && selection->audio_regions.size() > 1) {
|
||||
if (/* group && group->is_active() && */ selection->audio_regions.size() > 1) {
|
||||
/* reduce selection down to just the one clicked */
|
||||
selection->set (clicked_regionview);
|
||||
} else {
|
||||
selection->remove (clicked_regionview);
|
||||
}
|
||||
} else {
|
||||
selection->add (all_equivalent_regions);
|
||||
selection->toggle (all_equivalent_regions);
|
||||
}
|
||||
|
||||
set_selected_track_from_click (add, false, no_track_remove);
|
||||
|
||||
} else {
|
||||
set_selected_track_from_click (op, false, no_track_remove);
|
||||
break;
|
||||
|
||||
case Selection::Set:
|
||||
// karsten wiese suggested these two lines to make
|
||||
// a selected region rise to the top. but this
|
||||
// leads to a mismatch between actual layering
|
||||
@ -3137,15 +3170,20 @@ Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
|
||||
} else {
|
||||
|
||||
selection->set (all_equivalent_regions);
|
||||
set_selected_track_from_click (add, false, false);
|
||||
set_selected_track_from_click (op, false, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case Selection::Extend:
|
||||
/* not defined yet */
|
||||
break;
|
||||
}
|
||||
|
||||
commit_reversible_command () ;
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_selected_regionview_from_region_list (Region& r, bool add)
|
||||
Editor::set_selected_regionview_from_region_list (Region& r, Selection::Operation op)
|
||||
{
|
||||
vector<AudioRegionView*> all_equivalent_regions;
|
||||
AudioRegion* region;
|
||||
@ -3185,13 +3223,16 @@ Editor::set_selected_regionview_from_region_list (Region& r, bool add)
|
||||
|
||||
begin_reversible_command (_("set selected regions"));
|
||||
|
||||
if (add) {
|
||||
|
||||
selection->add (all_equivalent_regions);
|
||||
|
||||
} else {
|
||||
|
||||
switch (op) {
|
||||
case Selection::Toggle:
|
||||
selection->toggle (all_equivalent_regions);
|
||||
break;
|
||||
case Selection::Set:
|
||||
selection->set (all_equivalent_regions);
|
||||
break;
|
||||
case Selection::Extend:
|
||||
/* not defined yet */
|
||||
break;
|
||||
}
|
||||
|
||||
commit_reversible_command () ;
|
||||
@ -3597,6 +3638,12 @@ Editor::time_selection_changed ()
|
||||
(*i)->show_selection (selection->time);
|
||||
}
|
||||
}
|
||||
|
||||
if (selection->time.empty()) {
|
||||
ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
|
||||
} else {
|
||||
ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -215,8 +215,8 @@ class Editor : public PublicEditor
|
||||
Selection& get_cut_buffer() const { return *cut_buffer; }
|
||||
|
||||
void play_selection ();
|
||||
void select_all_in_track (bool add);
|
||||
void select_all (bool add);
|
||||
void select_all_in_track (Selection::Operation op);
|
||||
void select_all (Selection::Operation op);
|
||||
void invert_selection_in_track ();
|
||||
void invert_selection ();
|
||||
|
||||
@ -442,11 +442,19 @@ class Editor : public PublicEditor
|
||||
CrossfadeView* clicked_crossfadeview;
|
||||
ControlPoint* clicked_control_point;
|
||||
|
||||
void mapover_audio_tracks (sigc::slot<void,AudioTimeAxisView&> sl);
|
||||
|
||||
/* functions to be passed to mapover_audio_tracks(), possibly with sigc::bind()-supplied arguments */
|
||||
|
||||
void track_set_selected_regionview_from_click (AudioTimeAxisView&, AudioRegionView*, vector<AudioRegionView*>*);
|
||||
|
||||
/* end */
|
||||
|
||||
void catch_vanishing_audio_regionview (AudioRegionView *);
|
||||
void set_selected_control_point_from_click (bool add = false, bool with_undo = true, bool no_remove=false);
|
||||
void set_selected_track_from_click (bool add = false, bool with_undo = true, bool no_remove=false);
|
||||
void set_selected_regionview_from_click (bool add = false, bool no_track_remove=false);
|
||||
void set_selected_regionview_from_region_list (ARDOUR::Region& region, bool add = false);
|
||||
void set_selected_control_point_from_click (Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false);
|
||||
void set_selected_track_from_click (Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false);
|
||||
void set_selected_regionview_from_click (Selection::Operation op = Selection::Set, bool no_track_remove=false);
|
||||
void set_selected_regionview_from_region_list (ARDOUR::Region& region, Selection::Operation op = Selection::Set);
|
||||
bool set_selected_regionview_from_map_event (GdkEventAny*, StreamView*, ARDOUR::Region*);
|
||||
void collect_new_region_view (AudioRegionView *);
|
||||
|
||||
@ -1121,7 +1129,9 @@ class Editor : public PublicEditor
|
||||
void start_line_grab_from_line (ArdourCanvas::Item*, GdkEvent*);
|
||||
void start_line_grab (AutomationLine *, GdkEvent*);
|
||||
void start_tempo_marker_grab (ArdourCanvas::Item*, GdkEvent*);
|
||||
void start_tempo_marker_copy_grab (ArdourCanvas::Item*, GdkEvent*);
|
||||
void start_meter_marker_grab (ArdourCanvas::Item*, GdkEvent*);
|
||||
void start_meter_marker_copy_grab (ArdourCanvas::Item*, GdkEvent*);
|
||||
|
||||
void region_view_item_click (AudioRegionView&, GdkEventButton*);
|
||||
|
||||
@ -1440,7 +1450,7 @@ class Editor : public PublicEditor
|
||||
void drag_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event);
|
||||
void end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event);
|
||||
|
||||
bool select_all_within (jack_nframes_t start, jack_nframes_t end, gdouble topy, gdouble boty, bool add);
|
||||
bool select_all_within (jack_nframes_t start, jack_nframes_t end, gdouble topy, gdouble boty, Selection::Operation op);
|
||||
|
||||
ArdourCanvas::SimpleRect *rubberband_rect;
|
||||
|
||||
@ -1616,7 +1626,10 @@ class Editor : public PublicEditor
|
||||
/* audio export */
|
||||
|
||||
ExportDialog *export_dialog;
|
||||
ExportDialog *export_range_markers_dialog;
|
||||
|
||||
void export_range (jack_nframes_t start, jack_nframes_t end);
|
||||
void export_range_markers ();
|
||||
|
||||
int write_region_selection(AudioRegionSelection&);
|
||||
bool write_region (string path, ARDOUR::AudioRegion&);
|
||||
|
@ -82,7 +82,7 @@ Editor::register_actions ()
|
||||
act = ActionManager::register_action (editor_actions, "edit-cursor-to-range-end", _("edit cursor to range end"), bind (mem_fun(*this, &Editor::cursor_to_selection_end), edit_cursor));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
|
||||
act = ActionManager::register_action (editor_actions, "select-all", _("select all"), bind (mem_fun(*this, &Editor::select_all), false));
|
||||
act = ActionManager::register_action (editor_actions, "select-all", _("select all"), bind (mem_fun(*this, &Editor::select_all), Selection::Set));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
act = ActionManager::register_action (editor_actions, "select-all-after-edit-cursor", _("select all after edit cursor"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), edit_cursor, true));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
|
@ -20,14 +20,18 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <climits>
|
||||
#include "export_dialog.h"
|
||||
|
||||
#include <gtkmm/messagedialog.h>
|
||||
|
||||
#include "export_session_dialog.h"
|
||||
#include "export_region_dialog.h"
|
||||
#include "export_range_markers_dialog.h"
|
||||
#include "editor.h"
|
||||
#include "public_editor.h"
|
||||
#include "selection.h"
|
||||
#include "time_axis_view.h"
|
||||
#include "audio_time_axis.h"
|
||||
#include "regionview.h"
|
||||
#include "ardour_message.h"
|
||||
|
||||
#include <pbd/pthread_utils.h>
|
||||
#include <ardour/types.h>
|
||||
@ -57,12 +61,12 @@ Editor::export_selection ()
|
||||
{
|
||||
if (session) {
|
||||
if (selection->time.empty()) {
|
||||
ArdourMessage message (this, X_("norange"), _("There is no range to export.\n\nSelect a range using the range mouse mode"));
|
||||
MessageDialog message (*this, _("There is no selection to export.\n\nSelect a selection using the range mouse mode"));
|
||||
message.run ();
|
||||
return;
|
||||
}
|
||||
|
||||
export_range (selection->time.front().start,
|
||||
selection->time.front().end);
|
||||
export_range (selection->time.front().start, selection->time.front().end);
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +75,7 @@ Editor::export_range (jack_nframes_t start, jack_nframes_t end)
|
||||
{
|
||||
if (session) {
|
||||
if (export_dialog == 0) {
|
||||
export_dialog = new ExportDialog (*this);
|
||||
export_dialog = new ExportSessionDialog (*this);
|
||||
}
|
||||
|
||||
export_dialog->connect_to_session (session);
|
||||
@ -87,13 +91,36 @@ Editor::export_region ()
|
||||
return;
|
||||
}
|
||||
|
||||
ExportDialog* dialog = new ExportDialog (*this, &clicked_regionview->region);
|
||||
ExportDialog* dialog = new ExportRegionDialog (*this, &clicked_regionview->region);
|
||||
|
||||
dialog->connect_to_session (session);
|
||||
dialog->set_range (0, clicked_regionview->region.length());
|
||||
dialog->set_range (
|
||||
clicked_regionview->region.first_frame(),
|
||||
clicked_regionview->region.last_frame());
|
||||
dialog->start_export();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::export_range_markers ()
|
||||
{
|
||||
if (session) {
|
||||
|
||||
if (session->locations()->num_range_markers() == 0) {
|
||||
MessageDialog message (*this, _("There are no ranges to export.\n\nCreate 1 or more ranges by dragging the mouse in the range bar"));
|
||||
message.run ();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (export_range_markers_dialog == 0) {
|
||||
export_range_markers_dialog = new ExportRangeMarkersDialog(*this);
|
||||
}
|
||||
|
||||
export_range_markers_dialog->connect_to_session (session);
|
||||
export_range_markers_dialog->start_export();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Editor::write_region_selection (AudioRegionSelection& regions)
|
||||
{
|
||||
|
@ -43,10 +43,10 @@ Editor::keyboard_selection_finish (bool add)
|
||||
{
|
||||
if (session && have_pending_keyboard_selection) {
|
||||
begin_reversible_command (_("keyboard selection"));
|
||||
if (!add) {
|
||||
selection->set (0, pending_keyboard_selection_start, session->audible_frame());
|
||||
} else {
|
||||
if (add) {
|
||||
selection->add (pending_keyboard_selection_start, session->audible_frame());
|
||||
} else {
|
||||
selection->set (0, pending_keyboard_selection_start, session->audible_frame());
|
||||
}
|
||||
commit_reversible_command ();
|
||||
have_pending_keyboard_selection = false;
|
||||
|
@ -30,10 +30,10 @@
|
||||
#include "editor.h"
|
||||
#include "marker.h"
|
||||
#include "selection.h"
|
||||
#include "simplerect.h"
|
||||
#include "editing.h"
|
||||
#include "gui_thread.h"
|
||||
#include "simplerect.h"
|
||||
#include "actions.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
@ -564,7 +564,7 @@ Editor::marker_menu_select_all_selectables_using_range ()
|
||||
bool is_start;
|
||||
|
||||
if (((l = find_location_from_marker (marker, is_start)) != 0) && (l->end() > l->start())) {
|
||||
select_all_within (l->start(), l->end(), 0, DBL_MAX, false);
|
||||
select_all_within (l->start(), l->end(), 0, DBL_MAX, Selection::Set);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -314,21 +314,21 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
|
||||
|
||||
switch (item_type) {
|
||||
case RegionItem:
|
||||
set_selected_regionview_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true);
|
||||
set_selected_regionview_from_click (Keyboard::selection_type (event->button.state), true);
|
||||
break;
|
||||
|
||||
case AudioRegionViewNameHighlight:
|
||||
case AudioRegionViewName:
|
||||
if ((rv = reinterpret_cast<AudioRegionView *> (item->get_data ("regionview"))) != 0) {
|
||||
set_selected_regionview_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true);
|
||||
if ((rv = static_cast<AudioRegionView *> (item->get_data ("regionview"))) != 0) {
|
||||
set_selected_regionview_from_click (Keyboard::selection_type (event->button.state), true);
|
||||
}
|
||||
break;
|
||||
|
||||
case GainAutomationControlPointItem:
|
||||
case PanAutomationControlPointItem:
|
||||
case RedirectAutomationControlPointItem:
|
||||
if ((cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"))) != 0) {
|
||||
set_selected_control_point_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true);
|
||||
if ((cp = static_cast<ControlPoint *> (item->get_data ("control_point"))) != 0) {
|
||||
set_selected_control_point_from_click (Keyboard::selection_type (event->button.state), true);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -357,7 +357,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
|
||||
case StreamItem:
|
||||
case RegionItem:
|
||||
case AutomationTrackItem:
|
||||
set_selected_track_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true, true);
|
||||
set_selected_track_from_click (Keyboard::selection_type (event->button.state), true, true);
|
||||
break;
|
||||
|
||||
case AudioRegionViewNameHighlight:
|
||||
@ -409,11 +409,19 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
|
||||
return TRUE;
|
||||
|
||||
case TempoMarkerItem:
|
||||
start_tempo_marker_grab (item, event);
|
||||
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
|
||||
start_tempo_marker_copy_grab (item, event);
|
||||
} else {
|
||||
start_tempo_marker_grab (item, event);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case MeterMarkerItem:
|
||||
start_meter_marker_grab (item, event);
|
||||
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
|
||||
start_meter_marker_copy_grab (item, event);
|
||||
} else {
|
||||
start_meter_marker_grab (item, event);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case TempoBarItem:
|
||||
@ -2142,6 +2150,39 @@ Editor::start_meter_marker_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
||||
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::start_meter_marker_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
||||
{
|
||||
Marker* marker;
|
||||
MeterMarker* meter_marker;
|
||||
|
||||
if ((marker = reinterpret_cast<Marker *> (item->get_data ("marker"))) == 0) {
|
||||
fatal << _("programming error: meter marker canvas item has no marker object pointer!") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
meter_marker = dynamic_cast<MeterMarker*> (marker);
|
||||
|
||||
// create a dummy marker for visual representation of moving the copy.
|
||||
// The actual copying is not done before we reach the finish callback.
|
||||
char name[64];
|
||||
snprintf (name, sizeof(name), "%g/%g", meter_marker->meter().beats_per_bar(), meter_marker->meter().note_divisor ());
|
||||
MeterMarker* new_marker = new MeterMarker(*this, *meter_group, color_map[cMeterMarker], name,
|
||||
*new MeterSection(meter_marker->meter()));
|
||||
|
||||
drag_info.item = &new_marker->the_item();
|
||||
drag_info.copy = true;
|
||||
drag_info.data = new_marker;
|
||||
drag_info.motion_callback = &Editor::meter_marker_drag_motion_callback;
|
||||
drag_info.finished_callback = &Editor::meter_marker_drag_finished_callback;
|
||||
|
||||
start_grab (event);
|
||||
|
||||
drag_info.pointer_frame_offset = drag_info.grab_frame - meter_marker->meter().frame();
|
||||
|
||||
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::meter_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||
{
|
||||
@ -2175,7 +2216,7 @@ Editor::meter_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
|
||||
{
|
||||
if (drag_info.first_move) return;
|
||||
|
||||
meter_marker_drag_motion_callback (item, event);
|
||||
meter_marker_drag_motion_callback (drag_info.item, event);
|
||||
|
||||
MeterMarker* marker = (MeterMarker *) drag_info.data;
|
||||
BBT_Time when;
|
||||
@ -2183,11 +2224,23 @@ Editor::meter_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
|
||||
TempoMap& map (session->tempo_map());
|
||||
map.bbt_time (drag_info.last_pointer_frame, when);
|
||||
|
||||
begin_reversible_command (_("move meter mark"));
|
||||
session->add_undo (map.get_memento());
|
||||
map.move_meter (marker->meter(), when);
|
||||
session->add_redo_no_execute (map.get_memento());
|
||||
commit_reversible_command ();
|
||||
if (drag_info.copy == true) {
|
||||
begin_reversible_command (_("copy meter mark"));
|
||||
session->add_undo (map.get_memento());
|
||||
map.add_meter (marker->meter(), when);
|
||||
session->add_redo_no_execute (map.get_memento());
|
||||
commit_reversible_command ();
|
||||
|
||||
// delete the dummy marker we used for visual representation of copying.
|
||||
// a new visual marker will show up automatically.
|
||||
delete marker;
|
||||
} else {
|
||||
begin_reversible_command (_("move meter mark"));
|
||||
session->add_undo (map.get_memento());
|
||||
map.move_meter (marker->meter(), when);
|
||||
session->add_redo_no_execute (map.get_memento());
|
||||
commit_reversible_command ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -2223,6 +2276,42 @@ Editor::start_tempo_marker_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
||||
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::start_tempo_marker_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
||||
{
|
||||
Marker* marker;
|
||||
TempoMarker* tempo_marker;
|
||||
|
||||
if ((marker = reinterpret_cast<Marker *> (item->get_data ("marker"))) == 0) {
|
||||
fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
if ((tempo_marker = dynamic_cast<TempoMarker *> (marker)) == 0) {
|
||||
fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
// create a dummy marker for visual representation of moving the copy.
|
||||
// The actual copying is not done before we reach the finish callback.
|
||||
char name[64];
|
||||
snprintf (name, sizeof (name), "%.2f", tempo_marker->tempo().beats_per_minute());
|
||||
TempoMarker* new_marker = new TempoMarker(*this, *tempo_group, color_map[cTempoMarker], name,
|
||||
*new TempoSection(tempo_marker->tempo()));
|
||||
|
||||
drag_info.item = &new_marker->the_item();
|
||||
drag_info.copy = true;
|
||||
drag_info.data = new_marker;
|
||||
drag_info.motion_callback = &Editor::tempo_marker_drag_motion_callback;
|
||||
drag_info.finished_callback = &Editor::tempo_marker_drag_finished_callback;
|
||||
|
||||
start_grab (event);
|
||||
|
||||
drag_info.pointer_frame_offset = drag_info.grab_frame - tempo_marker->tempo().frame();
|
||||
|
||||
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::tempo_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||
{
|
||||
@ -2257,7 +2346,7 @@ Editor::tempo_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
|
||||
{
|
||||
if (drag_info.first_move) return;
|
||||
|
||||
tempo_marker_drag_motion_callback (item, event);
|
||||
tempo_marker_drag_motion_callback (drag_info.item, event);
|
||||
|
||||
TempoMarker* marker = (TempoMarker *) drag_info.data;
|
||||
BBT_Time when;
|
||||
@ -2265,11 +2354,23 @@ Editor::tempo_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
|
||||
TempoMap& map (session->tempo_map());
|
||||
map.bbt_time (drag_info.last_pointer_frame, when);
|
||||
|
||||
begin_reversible_command (_("move tempo mark"));
|
||||
session->add_undo (map.get_memento());
|
||||
map.move_tempo (marker->tempo(), when);
|
||||
session->add_redo_no_execute (map.get_memento());
|
||||
commit_reversible_command ();
|
||||
if (drag_info.copy == true) {
|
||||
begin_reversible_command (_("copy tempo mark"));
|
||||
session->add_undo (map.get_memento());
|
||||
map.add_tempo (marker->tempo(), when);
|
||||
session->add_redo_no_execute (map.get_memento());
|
||||
commit_reversible_command ();
|
||||
|
||||
// delete the dummy marker we used for visual representation of copying.
|
||||
// a new visual marker will show up automatically.
|
||||
delete marker;
|
||||
} else {
|
||||
begin_reversible_command (_("move tempo mark"));
|
||||
session->add_undo (map.get_memento());
|
||||
map.move_tempo (marker->tempo(), when);
|
||||
session->add_redo_no_execute (map.get_memento());
|
||||
commit_reversible_command ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -4243,7 +4344,7 @@ Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event)
|
||||
case CreateRangeMarker:
|
||||
begin_reversible_command (_("new range marker"));
|
||||
session->add_undo (session->locations()->get_memento());
|
||||
newloc = new Location(temp_location->start(), temp_location->end(), "unnamed");
|
||||
newloc = new Location(temp_location->start(), temp_location->end(), "unnamed", Location::IsRangeMarker);
|
||||
session->locations()->add (newloc, true);
|
||||
session->add_redo_no_execute (session->locations()->get_memento());
|
||||
commit_reversible_command ();
|
||||
@ -4453,15 +4554,15 @@ Editor::end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event)
|
||||
}
|
||||
|
||||
|
||||
bool add = Keyboard::modifier_state_contains (event->button.state, Keyboard::Shift);
|
||||
Selection::Operation op = Keyboard::selection_type (event->button.state);
|
||||
bool commit;
|
||||
|
||||
begin_reversible_command (_("select regions"));
|
||||
|
||||
if (drag_info.grab_frame < drag_info.last_pointer_frame) {
|
||||
commit = select_all_within (drag_info.grab_frame, drag_info.last_pointer_frame, y1, y2, add);
|
||||
commit = select_all_within (drag_info.grab_frame, drag_info.last_pointer_frame, y1, y2, op);
|
||||
} else {
|
||||
commit = select_all_within (drag_info.last_pointer_frame, drag_info.grab_frame, y1, y2, add);
|
||||
commit = select_all_within (drag_info.last_pointer_frame, drag_info.grab_frame, y1, y2, op);
|
||||
}
|
||||
|
||||
if (commit) {
|
||||
|
@ -1200,7 +1200,7 @@ Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
|
||||
}
|
||||
|
||||
void
|
||||
Editor::select_all_in_track (bool add)
|
||||
Editor::select_all_in_track (Selection::Operation op)
|
||||
{
|
||||
list<Selectable *> touched;
|
||||
|
||||
@ -1210,15 +1210,21 @@ Editor::select_all_in_track (bool add)
|
||||
|
||||
clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
|
||||
|
||||
if (add) {
|
||||
switch (op) {
|
||||
case Selection::Toggle:
|
||||
selection->add (touched);
|
||||
} else {
|
||||
break;
|
||||
case Selection::Set:
|
||||
selection->set (touched);
|
||||
break;
|
||||
case Selection::Extend:
|
||||
/* not defined yet */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::select_all (bool add)
|
||||
Editor::select_all (Selection::Operation op)
|
||||
{
|
||||
list<Selectable *> touched;
|
||||
|
||||
@ -1229,10 +1235,16 @@ Editor::select_all (bool add)
|
||||
(*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
|
||||
}
|
||||
begin_reversible_command (_("select all"));
|
||||
if (add) {
|
||||
switch (op) {
|
||||
case Selection::Toggle:
|
||||
selection->add (touched);
|
||||
} else {
|
||||
break;
|
||||
case Selection::Set:
|
||||
selection->set (touched);
|
||||
break;
|
||||
case Selection::Extend:
|
||||
/* not defined yet */
|
||||
break;
|
||||
}
|
||||
commit_reversible_command ();
|
||||
}
|
||||
@ -1266,7 +1278,7 @@ Editor::invert_selection ()
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, double bot, bool add)
|
||||
Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, double bot, Selection::Operation op)
|
||||
{
|
||||
list<Selectable *> touched;
|
||||
|
||||
@ -1277,10 +1289,16 @@ Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top,
|
||||
(*iter)->get_selectables (start, end, top, bot, touched);
|
||||
}
|
||||
begin_reversible_command (_("select all within"));
|
||||
if (add) {
|
||||
switch (op) {
|
||||
case Selection::Toggle:
|
||||
selection->add (touched);
|
||||
} else {
|
||||
break;
|
||||
case Selection::Set:
|
||||
selection->set (touched);
|
||||
break;
|
||||
case Selection::Extend:
|
||||
/* not defined yet */
|
||||
break;
|
||||
}
|
||||
commit_reversible_command ();
|
||||
return !touched.empty();
|
||||
|
@ -195,7 +195,7 @@ Editor::region_list_selection_changed()
|
||||
*/
|
||||
|
||||
if ((iter = region_list_model->get_iter (*i))) {
|
||||
set_selected_regionview_from_region_list (*((*iter)[region_list_columns.region]), false);
|
||||
set_selected_regionview_from_region_list (*((*iter)[region_list_columns.region]), Selection::Set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include <fstream>
|
||||
|
||||
#include <samplerate.h>
|
||||
#include <pbd/pthread_utils.h>
|
||||
#include <pbd/xml++.h>
|
||||
#include <pbd/dirname.h>
|
||||
|
||||
@ -43,7 +42,6 @@
|
||||
#include "ardour_ui.h"
|
||||
#include "public_editor.h"
|
||||
#include "keyboard.h"
|
||||
#include "ardour_message.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
@ -95,7 +93,7 @@ static const gchar* cue_file_types[] = {
|
||||
0
|
||||
};
|
||||
|
||||
ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
|
||||
ExportDialog::ExportDialog(PublicEditor& e)
|
||||
: ArdourDialog ("export dialog"),
|
||||
editor (e),
|
||||
format_table (9, 2),
|
||||
@ -117,9 +115,10 @@ ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
|
||||
guint32 len;
|
||||
guint32 maxlen;
|
||||
|
||||
audio_region = r;
|
||||
|
||||
session = 0;
|
||||
track_and_master_selection_allowed = true;
|
||||
channel_count_selection_allowed = true;
|
||||
export_cd_markers_allowed = true;
|
||||
|
||||
set_title (_("ardour: export"));
|
||||
set_wmclass (_("ardour_export"), "Ardour");
|
||||
@ -177,23 +176,18 @@ ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
|
||||
hpacker.set_border_width (5);
|
||||
hpacker.pack_start (format_frame, false, false);
|
||||
|
||||
if (!audio_region) {
|
||||
|
||||
master_scroll.add (master_selector);
|
||||
track_scroll.add (track_selector);
|
||||
|
||||
master_scroll.set_size_request (220, 100);
|
||||
track_scroll.set_size_request (220, 100);
|
||||
master_scroll.add (master_selector);
|
||||
track_scroll.add (track_selector);
|
||||
|
||||
master_scroll.set_size_request (220, 100);
|
||||
track_scroll.set_size_request (220, 100);
|
||||
|
||||
|
||||
/* we may hide some of these later */
|
||||
track_vpacker.pack_start (master_scroll);
|
||||
track_vpacker.pack_start (track_scroll);
|
||||
track_vpacker.pack_start (track_selector_button, Gtk::PACK_EXPAND_PADDING);
|
||||
/* we may hide some of these later */
|
||||
track_vpacker.pack_start (master_scroll);
|
||||
track_vpacker.pack_start (track_scroll);
|
||||
track_vpacker.pack_start (track_selector_button, Gtk::PACK_EXPAND_PADDING);
|
||||
|
||||
hpacker.pack_start (track_vpacker);
|
||||
}
|
||||
hpacker.pack_start (track_vpacker);
|
||||
|
||||
get_vbox()->pack_start (hpacker);
|
||||
|
||||
@ -251,7 +245,7 @@ ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
|
||||
/* determine longest strings at runtime */
|
||||
|
||||
maxlen = 0;
|
||||
const char *longest = "gl";
|
||||
const char *longest = X_("gl"); /* translators: one ascender, one descender */
|
||||
string longest_str;
|
||||
|
||||
for (n = 0; n < SNDFILE_HEADER_FORMATS; ++n) {
|
||||
@ -321,11 +315,9 @@ ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
|
||||
format_table.set_col_spacings (5);
|
||||
format_table.set_row_spacings (5);
|
||||
|
||||
if (!audio_region) {
|
||||
format_table.attach (channel_count_label, 0, 1, 0, 1);
|
||||
format_table.attach (channel_count_combo, 1, 2, 0, 1);
|
||||
}
|
||||
|
||||
format_table.attach (channel_count_label, 0, 1, 0, 1);
|
||||
format_table.attach (channel_count_combo, 1, 2, 0, 1);
|
||||
|
||||
format_table.attach (header_format_label, 0, 1, 1, 2);
|
||||
format_table.attach (header_format_combo, 1, 2, 1, 2);
|
||||
|
||||
@ -374,6 +366,30 @@ ExportDialog::~ExportDialog()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ExportDialog::do_not_allow_track_and_master_selection()
|
||||
{
|
||||
track_and_master_selection_allowed = false;
|
||||
track_vpacker.set_no_show_all();
|
||||
}
|
||||
|
||||
void
|
||||
ExportDialog::do_not_allow_channel_count_selection()
|
||||
{
|
||||
channel_count_selection_allowed = false;
|
||||
channel_count_combo.set_no_show_all();
|
||||
channel_count_label.set_no_show_all();
|
||||
}
|
||||
|
||||
void
|
||||
ExportDialog::do_not_allow_export_cd_markers()
|
||||
{
|
||||
export_cd_markers_allowed = false;
|
||||
cue_file_label.set_no_show_all();
|
||||
cue_file_combo.set_no_show_all();
|
||||
cuefile_only_checkbox.set_no_show_all();
|
||||
}
|
||||
|
||||
void
|
||||
ExportDialog::connect_to_session (Session *s)
|
||||
{
|
||||
@ -571,35 +587,15 @@ ExportDialog::set_range (jack_nframes_t start, jack_nframes_t end)
|
||||
{
|
||||
spec.start_frame = start;
|
||||
spec.end_frame = end;
|
||||
|
||||
if (!audio_region) {
|
||||
// XXX: this is a hack until we figure out what is really wrong
|
||||
session->request_locate (spec.start_frame, false);
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
ExportDialog::progress_timeout ()
|
||||
{
|
||||
progress_bar.set_fraction (spec.progress/100);
|
||||
progress_bar.set_fraction (spec.progress);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void*
|
||||
ExportDialog::_export_region_thread (void *arg)
|
||||
{
|
||||
PBD::ThreadCreated (pthread_self(), X_("Export Region"));
|
||||
|
||||
static_cast<ExportDialog*>(arg)->export_region ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ExportDialog::export_region ()
|
||||
{
|
||||
audio_region->exportme (*session, spec);
|
||||
}
|
||||
|
||||
void
|
||||
frames_to_cd_frames_string (char* buf, jack_nframes_t when, jack_nframes_t fr)
|
||||
{
|
||||
@ -625,8 +621,11 @@ struct LocationSortByStart {
|
||||
void
|
||||
ExportDialog::export_toc_file (Locations::LocationList& locations, const string& path)
|
||||
{
|
||||
if(!export_cd_markers_allowed){
|
||||
return;
|
||||
}
|
||||
|
||||
string filepath = path + ".toc";
|
||||
string filepath = path + ".toc";
|
||||
ofstream out (filepath.c_str());
|
||||
long unsigned int last_end_time = spec.start_frame, last_start_time = spec.start_frame;
|
||||
int numtracks = 0;
|
||||
@ -748,7 +747,11 @@ ExportDialog::export_toc_file (Locations::LocationList& locations, const string&
|
||||
void
|
||||
ExportDialog::export_cue_file (Locations::LocationList& locations, const string& path)
|
||||
{
|
||||
string filepath = path + ".cue";
|
||||
if(!export_cd_markers_allowed){
|
||||
return;
|
||||
}
|
||||
|
||||
string filepath = path + ".cue";
|
||||
ofstream out (filepath.c_str());
|
||||
gchar buf[18];
|
||||
long unsigned int last_track_end = spec.start_frame;
|
||||
@ -867,7 +870,7 @@ ExportDialog::export_cue_file (Locations::LocationList& locations, const string&
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExportDialog::do_export_cd_markers (const string& path,const string& cuefile_type)
|
||||
{
|
||||
@ -882,52 +885,21 @@ ExportDialog::do_export_cd_markers (const string& path,const string& cuefile_typ
|
||||
void
|
||||
ExportDialog::do_export ()
|
||||
{
|
||||
// sanity check file name first
|
||||
string filepath = file_entry.get_text();
|
||||
struct stat statbuf;
|
||||
|
||||
if (filepath.empty()) {
|
||||
// warning dialog
|
||||
string txt = _("Please enter a valid filename.");
|
||||
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
|
||||
msg.run();
|
||||
return;
|
||||
}
|
||||
string filepath = file_entry.get_text();
|
||||
|
||||
// check if file exists already and warn
|
||||
if (stat (filepath.c_str(), &statbuf) == 0) {
|
||||
if (S_ISDIR (statbuf.st_mode)) {
|
||||
string txt = _("Please specify a complete filename for the audio file.");
|
||||
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
|
||||
msg.run();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
string txt = _("File already exists, do you want to overwrite it?");
|
||||
MessageDialog msg (*this, txt, false, MESSAGE_QUESTION, BUTTONS_YES_NO, true);
|
||||
//ArdourMessage msg (this, X_("exportoverwrite"), txt, true, false, Gtk::BUTTONS_YES_NO);
|
||||
if ((ResponseType) msg.run() == Gtk::RESPONSE_NO) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// directory needs to exist and be writable
|
||||
string dirpath = PBD::dirname (filepath);
|
||||
if (::access (dirpath.c_str(), W_OK) != 0) {
|
||||
string txt = _("Cannot write file in: ") + dirpath;
|
||||
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
|
||||
msg.run();
|
||||
return;
|
||||
}
|
||||
|
||||
if (cue_file_combo.get_active_text () != _("None")) {
|
||||
do_export_cd_markers (file_entry.get_text(), cue_file_combo.get_active_text ());
|
||||
if(!is_filepath_valid(filepath)){
|
||||
return;
|
||||
}
|
||||
|
||||
if (cuefile_only_checkbox.get_active()) {
|
||||
end_dialog ();
|
||||
return;
|
||||
if (export_cd_markers_allowed) {
|
||||
if (cue_file_combo.get_active_text () != _("None")) {
|
||||
do_export_cd_markers (file_entry.get_text(), cue_file_combo.get_active_text ());
|
||||
}
|
||||
|
||||
if (cuefile_only_checkbox.get_active()) {
|
||||
end_dialog ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ok_button->set_sensitive(false);
|
||||
@ -935,148 +907,15 @@ ExportDialog::do_export ()
|
||||
|
||||
set_modal (true);
|
||||
|
||||
spec.path = filepath;
|
||||
spec.progress = 0;
|
||||
spec.running = true;
|
||||
spec.stop = false;
|
||||
spec.port_map.clear();
|
||||
// read user input into spec
|
||||
initSpec(filepath);
|
||||
|
||||
if (channel_count_combo.get_active_text() == _("mono")) {
|
||||
spec.channels = 1;
|
||||
} else {
|
||||
spec.channels = 2;
|
||||
}
|
||||
|
||||
spec.format = 0;
|
||||
|
||||
spec.format |= sndfile_header_format_from_string (header_format_combo.get_active_text ());
|
||||
|
||||
if ((spec.format & SF_FORMAT_WAV) == 0) {
|
||||
/* RIFF/WAV specifies endianess */
|
||||
spec.format |= sndfile_endian_format_from_string (endian_format_combo.get_active_text ());
|
||||
}
|
||||
|
||||
spec.format |= sndfile_bitdepth_format_from_string (bitdepth_format_combo.get_active_text ());
|
||||
|
||||
string sr_str = sample_rate_combo.get_active_text();
|
||||
if (sr_str == N_("22.05kHz")) {
|
||||
spec.sample_rate = 22050;
|
||||
} else if (sr_str == N_("44.1kHz")) {
|
||||
spec.sample_rate = 44100;
|
||||
} else if (sr_str == N_("48kHz")) {
|
||||
spec.sample_rate = 48000;
|
||||
} else if (sr_str == N_("88.2kHz")) {
|
||||
spec.sample_rate = 88200;
|
||||
} else if (sr_str == N_("96kHz")) {
|
||||
spec.sample_rate = 96000;
|
||||
} else if (sr_str == N_("192kHz")) {
|
||||
spec.sample_rate = 192000;
|
||||
} else {
|
||||
spec.sample_rate = session->frame_rate();
|
||||
}
|
||||
|
||||
string src_str = src_quality_combo.get_active_text();
|
||||
if (src_str == _("fastest")) {
|
||||
spec.src_quality = SRC_ZERO_ORDER_HOLD;
|
||||
} else if (src_str == _("linear")) {
|
||||
spec.src_quality = SRC_LINEAR;
|
||||
} else if (src_str == _("better")) {
|
||||
spec.src_quality = SRC_SINC_FASTEST;
|
||||
} else if (src_str == _("intermediate")) {
|
||||
spec.src_quality = SRC_SINC_MEDIUM_QUALITY;
|
||||
} else {
|
||||
spec.src_quality = SRC_SINC_BEST_QUALITY;
|
||||
}
|
||||
|
||||
string dither_str = dither_type_combo.get_active_text();
|
||||
if (dither_str == _("None")) {
|
||||
spec.dither_type = GDitherNone;
|
||||
} else if (dither_str == _("Rectangular")) {
|
||||
spec.dither_type = GDitherRect;
|
||||
} else if (dither_str == _("Triangular")) {
|
||||
spec.dither_type = GDitherTri;
|
||||
} else {
|
||||
spec.dither_type = GDitherShaped;
|
||||
}
|
||||
|
||||
if (!audio_region) {
|
||||
|
||||
uint32_t chan=0;
|
||||
Port *last_port = 0;
|
||||
|
||||
TreeModel::Children rows = master_selector.get_model()->children();
|
||||
TreeModel::Children::iterator ri;
|
||||
TreeModel::Row row;
|
||||
for (ri = rows.begin(); ri != rows.end(); ++ri) {
|
||||
row = *ri;
|
||||
Port* port = row[exp_cols.port];
|
||||
|
||||
if (last_port != port) {
|
||||
chan = 0;
|
||||
}
|
||||
|
||||
if (row[exp_cols.left]) {
|
||||
spec.port_map[0].push_back (std::pair<Port*,uint32_t>(port, chan));
|
||||
}
|
||||
|
||||
if (spec.channels == 2) {
|
||||
if (row[exp_cols.right]) {
|
||||
spec.port_map[1].push_back (std::pair<Port*,uint32_t>(port, chan));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chan = 0;
|
||||
|
||||
rows = track_selector.get_model()->children();
|
||||
for (ri = rows.begin(); ri != rows.end(); ++ri) {
|
||||
row = *ri;
|
||||
|
||||
Port* port = row[exp_cols.port];
|
||||
|
||||
if (last_port != port) {
|
||||
chan = 0;
|
||||
}
|
||||
|
||||
if (row[exp_cols.left]) {
|
||||
spec.port_map[0].push_back (std::pair<Port*,uint32_t>(port, chan));
|
||||
}
|
||||
|
||||
if (spec.channels == 2) {
|
||||
if (row[exp_cols.right]) {
|
||||
spec.port_map[1].push_back (std::pair<Port*,uint32_t>(port, chan));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
last_port = port;
|
||||
++chan;
|
||||
}
|
||||
}
|
||||
|
||||
progress_connection = Glib::signal_timeout().connect (mem_fun(*this, &ExportDialog::progress_timeout), 100);
|
||||
cancel_label.set_text (_("Stop Export"));
|
||||
|
||||
if (!audio_region) {
|
||||
if (session->start_audio_export (spec)) {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
pthread_t thr;
|
||||
pthread_create_and_store ("region export", &thr, 0, ExportDialog::_export_region_thread, this);
|
||||
}
|
||||
|
||||
gtk_main_iteration ();
|
||||
while (spec.running) {
|
||||
if (gtk_events_pending()) {
|
||||
gtk_main_iteration ();
|
||||
} else {
|
||||
usleep (10000);
|
||||
}
|
||||
}
|
||||
export_audio_data();
|
||||
|
||||
out:
|
||||
progress_connection.disconnect ();
|
||||
progress_connection.disconnect ();
|
||||
end_dialog ();
|
||||
}
|
||||
|
||||
@ -1116,7 +955,7 @@ ExportDialog::start_export ()
|
||||
return;
|
||||
}
|
||||
|
||||
/* If it the filename hasn't been set before, use the
|
||||
/* If the filename hasn't been set before, use the
|
||||
directory above the current session as a default
|
||||
location for the export.
|
||||
*/
|
||||
@ -1286,12 +1125,191 @@ ExportDialog::fill_lists ()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ExportDialog::is_filepath_valid(string &filepath)
|
||||
{
|
||||
// sanity check file name first
|
||||
|
||||
struct stat statbuf;
|
||||
|
||||
if (filepath.empty()) {
|
||||
string txt = _("Please enter a valid filename.");
|
||||
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
|
||||
msg.run();
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if file exists already and warn
|
||||
|
||||
if (stat (filepath.c_str(), &statbuf) == 0) {
|
||||
if (S_ISDIR (statbuf.st_mode)) {
|
||||
string txt = _("Please specify a complete filename for the audio file.");
|
||||
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
|
||||
msg.run();
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
string txt = _("File already exists, do you want to overwrite it?");
|
||||
MessageDialog msg (*this, txt, false, MESSAGE_QUESTION, BUTTONS_YES_NO, true);
|
||||
if ((ResponseType) msg.run() == Gtk::RESPONSE_NO) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// directory needs to exist and be writable
|
||||
|
||||
string dirpath = PBD::dirname (filepath);
|
||||
if (::access (dirpath.c_str(), W_OK) != 0) {
|
||||
string txt = _("Cannot write file in: ") + dirpath;
|
||||
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
|
||||
msg.run();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ExportDialog::initSpec(string &filepath)
|
||||
{
|
||||
spec.path = filepath;
|
||||
spec.progress = 0;
|
||||
spec.running = true;
|
||||
spec.stop = false;
|
||||
spec.port_map.clear();
|
||||
|
||||
if (channel_count_combo.get_active_text() == _("mono")) {
|
||||
spec.channels = 1;
|
||||
} else {
|
||||
spec.channels = 2;
|
||||
}
|
||||
|
||||
spec.format = 0;
|
||||
|
||||
spec.format |= sndfile_header_format_from_string (header_format_combo.get_active_text ());
|
||||
|
||||
if ((spec.format & SF_FORMAT_WAV) == 0) {
|
||||
/* RIFF/WAV specifies endianess */
|
||||
spec.format |= sndfile_endian_format_from_string (endian_format_combo.get_active_text ());
|
||||
}
|
||||
|
||||
spec.format |= sndfile_bitdepth_format_from_string (bitdepth_format_combo.get_active_text ());
|
||||
|
||||
string sr_str = sample_rate_combo.get_active_text();
|
||||
if (sr_str == N_("22.05kHz")) {
|
||||
spec.sample_rate = 22050;
|
||||
} else if (sr_str == N_("44.1kHz")) {
|
||||
spec.sample_rate = 44100;
|
||||
} else if (sr_str == N_("48kHz")) {
|
||||
spec.sample_rate = 48000;
|
||||
} else if (sr_str == N_("88.2kHz")) {
|
||||
spec.sample_rate = 88200;
|
||||
} else if (sr_str == N_("96kHz")) {
|
||||
spec.sample_rate = 96000;
|
||||
} else if (sr_str == N_("192kHz")) {
|
||||
spec.sample_rate = 192000;
|
||||
} else {
|
||||
spec.sample_rate = session->frame_rate();
|
||||
}
|
||||
|
||||
string src_str = src_quality_combo.get_active_text();
|
||||
if (src_str == _("fastest")) {
|
||||
spec.src_quality = SRC_ZERO_ORDER_HOLD;
|
||||
} else if (src_str == _("linear")) {
|
||||
spec.src_quality = SRC_LINEAR;
|
||||
} else if (src_str == _("better")) {
|
||||
spec.src_quality = SRC_SINC_FASTEST;
|
||||
} else if (src_str == _("intermediate")) {
|
||||
spec.src_quality = SRC_SINC_MEDIUM_QUALITY;
|
||||
} else {
|
||||
spec.src_quality = SRC_SINC_BEST_QUALITY;
|
||||
}
|
||||
|
||||
string dither_str = dither_type_combo.get_active_text();
|
||||
if (dither_str == _("None")) {
|
||||
spec.dither_type = GDitherNone;
|
||||
} else if (dither_str == _("Rectangular")) {
|
||||
spec.dither_type = GDitherRect;
|
||||
} else if (dither_str == _("Triangular")) {
|
||||
spec.dither_type = GDitherTri;
|
||||
} else {
|
||||
spec.dither_type = GDitherShaped;
|
||||
}
|
||||
|
||||
write_track_and_master_selection_to_spec();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExportDialog::write_track_and_master_selection_to_spec()
|
||||
{
|
||||
if(!track_and_master_selection_allowed){
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t chan=0;
|
||||
Port *last_port = 0;
|
||||
|
||||
TreeModel::Children rows = master_selector.get_model()->children();
|
||||
TreeModel::Children::iterator ri;
|
||||
TreeModel::Row row;
|
||||
for (ri = rows.begin(); ri != rows.end(); ++ri) {
|
||||
row = *ri;
|
||||
Port* port = row[exp_cols.port];
|
||||
|
||||
if (last_port != port) {
|
||||
chan = 0;
|
||||
}
|
||||
|
||||
if (row[exp_cols.left]) {
|
||||
spec.port_map[0].push_back (std::pair<Port*,uint32_t>(port, chan));
|
||||
}
|
||||
|
||||
if (spec.channels == 2) {
|
||||
if (row[exp_cols.right]) {
|
||||
spec.port_map[1].push_back (std::pair<Port*,uint32_t>(port, chan));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chan = 0;
|
||||
rows = track_selector.get_model()->children();
|
||||
|
||||
for (ri = rows.begin(); ri != rows.end(); ++ri) {
|
||||
row = *ri;
|
||||
|
||||
Port* port = row[exp_cols.port];
|
||||
|
||||
if (last_port != port) {
|
||||
chan = 0;
|
||||
}
|
||||
|
||||
if (row[exp_cols.left]) {
|
||||
spec.port_map[0].push_back (std::pair<Port*,uint32_t>(port, chan));
|
||||
}
|
||||
|
||||
if (spec.channels == 2) {
|
||||
if (row[exp_cols.right]) {
|
||||
spec.port_map[1].push_back (std::pair<Port*,uint32_t>(port, chan));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
last_port = port;
|
||||
++chan;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gint
|
||||
ExportDialog::window_closed (GdkEventAny *ignored)
|
||||
{
|
||||
end_dialog ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
ExportDialog::initiate_browse ()
|
||||
{
|
||||
|
@ -49,15 +49,17 @@ namespace ARDOUR {
|
||||
class ExportDialog : public ArdourDialog
|
||||
{
|
||||
public:
|
||||
ExportDialog (PublicEditor&, ARDOUR::AudioRegion* r = 0);
|
||||
ExportDialog (PublicEditor&);
|
||||
~ExportDialog ();
|
||||
|
||||
void connect_to_session (ARDOUR::Session*);
|
||||
void set_range (jack_nframes_t start, jack_nframes_t end);
|
||||
virtual void set_range (jack_nframes_t start, jack_nframes_t end);
|
||||
void start_export ();
|
||||
|
||||
protected:
|
||||
struct ExportModelColumns : public Gtk::TreeModel::ColumnRecord
|
||||
ARDOUR::AudioExportSpecification spec;
|
||||
|
||||
struct ExportModelColumns : public Gtk::TreeModel::ColumnRecord
|
||||
{
|
||||
public:
|
||||
Gtk::TreeModelColumn<std::string> output;
|
||||
@ -69,11 +71,41 @@ class ExportDialog : public ArdourDialog
|
||||
};
|
||||
|
||||
ExportModelColumns exp_cols;
|
||||
|
||||
// These methods are intended to be used in constructors of subclasses
|
||||
void do_not_allow_track_and_master_selection();
|
||||
void do_not_allow_channel_count_selection();
|
||||
void do_not_allow_export_cd_markers();
|
||||
|
||||
// Checks the given filename for validity when export gets started.
|
||||
// Export will interrupt when this method returns 'false'.
|
||||
// Method is responsible for informing user.
|
||||
virtual bool is_filepath_valid(string &filepath);
|
||||
|
||||
// Gets called from within do_export. Is responsible for exporting the
|
||||
// audio data. spec has already been filled with user input before calling
|
||||
// this method. The dialog will be closed after this function exited.
|
||||
virtual void export_audio_data() = 0;
|
||||
|
||||
// reads the user input and fills spec with the according values
|
||||
// filepath: complete path to the target file, including filename
|
||||
void initSpec(string &filepath);
|
||||
|
||||
void set_progress_fraction(double progress) {
|
||||
progress_bar.set_fraction (progress); }
|
||||
|
||||
ARDOUR::Session& getSession() { return *session; };
|
||||
string get_selected_header_format() {
|
||||
return header_format_combo.get_active_text(); };
|
||||
string get_selected_file_name() { return file_entry.get_text(); };
|
||||
|
||||
private:
|
||||
PublicEditor& editor;
|
||||
ARDOUR::Session* session;
|
||||
ARDOUR::AudioRegion* audio_region;
|
||||
bool track_and_master_selection_allowed;
|
||||
bool channel_count_selection_allowed;
|
||||
bool export_cd_markers_allowed;
|
||||
|
||||
Gtk::VBox track_vpacker;
|
||||
Gtk::HBox hpacker;
|
||||
|
||||
@ -123,10 +155,10 @@ class ExportDialog : public ArdourDialog
|
||||
Gtk::TreeView master_selector;
|
||||
Glib::RefPtr<Gtk::ListStore> master_list;
|
||||
Gtk::FileSelection *file_selector;
|
||||
ARDOUR::AudioExportSpecification spec;
|
||||
|
||||
static void *_thread (void *arg);
|
||||
gint progress_timeout ();
|
||||
// sets the export progress in the progress bar
|
||||
virtual gint progress_timeout ();
|
||||
sigc::connection progress_connection;
|
||||
void build_window ();
|
||||
void end_dialog();
|
||||
@ -137,8 +169,9 @@ class ExportDialog : public ArdourDialog
|
||||
void cue_file_type_chosen();
|
||||
|
||||
void fill_lists();
|
||||
void write_track_and_master_selection_to_spec();
|
||||
|
||||
void do_export_cd_markers (const string& path, const string& cuefile_type);
|
||||
void do_export_cd_markers (const string& path, const string& cuefile_type);
|
||||
void export_cue_file (ARDOUR::Locations::LocationList& locations, const string& path);
|
||||
void export_toc_file (ARDOUR::Locations::LocationList& locations, const string& path);
|
||||
void do_export ();
|
||||
@ -151,10 +184,6 @@ class ExportDialog : public ArdourDialog
|
||||
|
||||
void set_state();
|
||||
void save_state();
|
||||
|
||||
static void* _export_region_thread (void *);
|
||||
void export_region ();
|
||||
};
|
||||
|
||||
#endif // __ardour_export_dialog_h__
|
||||
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <gtkmm/messagedialog.h>
|
||||
|
||||
#include <pbd/lockmonitor.h>
|
||||
|
||||
#include <ardour/io.h>
|
||||
@ -36,7 +38,6 @@
|
||||
#include <gtkmm2ext/utils.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "ardour_message.h"
|
||||
#include "io_selector.h"
|
||||
#include "keyboard.h"
|
||||
#include "gui_thread.h"
|
||||
@ -557,7 +558,8 @@ IOSelector::add_port ()
|
||||
}
|
||||
|
||||
catch (AudioEngine::PortRegistrationFailure& err) {
|
||||
ArdourMessage msg (0, X_("noport dialog"), _("There are no more JACK ports available."));
|
||||
MessageDialog msg (0, _("There are no more JACK ports available."));
|
||||
msg.run ();
|
||||
}
|
||||
|
||||
if (io.input_maximum() >= 0 && io.input_maximum() <= (int) io.n_inputs()) {
|
||||
@ -575,8 +577,8 @@ IOSelector::add_port ()
|
||||
}
|
||||
|
||||
catch (AudioEngine::PortRegistrationFailure& err) {
|
||||
ArdourMessage msg (0, X_("noport dialog"),
|
||||
_("There are no more JACK ports available."));
|
||||
MessageDialog msg (0, _("There are no more JACK ports available."));
|
||||
msg.run ();
|
||||
}
|
||||
|
||||
if (io.output_maximum() >= 0 && io.output_maximum() <= (int) io.n_outputs()) {
|
||||
|
@ -791,3 +791,14 @@ Keyboard::modifier_state_equals (guint state, ModifierMask mask)
|
||||
return (state & RelevantModifierKeyMask) == (guint) mask;
|
||||
}
|
||||
|
||||
Selection::Operation
|
||||
Keyboard::selection_type (guint state)
|
||||
{
|
||||
if (modifier_state_equals (state, Shift)) {
|
||||
return Selection::Extend;
|
||||
} else if (modifier_state_equals (state, Control)) {
|
||||
return Selection::Toggle;
|
||||
} else {
|
||||
return Selection::Set;
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <ardour/types.h>
|
||||
#include <ardour/stateful.h>
|
||||
|
||||
#include "selection.h"
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
@ -71,6 +73,8 @@ class Keyboard : public sigc::trackable, Stateful
|
||||
static bool modifier_state_contains (guint state, ModifierMask);
|
||||
static bool modifier_state_equals (guint state, ModifierMask);
|
||||
|
||||
static Selection::Operation selection_type (guint state);
|
||||
|
||||
static bool no_modifiers_active (guint state);
|
||||
|
||||
static void set_meta_modifier (guint);
|
||||
|
@ -784,7 +784,8 @@ LocationUI::add_new_range()
|
||||
{
|
||||
if (session) {
|
||||
jack_nframes_t where = session->audible_frame();
|
||||
Location *location = new Location (where, where, "unnamed");
|
||||
Location *location = new Location (where, where, "unnamed",
|
||||
Location::IsRangeMarker);
|
||||
session->begin_reversible_command (_("add range marker"));
|
||||
session->add_undo (session->locations()->get_memento());
|
||||
session->locations()->add (location, true);
|
||||
|
@ -46,7 +46,6 @@
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "ardour_dialog.h"
|
||||
#include "ardour_message.h"
|
||||
#include "mixer_strip.h"
|
||||
#include "mixer_ui.h"
|
||||
#include "keyboard.h"
|
||||
@ -528,8 +527,9 @@ MixerStrip::output_press (GdkEventButton *ev)
|
||||
using namespace Menu_Helpers;
|
||||
|
||||
if (!_session.engine().connected()) {
|
||||
ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible"));
|
||||
return TRUE;
|
||||
MessageDialog msg (_("Not connected to JACK - no I/O changes are possible"));
|
||||
msg.run ();
|
||||
return true;
|
||||
}
|
||||
|
||||
MenuList& citems = output_menu.items();
|
||||
@ -586,8 +586,9 @@ MixerStrip::input_press (GdkEventButton *ev)
|
||||
citems.clear();
|
||||
|
||||
if (!_session.engine().connected()) {
|
||||
ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible"));
|
||||
return TRUE;
|
||||
MessageDialog msg (_("Not connected to JACK - no I/O changes are possible"));
|
||||
msg.run ();
|
||||
return true;
|
||||
}
|
||||
|
||||
#if ADVANCED_ROUTE_DISKSTREAM_CONNECTIVITY
|
||||
|
@ -94,6 +94,7 @@ class PublicEditor : public Gtk::Window, public Stateful {
|
||||
virtual bool show_measures () const = 0;
|
||||
virtual void export_session() = 0;
|
||||
virtual void export_selection() = 0;
|
||||
virtual void export_range_markers() = 0;
|
||||
virtual void register_actions() = 0;
|
||||
virtual void add_toplevel_controls (Gtk::Container&) = 0;
|
||||
virtual void set_zoom_focus (Editing::ZoomFocus) = 0;
|
||||
@ -172,4 +173,4 @@ class PublicEditor : public Gtk::Window, public Stateful {
|
||||
static PublicEditor* _instance;
|
||||
};
|
||||
|
||||
#endif // __gtk_ardour_public_editor_h__
|
||||
#endif // __gtk_ardour_public_editor_h__
|
||||
|
@ -23,6 +23,8 @@
|
||||
|
||||
#include <sigc++/bind.h>
|
||||
|
||||
#include <gtkmm/messagedialog.h>
|
||||
|
||||
#include <gtkmm2ext/gtk_ui.h>
|
||||
#include <gtkmm2ext/utils.h>
|
||||
#include <gtkmm2ext/choice.h>
|
||||
@ -44,7 +46,6 @@
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "ardour_dialog.h"
|
||||
#include "ardour_message.h"
|
||||
#include "public_editor.h"
|
||||
#include "redirect_box.h"
|
||||
#include "keyboard.h"
|
||||
@ -318,10 +319,7 @@ void
|
||||
RedirectBox::selection_changed ()
|
||||
{
|
||||
bool sensitive = (redirect_display.get_selection()->count_selected_rows()) ? true : false;
|
||||
|
||||
for (vector<Glib::RefPtr<Gtk::Action> >::iterator i = ActionManager::plugin_selection_sensitive_actions.begin(); i != ActionManager::plugin_selection_sensitive_actions.end(); ++i) {
|
||||
(*i)->set_sensitive (sensitive);
|
||||
}
|
||||
ActionManager::set_sensitive (ActionManager::plugin_selection_sensitive_actions, sensitive);
|
||||
}
|
||||
|
||||
void
|
||||
@ -830,7 +828,8 @@ RedirectBox::paste_redirect_list (list<Redirect*>& redirects)
|
||||
"Copying the set of redirects on the clipboard failed,\n\
|
||||
probably because the I/O configuration of the plugins\n\
|
||||
could not match the configuration of this track.");
|
||||
ArdourMessage am (0, X_("bad redirect copy dialog"), msg);
|
||||
MessageDialog am (msg);
|
||||
am.run ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -877,7 +876,8 @@ RedirectBox::clone_redirects ()
|
||||
"Copying the set of redirects on the clipboard failed,\n\
|
||||
probably because the I/O configuration of the plugins\n\
|
||||
could not match the configuration of this track.");
|
||||
ArdourMessage am (0, X_("bad redirect copy dialog"), msg);
|
||||
MessageDialog am (msg);
|
||||
am.run ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1011,7 +1011,8 @@ RedirectBox::edit_redirect (Redirect* redirect)
|
||||
} else if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
|
||||
|
||||
if (!_session.engine().connected()) {
|
||||
ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible"));
|
||||
MessageDialog msg ( _("Not connected to JACK - no I/O changes are possible"));
|
||||
msg.run ();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -149,6 +149,116 @@ Selection::clear_lines ()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Selection::toggle (Redirect* r)
|
||||
{
|
||||
if (find (redirects.begin(), redirects.end(), r) == redirects.end()) {
|
||||
redirects.push_back (r);
|
||||
RedirectsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Selection::toggle (Playlist* pl)
|
||||
{
|
||||
if (find (playlists.begin(), playlists.end(), pl) == playlists.end()) {
|
||||
pl->ref ();
|
||||
playlists.push_back(pl);
|
||||
PlaylistsChanged ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Selection::toggle (const list<Playlist*>& pllist)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
for (list<Playlist*>::const_iterator i = pllist.begin(); i != pllist.end(); ++i) {
|
||||
if (find (playlists.begin(), playlists.end(), (*i)) == playlists.end()) {
|
||||
(*i)->ref ();
|
||||
playlists.push_back (*i);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
PlaylistsChanged ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Selection::toggle (const list<TimeAxisView*>& track_list)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
for (list<TimeAxisView*>::const_iterator i = track_list.begin(); i != track_list.end(); ++i) {
|
||||
if (find (tracks.begin(), tracks.end(), (*i)) == tracks.end()) {
|
||||
void (Selection::*pmf)(TimeAxisView*) = &Selection::remove;
|
||||
(*i)->GoingAway.connect (sigc::bind (mem_fun (*this, pmf), (*i)));
|
||||
tracks.push_back (*i);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
TracksChanged ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Selection::toggle (TimeAxisView* track)
|
||||
{
|
||||
if (find (tracks.begin(), tracks.end(), track) == tracks.end()) {
|
||||
void (Selection::*pmf)(TimeAxisView*) = &Selection::remove;
|
||||
track->GoingAway.connect (sigc::bind (mem_fun (*this, pmf), track));
|
||||
tracks.push_back (track);
|
||||
TracksChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Selection::toggle (AudioRegionView* r)
|
||||
{
|
||||
if (find (audio_regions.begin(), audio_regions.end(), r) == audio_regions.end()) {
|
||||
audio_regions.add (r);
|
||||
RegionsChanged ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Selection::toggle (vector<AudioRegionView*>& v)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
for (vector<AudioRegionView*>::iterator i = v.begin(); i != v.end(); ++i) {
|
||||
if (find (audio_regions.begin(), audio_regions.end(), (*i)) == audio_regions.end()) {
|
||||
audio_regions.add ((*i));
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
RegionsChanged ();
|
||||
}
|
||||
}
|
||||
|
||||
long
|
||||
Selection::toggle (jack_nframes_t start, jack_nframes_t end)
|
||||
{
|
||||
AudioRangeComparator cmp;
|
||||
|
||||
/* XXX this implementation is incorrect */
|
||||
|
||||
time.push_back (AudioRange (start, end, next_time_id++));
|
||||
time.consolidate ();
|
||||
time.sort (cmp);
|
||||
|
||||
TimeChanged ();
|
||||
|
||||
return next_time_id - 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Selection::add (Redirect* r)
|
||||
{
|
||||
@ -247,6 +357,8 @@ Selection::add (jack_nframes_t start, jack_nframes_t end)
|
||||
{
|
||||
AudioRangeComparator cmp;
|
||||
|
||||
/* XXX this implementation is incorrect */
|
||||
|
||||
time.push_back (AudioRange (start, end, next_time_id++));
|
||||
time.consolidate ();
|
||||
time.sort (cmp);
|
||||
|
@ -21,6 +21,8 @@
|
||||
#ifndef __ardour_gtk_selection_h__
|
||||
#define __ardour_gtk_selection_h__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <sigc++/signal.h>
|
||||
|
||||
#include "time_selection.h"
|
||||
@ -35,6 +37,14 @@ class TimeAxisView;
|
||||
class AudioRegionView;
|
||||
class Selectable;
|
||||
|
||||
namespace ARDOUR {
|
||||
class Region;
|
||||
class AudioRegion;
|
||||
class Playlist;
|
||||
class Redirect;
|
||||
class AutomationList;
|
||||
}
|
||||
|
||||
class Selection : public sigc::trackable
|
||||
{
|
||||
public:
|
||||
@ -43,6 +53,12 @@ class Selection : public sigc::trackable
|
||||
Range = 0x2
|
||||
};
|
||||
|
||||
enum Operation {
|
||||
Set,
|
||||
Toggle,
|
||||
Extend
|
||||
};
|
||||
|
||||
TrackSelection tracks;
|
||||
AudioRegionSelection audio_regions;
|
||||
TimeSelection time;
|
||||
@ -88,6 +104,16 @@ class Selection : public sigc::trackable
|
||||
void set (ARDOUR::Redirect*);
|
||||
void set (AutomationSelectable*);
|
||||
|
||||
void toggle (TimeAxisView*);
|
||||
void toggle (const list<TimeAxisView*>&);
|
||||
void toggle (AudioRegionView*);
|
||||
void toggle (std::vector<AudioRegionView*>&);
|
||||
long toggle (jack_nframes_t, jack_nframes_t);
|
||||
void toggle (ARDOUR::AutomationList*);
|
||||
void toggle (ARDOUR::Playlist*);
|
||||
void toggle (const list<ARDOUR::Playlist*>&);
|
||||
void toggle (ARDOUR::Redirect*);
|
||||
|
||||
void add (TimeAxisView*);
|
||||
void add (const list<TimeAxisView*>&);
|
||||
void add (AudioRegionView*);
|
||||
@ -97,7 +123,7 @@ class Selection : public sigc::trackable
|
||||
void add (ARDOUR::Playlist*);
|
||||
void add (const list<ARDOUR::Playlist*>&);
|
||||
void add (ARDOUR::Redirect*);
|
||||
|
||||
|
||||
void remove (TimeAxisView*);
|
||||
void remove (const list<TimeAxisView*>&);
|
||||
void remove (AudioRegionView*);
|
||||
@ -126,7 +152,7 @@ class Selection : public sigc::trackable
|
||||
private:
|
||||
uint32_t next_time_id;
|
||||
|
||||
void add (vector<AutomationSelectable*>&);
|
||||
void add (std::vector<AutomationSelectable*>&);
|
||||
};
|
||||
|
||||
bool operator==(const Selection& a, const Selection& b);
|
||||
|
@ -407,7 +407,7 @@ pane_handler (GdkEventButton* ev, Gtk::Paned* pane)
|
||||
|
||||
/* already collapsed: restore it (note that this is cast from a pointer value to int, which is tricky on 64bit */
|
||||
|
||||
pane->set_position ((gint64) pane->get_data ("rpos"));
|
||||
pane->set_position ((intptr_t) pane->get_data ("rpos"));
|
||||
|
||||
} else {
|
||||
|
||||
@ -419,7 +419,7 @@ pane_handler (GdkEventButton* ev, Gtk::Paned* pane)
|
||||
|
||||
/* collapse to show the relevant child in full */
|
||||
|
||||
collapse_direction = (gint64) pane->get_data ("collapse-direction");
|
||||
collapse_direction = (intptr_t) pane->get_data ("collapse-direction");
|
||||
|
||||
if (collapse_direction) {
|
||||
pane->set_position (1);
|
||||
|
@ -28,6 +28,7 @@ namespace ARDOUR {
|
||||
class Session;
|
||||
class DiskStream;
|
||||
class AudioPlaylist;
|
||||
class RouteGroup;
|
||||
|
||||
class AudioTrack : public Route
|
||||
{
|
||||
|
@ -50,7 +50,8 @@ class Location : public Stateful, public sigc::trackable
|
||||
IsAutoLoop = 0x4,
|
||||
IsHidden = 0x8,
|
||||
IsCDMarker = 0x10,
|
||||
IsEnd = 0x20
|
||||
IsEnd = 0x20,
|
||||
IsRangeMarker = 0x40
|
||||
};
|
||||
|
||||
Location (jack_nframes_t sample_start,
|
||||
@ -95,6 +96,7 @@ class Location : public Stateful, public sigc::trackable
|
||||
bool is_hidden () { return _flags & IsHidden; }
|
||||
bool is_cd_marker () { return _flags & IsCDMarker; }
|
||||
bool is_end() { return _flags & IsEnd; }
|
||||
bool is_range_marker() { return _flags & IsRangeMarker; }
|
||||
|
||||
sigc::signal<void,Location*> name_changed;
|
||||
sigc::signal<void,Location*> end_changed;
|
||||
@ -145,6 +147,8 @@ class Locations : public Stateful, public StateManager
|
||||
Location* auto_punch_location () const;
|
||||
Location* end_location() const;
|
||||
|
||||
uint32_t num_range_markers() const;
|
||||
|
||||
int set_current (Location *, bool want_lock = true);
|
||||
Location *current () const { return current_location; }
|
||||
|
||||
@ -179,7 +183,7 @@ class Locations : public Stateful, public StateManager
|
||||
|
||||
LocationList locations;
|
||||
Location *current_location;
|
||||
PBD::Lock lock;
|
||||
mutable PBD::Lock lock;
|
||||
|
||||
int set_current_unlocked (Location *);
|
||||
void location_changed (Location*);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#define __ardour_route_group_h__
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <sigc++/signal.h>
|
||||
@ -84,6 +85,10 @@ class RouteGroup : public Stateful, public sigc::trackable {
|
||||
|
||||
template<class T> void apply (void (AudioTrack::*func)(T, void *), T val, void *src);
|
||||
|
||||
/* fills at_set with all members of the group that are AudioTracks */
|
||||
|
||||
void audio_track_group (std::set<AudioTrack*>& at_set);
|
||||
|
||||
void clear () {
|
||||
routes.clear ();
|
||||
changed();
|
||||
|
@ -16,7 +16,7 @@ RouteGroup::apply (void (AudioTrack::*func)(T, void *), T val, void *src)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} /* namespace ARDOUR */
|
||||
|
||||
#endif /* __ardour_route_group_specialized_h__ */
|
||||
|
@ -10,6 +10,7 @@ using std::string;
|
||||
|
||||
#define SNDFILE_HEADER_FORMATS 7
|
||||
extern const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1];
|
||||
extern const char * const sndfile_file_endings_strings[SNDFILE_HEADER_FORMATS+1];
|
||||
|
||||
extern int sndfile_header_formats[SNDFILE_HEADER_FORMATS];
|
||||
|
||||
@ -26,6 +27,7 @@ extern int sndfile_endian_formats[SNDFILE_ENDIAN_FORMATS];
|
||||
int sndfile_bitdepth_format_from_string(string);
|
||||
int sndfile_header_format_from_string(string);
|
||||
int sndfile_endian_format_from_string(string);
|
||||
string sndfile_file_ending_from_string(string);
|
||||
|
||||
int sndfile_data_width (int format);
|
||||
|
||||
|
@ -4,8 +4,13 @@
|
||||
#include <pbd/compose.h>
|
||||
#include "gettext.h"
|
||||
|
||||
#define _(Text) dgettext (PACKAGE, Text)
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
std::vector<std::string> internationalize (const char **);
|
||||
|
||||
#define _(Text) dgettext (PACKAGE,Text)
|
||||
#define N_(Text) gettext_noop (Text)
|
||||
#define X_(Text) (Text)
|
||||
#define X_(Text) Text
|
||||
|
||||
#endif // __i18n_h__
|
||||
|
@ -719,3 +719,16 @@ Locations::get_memento () const
|
||||
{
|
||||
return sigc::bind (mem_fun (*(const_cast<Locations*> (this)), &StateManager::use_state), _current_state_id);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Locations::num_range_markers () const
|
||||
{
|
||||
uint32_t cnt = 0;
|
||||
LockMonitor lm (lock, __LINE__, __FILE__);
|
||||
for (LocationList::const_iterator i = locations.begin(); i != locations.end(); ++i) {
|
||||
if ((*i)->is_range_marker()) {
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <pbd/error.h>
|
||||
|
||||
#include <ardour/route_group.h>
|
||||
#include <ardour/audio_track.h>
|
||||
#include <ardour/diskstream.h>
|
||||
#include <ardour/configuration.h>
|
||||
|
||||
@ -182,3 +183,15 @@ RouteGroup::set_hidden (bool yn, void *src)
|
||||
}
|
||||
FlagsChanged (src); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
RouteGroup::audio_track_group (set<AudioTrack*>& ats)
|
||||
{
|
||||
for (list<Route*>::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||
AudioTrack* at = dynamic_cast<AudioTrack*>(*i);
|
||||
if (at) {
|
||||
ats.insert (at);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#include <ardour/sndfile_helpers.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using std::map;
|
||||
using namespace std;
|
||||
|
||||
const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1] = {
|
||||
N_("WAV"),
|
||||
@ -19,6 +20,17 @@ const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1] = {
|
||||
0
|
||||
};
|
||||
|
||||
const char* const sndfile_file_endings_strings[SNDFILE_HEADER_FORMATS+1] = {
|
||||
N_(".wav"),
|
||||
N_(".aiff"),
|
||||
N_(".raw"),
|
||||
N_(".paf"),
|
||||
N_(".au"),
|
||||
N_(".ircam"),
|
||||
N_(".w64"),
|
||||
0
|
||||
};
|
||||
|
||||
int sndfile_header_formats[SNDFILE_HEADER_FORMATS] = {
|
||||
SF_FORMAT_WAV,
|
||||
SF_FORMAT_AIFF,
|
||||
@ -90,6 +102,23 @@ sndfile_endian_format_from_string (string str)
|
||||
return -1;
|
||||
}
|
||||
|
||||
string
|
||||
sndfile_file_ending_from_string (string str)
|
||||
{
|
||||
static vector<string> file_endings;
|
||||
|
||||
if (file_endings.empty()) {
|
||||
file_endings = internationalize((const char **) sndfile_file_endings_strings);
|
||||
}
|
||||
|
||||
for (int n = 0; sndfile_header_formats_strings[n]; ++n) {
|
||||
if (str == sndfile_header_formats_strings[n]) {
|
||||
return file_endings[n];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sndfile_data_width (int format)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user