summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/SConscript4
-rw-r--r--gtk2_ardour/actions.cc7
-rw-r--r--gtk2_ardour/actions.h8
-rw-r--r--gtk2_ardour/ardour.menus3
-rw-r--r--gtk2_ardour/ardour_ui.cc41
-rw-r--r--gtk2_ardour/ardour_ui.h1
-rw-r--r--gtk2_ardour/ardour_ui_dialogs.cc29
-rw-r--r--gtk2_ardour/ardour_ui_ed.cc8
-rw-r--r--gtk2_ardour/audio_time_axis.cc43
-rw-r--r--gtk2_ardour/audio_time_axis.h1
-rw-r--r--gtk2_ardour/editor.cc189
-rw-r--r--gtk2_ardour/editor.h27
-rw-r--r--gtk2_ardour/editor_actions.cc2
-rw-r--r--gtk2_ardour/editor_export_audio.cc43
-rw-r--r--gtk2_ardour/editor_keys.cc6
-rw-r--r--gtk2_ardour/editor_markers.cc4
-rw-r--r--gtk2_ardour/editor_mouse.cc149
-rw-r--r--gtk2_ardour/editor_ops.cc36
-rw-r--r--gtk2_ardour/editor_region_list.cc2
-rw-r--r--gtk2_ardour/export_dialog.cc478
-rw-r--r--gtk2_ardour/export_dialog.h51
-rw-r--r--gtk2_ardour/io_selector.cc10
-rw-r--r--gtk2_ardour/keyboard.cc11
-rw-r--r--gtk2_ardour/keyboard.h4
-rw-r--r--gtk2_ardour/location_ui.cc3
-rw-r--r--gtk2_ardour/mixer_strip.cc11
-rw-r--r--gtk2_ardour/public_editor.h3
-rw-r--r--gtk2_ardour/redirect_box.cc17
-rw-r--r--gtk2_ardour/selection.cc112
-rw-r--r--gtk2_ardour/selection.h30
-rw-r--r--gtk2_ardour/utils.cc4
-rw-r--r--libs/ardour/ardour/audio_track.h1
-rw-r--r--libs/ardour/ardour/location.h8
-rw-r--r--libs/ardour/ardour/route_group.h5
-rw-r--r--libs/ardour/ardour/route_group_specialized.h2
-rw-r--r--libs/ardour/ardour/sndfile_helpers.h2
-rw-r--r--libs/ardour/i18n.h9
-rw-r--r--libs/ardour/location.cc13
-rw-r--r--libs/ardour/route_group.cc13
-rw-r--r--libs/ardour/sndfile_helpers.cc31
40 files changed, 986 insertions, 435 deletions
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript
index 8ea3f27d81..c0fa90c4d5 100644
--- a/gtk2_ardour/SConscript
+++ b/gtk2_ardour/SConscript
@@ -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
diff --git a/gtk2_ardour/actions.cc b/gtk2_ardour/actions.cc
index 9f8c95ce2c..1ca9278baf 100644
--- a/gtk2_ardour/actions.cc
+++ b/gtk2_ardour/actions.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;
diff --git a/gtk2_ardour/actions.h b/gtk2_ardour/actions.h
index b842693eba..330caff1c2 100644
--- a/gtk2_ardour/actions.h
+++ b/gtk2_ardour/actions.h
@@ -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;
diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus
index 1e5ce5edfd..372b4fcee2 100644
--- a/gtk2_ardour/ardour.menus
+++ b/gtk2_ardour/ardour.menus
@@ -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'>
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 752a6f693d..b9f00340db 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -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);
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index fea1128799..7dc7226c7a 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -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;
diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc
index 08501e746a..29dc204af9 100644
--- a/gtk2_ardour/ardour_ui_dialogs.cc
+++ b/gtk2_ardour/ardour_ui_dialogs.cc
@@ -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);
+ }
+ }
+}
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index 5737eba319..bc34adfece 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -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);
}
-
diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc
index 0c0c402934..88a0f5eb57 100644
--- a/gtk2_ardour/audio_time_axis.cc
+++ b/gtk2_ardour/audio_time_axis.cc
@@ -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;
}
@@ -853,22 +858,17 @@ 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 ()
{
AudioPlaylist *pl;
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;
diff --git a/gtk2_ardour/audio_time_axis.h b/gtk2_ardour/audio_time_axis.h
index 19d9f6676c..c481c54ed5 100644
--- a/gtk2_ardour/audio_time_axis.h
+++ b/gtk2_ardour/audio_time_axis.h
@@ -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 ();
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 066f29499e..9d788f1566 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -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)
{
- if (!clicked_regionview) {
- return;
- }
+ set<AudioTimeAxisView*> relevant_tracks;
- AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
+ /* step one: get all selected tracks and all tracks in the relevant edit groups */
- if (!atv) {
- return;
- }
+ for (TrackSelection::iterator ti = selection->tracks.begin(); ti != selection->tracks.end(); ++ti) {
- 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* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
- AudioTimeAxisView* tatv;
+ if (!atv) {
+ continue;
+ }
- if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
+ RouteGroup* group = atv->route().edit_group();
- if (tatv->route().edit_group() != group) {
- continue;
- }
+ if (group && group->is_active()) {
- AudioPlaylist* pl;
- vector<AudioRegion*> results;
- AudioRegionView* marv;
- DiskStream* ds;
-
- if ((ds = tatv->get_diskstream()) == 0) {
- /* bus */
- continue;
- }
+ /* 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) {
- if ((pl = ds->playlist()) != 0) {
- pl->get_equivalent_regions (clicked_regionview->region,
- results);
- }
+ AudioTimeAxisView* tatv;
- 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);
+ 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);
}
- } else {
+ }
- all_equivalent_regions.push_back (clicked_regionview);
+ /* 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;
}
- begin_reversible_command (_("set selected regionview"));
+ if ((pl = ds->playlist()) != 0) {
+ pl->get_equivalent_regions (basis->region, results);
+ }
- if (add) {
+ 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;
+ }
+ 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"));
+
+ 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
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 19c2448f5f..57574d82ba 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -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&);
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
index 0dfef6f4e9..ece1aa305d 100644
--- a/gtk2_ardour/editor_actions.cc
+++ b/gtk2_ardour/editor_actions.cc
@@ -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);
diff --git a/gtk2_ardour/editor_export_audio.cc b/gtk2_ardour/editor_export_audio.cc
index 4964611db3..8ad432ece6 100644
--- a/gtk2_ardour/editor_export_audio.cc
+++ b/gtk2_ardour/editor_export_audio.cc
@@ -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)
{
diff --git a/gtk2_ardour/editor_keys.cc b/gtk2_ardour/editor_keys.cc
index 226863b88b..00469281fc 100644
--- a/gtk2_ardour/editor_keys.cc
+++ b/gtk2_ardour/editor_keys.cc
@@ -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;
diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc
index 64ac0fe7e9..d933357685 100644
--- a/gtk2_ardour/editor_markers.cc
+++ b/gtk2_ardour/editor_markers.cc
@@ -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);
}
}
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index ad8522b202..023c500c83 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -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:
@@ -2143,6 +2151,39 @@ Editor::start_meter_marker_grab (ArdourCanvas::Item* item, GdkEvent* event)
}
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)
{
MeterMarker* marker = (MeterMarker *) drag_info.data;
@@ -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
@@ -2224,6 +2277,42 @@ Editor::start_tempo_marker_grab (ArdourCanvas::Item* item, GdkEvent* event)
}
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)
{
TempoMarker* marker = (TempoMarker *) drag_info.data;
@@ -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) {
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 7a7101d831..747b4d47ec 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -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();
diff --git a/gtk2_ardour/editor_region_list.cc b/gtk2_ardour/editor_region_list.cc
index 034c20f7f0..464a707512 100644
--- a/gtk2_ardour/editor_region_list.cc
+++ b/gtk2_ardour/editor_region_list.cc
@@ -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);
}
}
}
diff --git a/gtk2_ardour/export_dialog.cc b/gtk2_ardour/export_dialog.cc
index 1b75bbf49d..8df28965b2 100644
--- a/gtk2_ardour/export_dialog.cc
+++ b/gtk2_ardour/export_dialog.cc
@@ -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);
@@ -375,6 +367,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)
{
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;
- }
-
- // 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;
- }
- }
- }
+ string filepath = file_entry.get_text();
- // 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();
-
- 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();
- }
+ // read user input into spec
+ initSpec(filepath);
- 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 ()
{
diff --git a/gtk2_ardour/export_dialog.h b/gtk2_ardour/export_dialog.h
index c07cebaa96..c67300e0d2 100644
--- a/gtk2_ardour/export_dialog.h
+++ b/gtk2_ardour/export_dialog.h
@@ -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__
-
diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc
index 1f7c7dc045..81f39f27c5 100644
--- a/gtk2_ardour/io_selector.cc
+++ b/gtk2_ardour/io_selector.cc
@@ -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()) {
diff --git a/gtk2_ardour/keyboard.cc b/gtk2_ardour/keyboard.cc
index de2039620b..c0bbea798a 100644
--- a/gtk2_ardour/keyboard.cc
+++ b/gtk2_ardour/keyboard.cc
@@ -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;
+ }
+}
diff --git a/gtk2_ardour/keyboard.h b/gtk2_ardour/keyboard.h
index 9178546c8e..06ed4c800d 100644
--- a/gtk2_ardour/keyboard.h
+++ b/gtk2_ardour/keyboard.h
@@ -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);
diff --git a/gtk2_ardour/location_ui.cc b/gtk2_ardour/location_ui.cc
index c62c7a2e90..21d0fb5b15 100644
--- a/gtk2_ardour/location_ui.cc
+++ b/gtk2_ardour/location_ui.cc
@@ -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);
diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc
index 7ef34f2451..64caac4eef 100644
--- a/gtk2_ardour/mixer_strip.cc
+++ b/gtk2_ardour/mixer_strip.cc
@@ -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
diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h
index bf184670a4..a5d0df530d 100644
--- a/gtk2_ardour/public_editor.h
+++ b/gtk2_ardour/public_editor.h
@@ -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__
diff --git a/gtk2_ardour/redirect_box.cc b/gtk2_ardour/redirect_box.cc
index 0936ff378b..2ae34ac4cf 100644
--- a/gtk2_ardour/redirect_box.cc
+++ b/gtk2_ardour/redirect_box.cc
@@ -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;
}
diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc
index f96d649b04..d6efce7264 100644
--- a/gtk2_ardour/selection.cc
+++ b/gtk2_ardour/selection.cc
@@ -150,6 +150,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)
{
if (find (redirects.begin(), redirects.end(), r) == redirects.end()) {
@@ -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);
diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h
index ffda6a0b0f..ebeda1aea7 100644
--- a/gtk2_ardour/selection.h
+++ b/gtk2_ardour/selection.h
@@ -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);
diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc
index e609d0e33b..393f919d95 100644
--- a/gtk2_ardour/utils.cc
+++ b/gtk2_ardour/utils.cc
@@ -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);
diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h
index 0ef4c45f16..4dae06eeff 100644
--- a/libs/ardour/ardour/audio_track.h
+++ b/libs/ardour/ardour/audio_track.h
@@ -28,6 +28,7 @@ namespace ARDOUR {
class Session;
class DiskStream;
class AudioPlaylist;
+class RouteGroup;
class AudioTrack : public Route
{
diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h
index 1da67c78da..3728d0b346 100644
--- a/libs/ardour/ardour/location.h
+++ b/libs/ardour/ardour/location.h
@@ -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*);
diff --git a/libs/ardour/ardour/route_group.h b/libs/ardour/ardour/route_group.h
index 910500ccf8..ad523da9c7 100644
--- a/libs/ardour/ardour/route_group.h
+++ b/libs/ardour/ardour/route_group.h
@@ -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();
diff --git a/libs/ardour/ardour/route_group_specialized.h b/libs/ardour/ardour/route_group_specialized.h
index 32c627eb7a..0424002dcd 100644
--- a/libs/ardour/ardour/route_group_specialized.h
+++ b/libs/ardour/ardour/route_group_specialized.h
@@ -16,7 +16,7 @@ RouteGroup::apply (void (AudioTrack::*func)(T, void *), T val, void *src)
}
}
}
-
+
} /* namespace ARDOUR */
#endif /* __ardour_route_group_specialized_h__ */
diff --git a/libs/ardour/ardour/sndfile_helpers.h b/libs/ardour/ardour/sndfile_helpers.h
index 4a2c38eac3..bae73a0377 100644
--- a/libs/ardour/ardour/sndfile_helpers.h
+++ b/libs/ardour/ardour/sndfile_helpers.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);
diff --git a/libs/ardour/i18n.h b/libs/ardour/i18n.h
index 7c79d2eb53..3ace250419 100644
--- a/libs/ardour/i18n.h
+++ b/libs/ardour/i18n.h
@@ -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__
diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc
index 6008f3d70b..972384cc32 100644
--- a/libs/ardour/location.cc
+++ b/libs/ardour/location.cc
@@ -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;
+}
diff --git a/libs/ardour/route_group.cc b/libs/ardour/route_group.cc
index 225224e684..3d40483634 100644
--- a/libs/ardour/route_group.cc
+++ b/libs/ardour/route_group.cc
@@ -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);
+ }
+ }
+}
+
diff --git a/libs/ardour/sndfile_helpers.cc b/libs/ardour/sndfile_helpers.cc
index 2fd9e63ce2..21d8c72b2b 100644
--- a/libs/ardour/sndfile_helpers.cc
+++ b/libs/ardour/sndfile_helpers.cc
@@ -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)
{