export range markers patch (revisited), change selection model, copy-drag tempo+meter...
authorPaul Davis <paul@linuxaudiosystems.com>
Sun, 5 Mar 2006 19:39:16 +0000 (19:39 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Sun, 5 Mar 2006 19:39:16 +0000 (19:39 +0000)
git-svn-id: svn://localhost/trunk/ardour2@349 d708f5d6-7413-0410-9779-e7cbd77b26cf

40 files changed:
gtk2_ardour/SConscript
gtk2_ardour/actions.cc
gtk2_ardour/actions.h
gtk2_ardour/ardour.menus
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui_dialogs.cc
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/audio_time_axis.cc
gtk2_ardour/audio_time_axis.h
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_actions.cc
gtk2_ardour/editor_export_audio.cc
gtk2_ardour/editor_keys.cc
gtk2_ardour/editor_markers.cc
gtk2_ardour/editor_mouse.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_region_list.cc
gtk2_ardour/export_dialog.cc
gtk2_ardour/export_dialog.h
gtk2_ardour/io_selector.cc
gtk2_ardour/keyboard.cc
gtk2_ardour/keyboard.h
gtk2_ardour/location_ui.cc
gtk2_ardour/mixer_strip.cc
gtk2_ardour/public_editor.h
gtk2_ardour/redirect_box.cc
gtk2_ardour/selection.cc
gtk2_ardour/selection.h
gtk2_ardour/utils.cc
libs/ardour/ardour/audio_track.h
libs/ardour/ardour/location.h
libs/ardour/ardour/route_group.h
libs/ardour/ardour/route_group_specialized.h
libs/ardour/ardour/sndfile_helpers.h
libs/ardour/i18n.h
libs/ardour/location.cc
libs/ardour/route_group.cc
libs/ardour/sndfile_helpers.cc

index 8ea3f27d8170c987cd8b9a2823e922241303ebf8..c0fa90c4d54f3d0f4ff184f119678794fa2a6ee8 100644 (file)
@@ -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
index 9f8c95ce2c72637200948743d8702719167b0f44..1ca9278bafa9ea0382dc7682efb290369d8fce94 100644 (file)
@@ -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;
index b842693eba3804d3404e4e6b6eafbfaf61bde54e..330caff1c21250f4ad4ac0c266f2b5992b2c5b6e 100644 (file)
@@ -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;
index 1e5ce5edfd69c4cf1a25bbf0c04c6ef529bacf82..372b4fcee2ba88bfa23026b72a8ee6c30edb390a 100644 (file)
@@ -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'>
index 752a6f693ddffe886c1dceee4c6b56e6c114ba45..b9f00340db0d01747144c561d712c102ca401a6b 100644 (file)
@@ -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);
index fea11287990878978a617efa32c4c732a5c3b905..7dc7226c7a84968577eb77426a85d6b389dfae0e 100644 (file)
@@ -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;
 
index 08501e746a68c487888195c133b85f6541e5bf9d..29dc204af946045eadb6f557370822f67ba2a9e2 100644 (file)
@@ -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);
+               }
+       }
+}
index 5737eba319a7af1071fcfb052ae1e3f8c403ff27..bc34adfece27ae65a8fe5372199a84090f2a54cb 100644 (file)
@@ -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);
 }
-
index 0c0c402934181d461925f18e3719e5919e3deb35..88a0f5eb5769ab8b310063e335e45c100ab89d7a 100644 (file)
@@ -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;
index 19d9f6676ccd12062db5e94edfa4e20125a88272..c481c54ed5b178e6b734eea6705412f5e6a5312b 100644 (file)
@@ -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 ();
index 066f29499e9fff3e09036490b607b7f386fd042b..9d788f156636925036acc4a04c9e3a4f3e29cf40 100644 (file)
@@ -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
index 19c2448f5fbaf83e09594282bd51e4dd8a15c946..57574d82bae39b10f49ffe9bf483751863820400 100644 (file)
@@ -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&);
index 0dfef6f4e91267c7cbe3dd07337d7c5e8af67203..ece1aa305debc7da70be86c171c504091ab42c9c 100644 (file)
@@ -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);
index 4964611db333e0a8a056a7088a51777f10fe7ccb..8ad432ece6287f605a0604069ca293cd590ad353 100644 (file)
 
 #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)
 {
index 226863b88b0074b2a92eba392d808e665a29de64..00469281fc7f1b355d20d08613710e33703e5162 100644 (file)
@@ -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;
index 64ac0fe7e99f1516c347811c4bdf35eae2bb3b58..d9333576850d2e7a021fc4bc49b372bfbaaa5356 100644 (file)
 #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);
        }
          
 }
index ad8522b2023b1ed9109f71db0bdfa2b606c7732e..023c500c83b898306cbdf9ea193185cceb633418 100644 (file)
@@ -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) {
index 7a7101d831c0ad7059ef9147a1744a490d7f6c38..747b4d47ecaea458fd3edd99126748fdf1afb617 100644 (file)
@@ -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();
index 034c20f7f0116322cf39bfabada948790e8e6728..464a7075124acebd0f949a735f07e144f234f4eb 100644 (file)
@@ -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);
                }
        }
 }
index 1b75bbf49d0d88900f425a7b16abf29898c2d30e..8df28965b235ae019ee79a9b4aa8aefae91d9bea 100644 (file)
@@ -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;
-       }
-       
-       // 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 ()
 {
index c07cebaa960b3d257d71d983dc38c7a196b0511c..c67300e0d2bc9ed8e6ecfa9bc36da5613d369947 100644 (file)
@@ -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__
-
index 1f7c7dc0450847f898eaab96b60b4904a7a4186c..81f39f27c5f744f3b6a690e63c6303ecb9d6eef0 100644 (file)
@@ -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()) {
index de2039620bbd110815be84aca150ab935e724dad..c0bbea798ad1f0012b8e057fde3a9f9d7102f1f0 100644 (file)
@@ -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;
+       }
+}
index 9178546c8e12d8dc549c6b5196e83ad9d6fa8047..06ed4c800d055a92bbfe9031b3e971e8072f79ee 100644 (file)
@@ -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);
index c62c7a2e90d249b1b7d7c1b729fd76a4b18b29cf..21d0fb5b15558ff06313be704558cd319f15282f 100644 (file)
@@ -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);
index 7ef34f24514e2e9eea082e37fa594293141d5a98..64caac4eefaa4321257a59d54c1e23eaf2084d7e 100644 (file)
@@ -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
index bf184670a4e322ad48b359705052471f00194041..a5d0df530d5dafcfb1e0463ded8aecff383eed94 100644 (file)
@@ -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__
index 0936ff378b19a033f09ee6a0dc96d7cb4ef0e44f..2ae34ac4cfcb01210f7fead32c152d0155bbdbf0 100644 (file)
@@ -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;
                        }
 
index f96d649b0467f6796190c80d40b200a50235a670..d6efce7264b754fd4aa7c4a103f68cf1a7fb6d73 100644 (file)
@@ -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);
index ffda6a0b0f701220bc509b2937ba4af642f0979e..ebeda1aea72b839f15051a30296d5543909d9801 100644 (file)
@@ -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);
index e609d0e33bef8c88bc85ead59948c843dfaade89..393f919d957e11f98e6df0bf18d7aba225ad94f0 100644 (file)
@@ -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);
index 0ef4c45f16805788683454583c5e381211063f34..4dae06eeffe19c77adb469d0b1dfe7b202b1bbf1 100644 (file)
@@ -28,6 +28,7 @@ namespace ARDOUR {
 class Session;
 class DiskStream;
 class AudioPlaylist;
+class RouteGroup;
 
 class AudioTrack : public Route
 {
index 1da67c78da587406a2fded4609e573cd1509ec9b..3728d0b3460140ec6ba188beac238b8b1e34d0e6 100644 (file)
@@ -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*);
index 910500ccf8ebc92a8f456d84119efcc181ca3f4d..ad523da9c7d49a8a6d027f78682acd83a34d2375 100644 (file)
@@ -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();
index 32c627eb7a1454defa42c1e6250dd1399b1756ea..0424002dcd5211c841ae7d836c3d480adba653ed 100644 (file)
@@ -16,7 +16,7 @@ RouteGroup::apply (void (AudioTrack::*func)(T, void *), T val, void *src)
                }
        }
 }
-
 } /* namespace ARDOUR */
 
 #endif /* __ardour_route_group_specialized_h__ */
index 4a2c38eac3ebccd5335acf99af040695f0240ba6..bae73a037724f0373e2847ce14b042ac792b411a 100644 (file)
@@ -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);
 
index 7c79d2eb53ad83fc045d8a820d8f992126c62ae2..3ace2504192fc540986dc3975a86b3d4a8802775 100644 (file)
@@ -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__
index 6008f3d70b82d124521a9837d1e8900501e6849d..972384cc32199e54fe162a4bb88e8975f5c415d9 100644 (file)
@@ -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;
+}
index 225224e6842afafc8bb81a5c6b1ade31199672f9..3d40483634ecd9df73bac7d5a7b4c55fab4613b2 100644 (file)
@@ -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);
+               }
+       }
+}
+
index 2fd9e63ce2fc9efdc55d2b53af6e8525b18da3ae..21d8c72b2b6ec28fc7f83dcdbfa3c6b4e41a86a4 100644 (file)
@@ -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)
 {