export range markers patch (revisited), change selection model, copy-drag tempo+meter marker patch

git-svn-id: svn://localhost/trunk/ardour2@349 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2006-03-05 19:39:16 +00:00
parent caeb564748
commit 5a39bf595c
40 changed files with 999 additions and 448 deletions

View file

@ -61,7 +61,6 @@ about.cc
actions.cc actions.cc
add_route_dialog.cc add_route_dialog.cc
ardour_dialog.cc ardour_dialog.cc
ardour_message.cc
ardour_ui.cc ardour_ui.cc
ardour_ui2.cc ardour_ui2.cc
ardour_ui_dependents.cc ardour_ui_dependents.cc
@ -113,6 +112,9 @@ editor_selection_list.cc
editor_tempodisplay.cc editor_tempodisplay.cc
editor_timefx.cc editor_timefx.cc
export_dialog.cc export_dialog.cc
export_session_dialog.cc
export_region_dialog.cc
export_range_markers_dialog.cc
gain_automation_time_axis.cc gain_automation_time_axis.cc
gain_meter.cc gain_meter.cc
ghostregion.cc ghostregion.cc

View file

@ -42,9 +42,14 @@ using namespace sigc;
vector<RefPtr<Gtk::Action> > ActionManager::session_sensitive_actions; vector<RefPtr<Gtk::Action> > ActionManager::session_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::region_list_selection_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::region_selection_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::track_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::range_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::jack_sensitive_actions; vector<RefPtr<Gtk::Action> > ActionManager::jack_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::jack_opposite_sensitive_actions; vector<RefPtr<Gtk::Action> > ActionManager::jack_opposite_sensitive_actions;

View file

@ -22,9 +22,15 @@ class ActionManager
static std::vector<Glib::RefPtr<Gtk::Action> > session_sensitive_actions; 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> > 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> > region_selection_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > track_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> > range_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > transport_sensitive_actions; static std::vector<Glib::RefPtr<Gtk::Action> > transport_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > jack_sensitive_actions; static std::vector<Glib::RefPtr<Gtk::Action> > jack_sensitive_actions;

View file

@ -15,7 +15,8 @@
<separator/> <separator/>
<menu name='Export' action='Export'> <menu name='Export' action='Export'>
<menuitem action='ExportSession'/> <menuitem action='ExportSession'/>
<menuitem action='ExportRange'/> <menuitem action='ExportSelection'/>
<menuitem action='ExportRangeMarkers'/>
</menu> </menu>
<separator/> <separator/>
<menu name='Cleanup' action='Cleanup'> <menu name='Cleanup' action='Cleanup'>

View file

@ -28,6 +28,8 @@
#include <iostream> #include <iostream>
#include <gtkmm/messagedialog.h>
#include <pbd/error.h> #include <pbd/error.h>
#include <pbd/compose.h> #include <pbd/compose.h>
#include <pbd/basename.h> #include <pbd/basename.h>
@ -58,7 +60,6 @@
#include "actions.h" #include "actions.h"
#include "ardour_ui.h" #include "ardour_ui.h"
#include "ardour_message.h"
#include "public_editor.h" #include "public_editor.h"
#include "audio_clock.h" #include "audio_clock.h"
#include "keyboard.h" #include "keyboard.h"
@ -219,7 +220,8 @@ because it has no input connections.\n\
You would be wasting space recording silence."), You would be wasting space recording silence."),
ds->name()); ds->name());
ArdourMessage message (editor, X_("cannotrecord"), msg); MessageDialog message (*editor, msg);
message.run ();
} }
void void
@ -402,11 +404,12 @@ ARDOUR_UI::finish()
/* use the default name */ /* use the default name */
if (save_state_canfail ("")) { if (save_state_canfail ("")) {
/* failed - don't quit */ /* failed - don't quit */
ArdourMessage (editor, X_("badsave dialog"), MessageDialog msg (*editor,
_("\ _("\
Ardour was unable to save your session.\n\n\ Ardour was unable to save your session.\n\n\
If you still wish to quit, please use the\n\n\ If you still wish to quit, please use the\n\n\
\"Just quit\" option.")); \"Just quit\" option."));
msg.run ();
return; return;
} }
break; break;
@ -936,11 +939,12 @@ ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t o
} }
catch (...) { catch (...) {
ArdourMessage msg (editor, X_("noport dialog"), MessageDialog msg (*editor,
_("There are insufficient JACK ports available\n\ _("There are insufficient JACK ports available\n\
to create a new track or bus.\n\ to create a new track or bus.\n\
You should save Ardour, exit and\n\ You should save Ardour, exit and\n\
restart JACK with more ports.")); restart JACK with more ports."));
msg.run ();
} }
} }
@ -1044,7 +1048,8 @@ ARDOUR_UI::transport_record ()
case Session::Disabled: case Session::Disabled:
if (session->ntracks() == 0) { if (session->ntracks() == 0) {
string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."); 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; return;
} }
session->maybe_enable_record (); session->maybe_enable_record ();
@ -1278,12 +1283,13 @@ ARDOUR_UI::engine_halted ()
update_sample_rate (0); update_sample_rate (0);
ArdourMessage msg (editor, X_("halted"), MessageDialog msg (*editor,
_("\ _("\
JACK has either been shutdown or it\n\ JACK has either been shutdown or it\n\
disconnected Ardour because Ardour\n\ disconnected Ardour because Ardour\n\
was not fast enough. You can save the\n\ was not fast enough. You can save the\n\
session and/or try to reconnect to JACK .")); session and/or try to reconnect to JACK ."));
msg.run ();
} }
int32_t 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 it already exists, we must have write access */
if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) { 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\ You do not have write access to this session.\n\
This prevents the session from being loaded.")); This prevents the session from being loaded."));
msg.run ();
return -1; return -1;
} }
@ -1901,12 +1908,13 @@ ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* l
removed = rep.paths.size(); removed = rep.paths.size();
if (removed == 0) { if (removed == 0) {
ArdourMessage msg (editor, X_("cleanupresults"), MessageDialog msg (*editor, X_("cleanupresults"),
_("\ _("\
No audio files were ready for cleanup\n\n\ No audio files were ready for cleanup\n\n\
If this seems suprising, check for any existing\n\ If this seems suprising, check for any existing\n\
snapshots. These may still include regions that\n\ snapshots. These may still include regions that\n\
require some unused files to continue to exist.")); require some unused files to continue to exist."));
msg.run ();
return; return;
} }
@ -2150,8 +2158,9 @@ ARDOUR_UI::halt_on_xrun_message ()
{ {
ENSURE_GUI_THREAD (mem_fun(*this, &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.")); _("Recording was stopped because your system could not keep up."));
msg.run ();
} }
void void
@ -2173,12 +2182,13 @@ ARDOUR_UI::disk_overrun_handler ()
if (!have_disk_overrun_displayed) { if (!have_disk_overrun_displayed) {
have_disk_overrun_displayed = true; have_disk_overrun_displayed = true;
ArdourMessage msg (editor, X_("diskrate dialog"), _("\ MessageDialog msg (*editor, X_("diskrate dialog"), _("\
The disk system on your computer\n\ The disk system on your computer\n\
was not able to keep up with Ardour.\n\ was not able to keep up with Ardour.\n\
\n\ \n\
Specifically, it failed to write data to disk\n\ Specifically, it failed to write data to disk\n\
quickly enough to keep up with recording.\n")); quickly enough to keep up with recording.\n"));
msg.run ();
have_disk_overrun_displayed = false; have_disk_overrun_displayed = false;
} }
} }
@ -2190,12 +2200,13 @@ ARDOUR_UI::disk_underrun_handler ()
if (!have_disk_underrun_displayed) { if (!have_disk_underrun_displayed) {
have_disk_underrun_displayed = true; have_disk_underrun_displayed = true;
ArdourMessage msg (editor, X_("diskrate2 dialog"), MessageDialog msg (*editor,
(_("The disk system on your computer\n\ (_("The disk system on your computer\n\
was not able to keep up with Ardour.\n\ was not able to keep up with Ardour.\n\
\n\ \n\
Specifically, it failed to read data from disk\n\ Specifically, it failed to read data from disk\n\
quickly enough to keep up with playback.\n"))); quickly enough to keep up with playback.\n")));
msg.run ();
have_disk_underrun_displayed = false; have_disk_underrun_displayed = false;
} }
} }
@ -2248,8 +2259,8 @@ ARDOUR_UI::disconnect_from_jack ()
{ {
if (engine) { if (engine) {
if( engine->disconnect_from_jack ()) { if( engine->disconnect_from_jack ()) {
ArdourMessage msg (editor, X_("nojack dialog"), MessageDialog msg (*editor, _("Could not disconnect from JACK"));
_("Could not disconnect from JACK")); msg.run ();
} }
update_sample_rate (0); update_sample_rate (0);
@ -2261,8 +2272,8 @@ ARDOUR_UI::reconnect_to_jack ()
{ {
if (engine) { if (engine) {
if (engine->reconnect_to_jack ()) { if (engine->reconnect_to_jack ()) {
ArdourMessage msg (editor, X_("nojack dialog"), MessageDialog msg (*editor, _("Could not reconnect to JACK"));
_("Could not reconnect to JACK")); msg.run ();
} }
update_sample_rate (0); update_sample_rate (0);

View file

@ -587,6 +587,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
LocationUI *location_ui; LocationUI *location_ui;
int create_location_ui (); int create_location_ui ();
void handle_locations_change (ARDOUR::Location*);
ColorManager* color_manager; ColorManager* color_manager;

View file

@ -53,6 +53,24 @@ ARDOUR_UI::connect_to_session (Session *s)
/* sensitize menu bar options that are now valid */ /* sensitize menu bar options that are now valid */
ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true); 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); rec_button.set_sensitive (true);
shuttle_box.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);
}
}
}

View 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)); 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); 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::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")); act = ActionManager::register_action (main_actions, X_("Export"), _("Export"));
ActionManager::session_sensitive_actions.push_back (act); 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.set_name ("MainMenuBar");
menu_bar_base.add (menu_hbox); menu_bar_base.add (menu_hbox);
} }

View file

@ -832,6 +832,11 @@ AudioTimeAxisView::rename_current_playlist ()
AudioPlaylist *pl; AudioPlaylist *pl;
DiskStream *ds; 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)) { if (((ds = get_diskstream()) == 0) ||((pl = ds->playlist()) == 0)) {
return; 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 void
AudioTimeAxisView::use_copy_playlist () AudioTimeAxisView::use_copy_playlist ()
{ {
@ -869,6 +864,11 @@ AudioTimeAxisView::use_copy_playlist ()
DiskStream *ds; DiskStream *ds;
string name; 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)) { if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) {
return; return;
} }
@ -902,6 +902,11 @@ AudioTimeAxisView::use_new_playlist ()
DiskStream *ds; DiskStream *ds;
string name; 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)) { if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) {
return; return;
} }
@ -1003,14 +1008,18 @@ AudioTimeAxisView::selection_click (GdkEventButton* ev)
{ {
PublicEditor::TrackViewList* tracks = editor.get_valid_views (this, _route.edit_group()); PublicEditor::TrackViewList* tracks = editor.get_valid_views (this, _route.edit_group());
if (Keyboard::modifier_state_contains (ev->state, Keyboard::Shift)) { switch (Keyboard::selection_type (ev->state)) {
if (editor.get_selection().selected (this)) { case Selection::Toggle:
editor.get_selection().remove (*tracks); editor.get_selection().toggle (*tracks);
} else { break;
editor.get_selection().add (*tracks);
} case Selection::Set:
} else {
editor.get_selection().set (*tracks); editor.get_selection().set (*tracks);
break;
case Selection::Extend:
/* not defined yet */
break;
} }
delete tracks; delete tracks;

View file

@ -227,7 +227,6 @@ class AudioTimeAxisView : public RouteUI, public TimeAxisView
void playlist_modified (); void playlist_modified ();
void add_playlist_to_playlist_menu (ARDOUR::Playlist*); void add_playlist_to_playlist_menu (ARDOUR::Playlist*);
void playlist_selected (ARDOUR::AudioPlaylist*);
void use_new_playlist (); void use_new_playlist ();
void use_copy_playlist (); void use_copy_playlist ();
void clear_playlist (); void clear_playlist ();

View file

@ -1873,8 +1873,8 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
MenuList& select_items = select_menu->items(); MenuList& select_items = select_menu->items();
select_menu->set_name ("ArdourContextMenu"); 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 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), false))); 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 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 (MenuElem (_("Invert selection"), mem_fun(*this, &Editor::invert_selection)));
select_items.push_back (SeparatorElem()); 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(); MenuList& select_items = select_menu->items();
select_menu->set_name ("ArdourContextMenu"); 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 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), false))); 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 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 (MenuElem (_("Invert selection"), mem_fun(*this, &Editor::invert_selection)));
select_items.push_back (SeparatorElem()); select_items.push_back (SeparatorElem());
@ -2988,7 +2988,7 @@ Editor::commit_reversible_command ()
} }
void 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) { if (!clicked_trackview) {
return; return;
@ -2997,25 +2997,29 @@ Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
if (with_undo) { if (with_undo) {
begin_reversible_command (_("set selected trackview")); begin_reversible_command (_("set selected trackview"));
} }
if (add) { switch (op) {
case Selection::Toggle:
if (selection->selected (clicked_trackview)) { if (selection->selected (clicked_trackview)) {
if (!no_remove) { if (!no_remove) {
selection->remove (clicked_trackview); selection->remove (clicked_trackview);
} }
} else { } else {
selection->add (clicked_trackview); selection->toggle (clicked_trackview);
} }
break;
} else { case Selection::Set:
if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) { if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
/* no commit necessary */ /* no commit necessary */
return; return;
} }
selection->set (clicked_trackview); selection->set (clicked_trackview);
break;
case Selection::Extend:
/* not defined yet */
break;
} }
if (with_undo) { if (with_undo) {
@ -3024,7 +3028,7 @@ Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
} }
void 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) { if (!clicked_control_point) {
return; 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")); begin_reversible_command (_("set selected control point"));
} }
if (add) { switch (op) {
case Selection::Set:
} else { break;
case Selection::Toggle:
break;
case Selection::Extend:
break;
} }
if (with_undo) { if (with_undo) {
commit_reversible_command (); commit_reversible_command ();
} }
} }
void void
Editor::set_selected_regionview_from_click (bool add, bool no_track_remove) Editor::mapover_audio_tracks (slot<void,AudioTimeAxisView&> sl)
{ {
set<AudioTimeAxisView*> relevant_tracks;
/* step one: get all selected tracks and all tracks in the relevant edit groups */
for (TrackSelection::iterator ti = selection->tracks.begin(); ti != selection->tracks.end(); ++ti) {
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
if (!atv) {
continue;
}
RouteGroup* group = atv->route().edit_group();
if (group && group->is_active()) {
/* active group for this track, loop over all tracks and get every member of the group */
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
AudioTimeAxisView* tatv;
if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
if (tatv->route().edit_group() == group) {
relevant_tracks.insert (tatv);
}
}
}
} else {
/* no active group, or no group */
relevant_tracks.insert (atv);
}
}
/* step two: apply operation to each track */
for (set<AudioTimeAxisView*>::iterator ati = relevant_tracks.begin(); ati != relevant_tracks.end(); ++ati) {
sl (**ati);
}
}
void
Editor::track_set_selected_regionview_from_click (AudioTimeAxisView& atv, AudioRegionView* basis, vector<AudioRegionView*>* all_equivs)
{
AudioPlaylist* pl;
vector<AudioRegion*> results;
AudioRegionView* marv;
DiskStream* ds;
if ((ds = atv.get_diskstream()) == 0) {
/* bus */
return;
}
if ((pl = ds->playlist()) != 0) {
pl->get_equivalent_regions (basis->region, results);
}
for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
if ((marv = atv.view->find_view (**ir)) != 0) {
all_equivs->push_back (marv);
}
}
}
void
Editor::set_selected_regionview_from_click (Selection::Operation op, bool no_track_remove)
{
vector<AudioRegionView*> all_equivalent_regions;
if (!clicked_regionview) { if (!clicked_regionview) {
return; return;
} }
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view()); mapover_audio_tracks (bind (mem_fun (*this, &Editor::track_set_selected_regionview_from_click),
clicked_regionview, &all_equivalent_regions));
if (!atv) {
return;
}
RouteGroup* group = atv->route().edit_group();
vector<AudioRegionView*> all_equivalent_regions;
if (group && group->is_active()) {
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
AudioTimeAxisView* tatv;
if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
if (tatv->route().edit_group() != group) {
continue;
}
AudioPlaylist* pl;
vector<AudioRegion*> results;
AudioRegionView* marv;
DiskStream* ds;
if ((ds = tatv->get_diskstream()) == 0) {
/* bus */
continue;
}
if ((pl = ds->playlist()) != 0) {
pl->get_equivalent_regions (clicked_regionview->region,
results);
}
for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
if ((marv = tatv->view->find_view (**ir)) != 0) {
all_equivalent_regions.push_back (marv);
}
}
}
}
} else {
all_equivalent_regions.push_back (clicked_regionview);
}
begin_reversible_command (_("set selected regionview")); begin_reversible_command (_("set selected regionview"));
if (add) {
switch (op) {
case Selection::Toggle:
if (clicked_regionview->get_selected()) { 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 */ /* reduce selection down to just the one clicked */
selection->set (clicked_regionview); selection->set (clicked_regionview);
} else { } else {
selection->remove (clicked_regionview); selection->remove (clicked_regionview);
} }
} else { } else {
selection->add (all_equivalent_regions); selection->toggle (all_equivalent_regions);
} }
set_selected_track_from_click (add, false, no_track_remove); set_selected_track_from_click (op, false, no_track_remove);
break;
} else {
case Selection::Set:
// karsten wiese suggested these two lines to make // karsten wiese suggested these two lines to make
// a selected region rise to the top. but this // a selected region rise to the top. but this
// leads to a mismatch between actual layering // leads to a mismatch between actual layering
@ -3137,15 +3170,20 @@ Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
} else { } else {
selection->set (all_equivalent_regions); 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 () ; commit_reversible_command () ;
} }
void 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; vector<AudioRegionView*> all_equivalent_regions;
AudioRegion* region; AudioRegion* region;
@ -3185,13 +3223,16 @@ Editor::set_selected_regionview_from_region_list (Region& r, bool add)
begin_reversible_command (_("set selected regions")); begin_reversible_command (_("set selected regions"));
if (add) { switch (op) {
case Selection::Toggle:
selection->add (all_equivalent_regions); selection->toggle (all_equivalent_regions);
break;
} else { case Selection::Set:
selection->set (all_equivalent_regions); selection->set (all_equivalent_regions);
break;
case Selection::Extend:
/* not defined yet */
break;
} }
commit_reversible_command () ; commit_reversible_command () ;
@ -3597,6 +3638,12 @@ Editor::time_selection_changed ()
(*i)->show_selection (selection->time); (*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 void

View file

@ -215,8 +215,8 @@ class Editor : public PublicEditor
Selection& get_cut_buffer() const { return *cut_buffer; } Selection& get_cut_buffer() const { return *cut_buffer; }
void play_selection (); void play_selection ();
void select_all_in_track (bool add); void select_all_in_track (Selection::Operation op);
void select_all (bool add); void select_all (Selection::Operation op);
void invert_selection_in_track (); void invert_selection_in_track ();
void invert_selection (); void invert_selection ();
@ -442,11 +442,19 @@ class Editor : public PublicEditor
CrossfadeView* clicked_crossfadeview; CrossfadeView* clicked_crossfadeview;
ControlPoint* clicked_control_point; 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 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_control_point_from_click (Selection::Operation op = Selection::Set, 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_track_from_click (Selection::Operation op = Selection::Set, 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_click (Selection::Operation op = Selection::Set, bool no_track_remove=false);
void set_selected_regionview_from_region_list (ARDOUR::Region& region, bool add = 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*); bool set_selected_regionview_from_map_event (GdkEventAny*, StreamView*, ARDOUR::Region*);
void collect_new_region_view (AudioRegionView *); 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_from_line (ArdourCanvas::Item*, GdkEvent*);
void start_line_grab (AutomationLine *, GdkEvent*); void start_line_grab (AutomationLine *, GdkEvent*);
void start_tempo_marker_grab (ArdourCanvas::Item*, 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_grab (ArdourCanvas::Item*, GdkEvent*);
void start_meter_marker_copy_grab (ArdourCanvas::Item*, GdkEvent*);
void region_view_item_click (AudioRegionView&, GdkEventButton*); 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 drag_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event);
void end_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; ArdourCanvas::SimpleRect *rubberband_rect;
@ -1616,7 +1626,10 @@ class Editor : public PublicEditor
/* audio export */ /* audio export */
ExportDialog *export_dialog; ExportDialog *export_dialog;
ExportDialog *export_range_markers_dialog;
void export_range (jack_nframes_t start, jack_nframes_t end); void export_range (jack_nframes_t start, jack_nframes_t end);
void export_range_markers ();
int write_region_selection(AudioRegionSelection&); int write_region_selection(AudioRegionSelection&);
bool write_region (string path, ARDOUR::AudioRegion&); bool write_region (string path, ARDOUR::AudioRegion&);

View 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)); 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); 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); 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)); 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); ActionManager::session_sensitive_actions.push_back (act);

View file

@ -20,14 +20,18 @@
#include <unistd.h> #include <unistd.h>
#include <climits> #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 "editor.h"
#include "public_editor.h" #include "public_editor.h"
#include "selection.h" #include "selection.h"
#include "time_axis_view.h" #include "time_axis_view.h"
#include "audio_time_axis.h" #include "audio_time_axis.h"
#include "regionview.h" #include "regionview.h"
#include "ardour_message.h"
#include <pbd/pthread_utils.h> #include <pbd/pthread_utils.h>
#include <ardour/types.h> #include <ardour/types.h>
@ -57,12 +61,12 @@ Editor::export_selection ()
{ {
if (session) { if (session) {
if (selection->time.empty()) { 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; return;
} }
export_range (selection->time.front().start, export_range (selection->time.front().start, selection->time.front().end);
selection->time.front().end);
} }
} }
@ -71,7 +75,7 @@ Editor::export_range (jack_nframes_t start, jack_nframes_t end)
{ {
if (session) { if (session) {
if (export_dialog == 0) { if (export_dialog == 0) {
export_dialog = new ExportDialog (*this); export_dialog = new ExportSessionDialog (*this);
} }
export_dialog->connect_to_session (session); export_dialog->connect_to_session (session);
@ -87,13 +91,36 @@ Editor::export_region ()
return; return;
} }
ExportDialog* dialog = new ExportDialog (*this, &clicked_regionview->region); ExportDialog* dialog = new ExportRegionDialog (*this, &clicked_regionview->region);
dialog->connect_to_session (session); 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(); 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 int
Editor::write_region_selection (AudioRegionSelection& regions) Editor::write_region_selection (AudioRegionSelection& regions)
{ {

View file

@ -43,10 +43,10 @@ Editor::keyboard_selection_finish (bool add)
{ {
if (session && have_pending_keyboard_selection) { if (session && have_pending_keyboard_selection) {
begin_reversible_command (_("keyboard selection")); begin_reversible_command (_("keyboard selection"));
if (!add) { if (add) {
selection->set (0, pending_keyboard_selection_start, session->audible_frame());
} else {
selection->add (pending_keyboard_selection_start, session->audible_frame()); selection->add (pending_keyboard_selection_start, session->audible_frame());
} else {
selection->set (0, pending_keyboard_selection_start, session->audible_frame());
} }
commit_reversible_command (); commit_reversible_command ();
have_pending_keyboard_selection = false; have_pending_keyboard_selection = false;

View file

@ -30,10 +30,10 @@
#include "editor.h" #include "editor.h"
#include "marker.h" #include "marker.h"
#include "selection.h" #include "selection.h"
#include "simplerect.h"
#include "editing.h" #include "editing.h"
#include "gui_thread.h" #include "gui_thread.h"
#include "simplerect.h" #include "simplerect.h"
#include "actions.h"
#include "i18n.h" #include "i18n.h"
@ -564,7 +564,7 @@ Editor::marker_menu_select_all_selectables_using_range ()
bool is_start; bool is_start;
if (((l = find_location_from_marker (marker, is_start)) != 0) && (l->end() > l->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);
} }
} }

View file

@ -314,21 +314,21 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
switch (item_type) { switch (item_type) {
case RegionItem: 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; break;
case AudioRegionViewNameHighlight: case AudioRegionViewNameHighlight:
case AudioRegionViewName: case AudioRegionViewName:
if ((rv = reinterpret_cast<AudioRegionView *> (item->get_data ("regionview"))) != 0) { if ((rv = static_cast<AudioRegionView *> (item->get_data ("regionview"))) != 0) {
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; break;
case GainAutomationControlPointItem: case GainAutomationControlPointItem:
case PanAutomationControlPointItem: case PanAutomationControlPointItem:
case RedirectAutomationControlPointItem: case RedirectAutomationControlPointItem:
if ((cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"))) != 0) { if ((cp = static_cast<ControlPoint *> (item->get_data ("control_point"))) != 0) {
set_selected_control_point_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true); set_selected_control_point_from_click (Keyboard::selection_type (event->button.state), true);
} }
break; break;
@ -357,7 +357,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
case StreamItem: case StreamItem:
case RegionItem: case RegionItem:
case AutomationTrackItem: 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; break;
case AudioRegionViewNameHighlight: case AudioRegionViewNameHighlight:
@ -409,11 +409,19 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
return TRUE; return TRUE;
case TempoMarkerItem: 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; return TRUE;
case MeterMarkerItem: 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; return TRUE;
case TempoBarItem: 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); 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 void
Editor::meter_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) 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; 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; MeterMarker* marker = (MeterMarker *) drag_info.data;
BBT_Time when; BBT_Time when;
@ -2183,11 +2224,23 @@ Editor::meter_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
TempoMap& map (session->tempo_map()); TempoMap& map (session->tempo_map());
map.bbt_time (drag_info.last_pointer_frame, when); map.bbt_time (drag_info.last_pointer_frame, when);
begin_reversible_command (_("move meter mark")); if (drag_info.copy == true) {
session->add_undo (map.get_memento()); begin_reversible_command (_("copy meter mark"));
map.move_meter (marker->meter(), when); session->add_undo (map.get_memento());
session->add_redo_no_execute (map.get_memento()); map.add_meter (marker->meter(), when);
commit_reversible_command (); 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 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); 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 void
Editor::tempo_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) 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; 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; TempoMarker* marker = (TempoMarker *) drag_info.data;
BBT_Time when; BBT_Time when;
@ -2265,11 +2354,23 @@ Editor::tempo_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
TempoMap& map (session->tempo_map()); TempoMap& map (session->tempo_map());
map.bbt_time (drag_info.last_pointer_frame, when); map.bbt_time (drag_info.last_pointer_frame, when);
begin_reversible_command (_("move tempo mark")); if (drag_info.copy == true) {
session->add_undo (map.get_memento()); begin_reversible_command (_("copy tempo mark"));
map.move_tempo (marker->tempo(), when); session->add_undo (map.get_memento());
session->add_redo_no_execute (map.get_memento()); map.add_tempo (marker->tempo(), when);
commit_reversible_command (); 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 void
@ -4243,7 +4344,7 @@ Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event)
case CreateRangeMarker: case CreateRangeMarker:
begin_reversible_command (_("new range marker")); begin_reversible_command (_("new range marker"));
session->add_undo (session->locations()->get_memento()); 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->locations()->add (newloc, true);
session->add_redo_no_execute (session->locations()->get_memento()); session->add_redo_no_execute (session->locations()->get_memento());
commit_reversible_command (); 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; bool commit;
begin_reversible_command (_("select regions")); begin_reversible_command (_("select regions"));
if (drag_info.grab_frame < drag_info.last_pointer_frame) { 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 { } 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) { if (commit) {

View file

@ -1200,7 +1200,7 @@ Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
} }
void void
Editor::select_all_in_track (bool add) Editor::select_all_in_track (Selection::Operation op)
{ {
list<Selectable *> touched; 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); clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
if (add) { switch (op) {
case Selection::Toggle:
selection->add (touched); selection->add (touched);
} else { break;
case Selection::Set:
selection->set (touched); selection->set (touched);
break;
case Selection::Extend:
/* not defined yet */
break;
} }
} }
void void
Editor::select_all (bool add) Editor::select_all (Selection::Operation op)
{ {
list<Selectable *> touched; list<Selectable *> touched;
@ -1229,10 +1235,16 @@ Editor::select_all (bool add)
(*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched); (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
} }
begin_reversible_command (_("select all")); begin_reversible_command (_("select all"));
if (add) { switch (op) {
case Selection::Toggle:
selection->add (touched); selection->add (touched);
} else { break;
case Selection::Set:
selection->set (touched); selection->set (touched);
break;
case Selection::Extend:
/* not defined yet */
break;
} }
commit_reversible_command (); commit_reversible_command ();
} }
@ -1266,7 +1278,7 @@ Editor::invert_selection ()
} }
bool 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; 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); (*iter)->get_selectables (start, end, top, bot, touched);
} }
begin_reversible_command (_("select all within")); begin_reversible_command (_("select all within"));
if (add) { switch (op) {
case Selection::Toggle:
selection->add (touched); selection->add (touched);
} else { break;
case Selection::Set:
selection->set (touched); selection->set (touched);
break;
case Selection::Extend:
/* not defined yet */
break;
} }
commit_reversible_command (); commit_reversible_command ();
return !touched.empty(); return !touched.empty();

View file

@ -195,7 +195,7 @@ Editor::region_list_selection_changed()
*/ */
if ((iter = region_list_model->get_iter (*i))) { 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);
} }
} }
} }

View file

@ -26,7 +26,6 @@
#include <fstream> #include <fstream>
#include <samplerate.h> #include <samplerate.h>
#include <pbd/pthread_utils.h>
#include <pbd/xml++.h> #include <pbd/xml++.h>
#include <pbd/dirname.h> #include <pbd/dirname.h>
@ -43,7 +42,6 @@
#include "ardour_ui.h" #include "ardour_ui.h"
#include "public_editor.h" #include "public_editor.h"
#include "keyboard.h" #include "keyboard.h"
#include "ardour_message.h"
#include "i18n.h" #include "i18n.h"
@ -95,7 +93,7 @@ static const gchar* cue_file_types[] = {
0 0
}; };
ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r) ExportDialog::ExportDialog(PublicEditor& e)
: ArdourDialog ("export dialog"), : ArdourDialog ("export dialog"),
editor (e), editor (e),
format_table (9, 2), format_table (9, 2),
@ -117,9 +115,10 @@ ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
guint32 len; guint32 len;
guint32 maxlen; guint32 maxlen;
audio_region = r;
session = 0; session = 0;
track_and_master_selection_allowed = true;
channel_count_selection_allowed = true;
export_cd_markers_allowed = true;
set_title (_("ardour: export")); set_title (_("ardour: export"));
set_wmclass (_("ardour_export"), "Ardour"); set_wmclass (_("ardour_export"), "Ardour");
@ -177,23 +176,18 @@ ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
hpacker.set_border_width (5); hpacker.set_border_width (5);
hpacker.pack_start (format_frame, false, false); hpacker.pack_start (format_frame, false, false);
if (!audio_region) { master_scroll.add (master_selector);
track_scroll.add (track_selector);
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.set_size_request (220, 100);
track_scroll.set_size_request (220, 100);
/* we may hide some of these later */
/* we may hide some of these later */ track_vpacker.pack_start (master_scroll);
track_vpacker.pack_start (master_scroll); track_vpacker.pack_start (track_scroll);
track_vpacker.pack_start (track_scroll); track_vpacker.pack_start (track_selector_button, Gtk::PACK_EXPAND_PADDING);
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); get_vbox()->pack_start (hpacker);
@ -251,7 +245,7 @@ ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
/* determine longest strings at runtime */ /* determine longest strings at runtime */
maxlen = 0; maxlen = 0;
const char *longest = "gl"; const char *longest = X_("gl"); /* translators: one ascender, one descender */
string longest_str; string longest_str;
for (n = 0; n < SNDFILE_HEADER_FORMATS; ++n) { 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_col_spacings (5);
format_table.set_row_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_label, 0, 1, 0, 1); format_table.attach (channel_count_combo, 1, 2, 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_label, 0, 1, 1, 2);
format_table.attach (header_format_combo, 1, 2, 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 void
ExportDialog::connect_to_session (Session *s) 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.start_frame = start;
spec.end_frame = end; 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 gint
ExportDialog::progress_timeout () ExportDialog::progress_timeout ()
{ {
progress_bar.set_fraction (spec.progress/100); progress_bar.set_fraction (spec.progress);
return TRUE; 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 void
frames_to_cd_frames_string (char* buf, jack_nframes_t when, jack_nframes_t fr) frames_to_cd_frames_string (char* buf, jack_nframes_t when, jack_nframes_t fr)
{ {
@ -625,8 +621,11 @@ struct LocationSortByStart {
void void
ExportDialog::export_toc_file (Locations::LocationList& locations, const string& path) 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()); ofstream out (filepath.c_str());
long unsigned int last_end_time = spec.start_frame, last_start_time = spec.start_frame; long unsigned int last_end_time = spec.start_frame, last_start_time = spec.start_frame;
int numtracks = 0; int numtracks = 0;
@ -748,7 +747,11 @@ ExportDialog::export_toc_file (Locations::LocationList& locations, const string&
void void
ExportDialog::export_cue_file (Locations::LocationList& locations, const string& path) 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()); ofstream out (filepath.c_str());
gchar buf[18]; gchar buf[18];
long unsigned int last_track_end = spec.start_frame; long unsigned int last_track_end = spec.start_frame;
@ -867,7 +870,7 @@ ExportDialog::export_cue_file (Locations::LocationList& locations, const string&
} }
} }
void void
ExportDialog::do_export_cd_markers (const string& path,const string& cuefile_type) 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 void
ExportDialog::do_export () ExportDialog::do_export ()
{ {
// sanity check file name first string filepath = file_entry.get_text();
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(!is_filepath_valid(filepath)){
if (stat (filepath.c_str(), &statbuf) == 0) { return;
if (S_ISDIR (statbuf.st_mode)) {
string txt = _("Please specify a complete filename for the audio file.");
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
msg.run();
return;
}
else {
string txt = _("File already exists, do you want to overwrite it?");
MessageDialog msg (*this, txt, false, MESSAGE_QUESTION, BUTTONS_YES_NO, true);
//ArdourMessage msg (this, X_("exportoverwrite"), txt, true, false, Gtk::BUTTONS_YES_NO);
if ((ResponseType) msg.run() == Gtk::RESPONSE_NO) {
return;
}
}
}
// directory needs to exist and be writable
string dirpath = PBD::dirname (filepath);
if (::access (dirpath.c_str(), W_OK) != 0) {
string txt = _("Cannot write file in: ") + dirpath;
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
msg.run();
return;
}
if (cue_file_combo.get_active_text () != _("None")) {
do_export_cd_markers (file_entry.get_text(), cue_file_combo.get_active_text ());
} }
if (cuefile_only_checkbox.get_active()) { if (export_cd_markers_allowed) {
end_dialog (); if (cue_file_combo.get_active_text () != _("None")) {
return; 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); ok_button->set_sensitive(false);
@ -935,148 +907,15 @@ ExportDialog::do_export ()
set_modal (true); set_modal (true);
spec.path = filepath; // read user input into spec
spec.progress = 0; initSpec(filepath);
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;
}
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); progress_connection = Glib::signal_timeout().connect (mem_fun(*this, &ExportDialog::progress_timeout), 100);
cancel_label.set_text (_("Stop Export")); cancel_label.set_text (_("Stop Export"));
if (!audio_region) { export_audio_data();
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);
}
}
out: progress_connection.disconnect ();
progress_connection.disconnect ();
end_dialog (); end_dialog ();
} }
@ -1116,7 +955,7 @@ ExportDialog::start_export ()
return; 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 directory above the current session as a default
location for the export. 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 gint
ExportDialog::window_closed (GdkEventAny *ignored) ExportDialog::window_closed (GdkEventAny *ignored)
{ {
end_dialog (); end_dialog ();
return TRUE; return TRUE;
} }
void void
ExportDialog::initiate_browse () ExportDialog::initiate_browse ()
{ {

View file

@ -49,15 +49,17 @@ namespace ARDOUR {
class ExportDialog : public ArdourDialog class ExportDialog : public ArdourDialog
{ {
public: public:
ExportDialog (PublicEditor&, ARDOUR::AudioRegion* r = 0); ExportDialog (PublicEditor&);
~ExportDialog (); ~ExportDialog ();
void connect_to_session (ARDOUR::Session*); 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 (); void start_export ();
protected: protected:
struct ExportModelColumns : public Gtk::TreeModel::ColumnRecord ARDOUR::AudioExportSpecification spec;
struct ExportModelColumns : public Gtk::TreeModel::ColumnRecord
{ {
public: public:
Gtk::TreeModelColumn<std::string> output; Gtk::TreeModelColumn<std::string> output;
@ -69,11 +71,41 @@ class ExportDialog : public ArdourDialog
}; };
ExportModelColumns exp_cols; 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: private:
PublicEditor& editor; PublicEditor& editor;
ARDOUR::Session* session; 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::VBox track_vpacker;
Gtk::HBox hpacker; Gtk::HBox hpacker;
@ -123,10 +155,10 @@ class ExportDialog : public ArdourDialog
Gtk::TreeView master_selector; Gtk::TreeView master_selector;
Glib::RefPtr<Gtk::ListStore> master_list; Glib::RefPtr<Gtk::ListStore> master_list;
Gtk::FileSelection *file_selector; Gtk::FileSelection *file_selector;
ARDOUR::AudioExportSpecification spec;
static void *_thread (void *arg); static void *_thread (void *arg);
gint progress_timeout (); // sets the export progress in the progress bar
virtual gint progress_timeout ();
sigc::connection progress_connection; sigc::connection progress_connection;
void build_window (); void build_window ();
void end_dialog(); void end_dialog();
@ -137,8 +169,9 @@ class ExportDialog : public ArdourDialog
void cue_file_type_chosen(); void cue_file_type_chosen();
void fill_lists(); 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_cue_file (ARDOUR::Locations::LocationList& locations, const string& path);
void export_toc_file (ARDOUR::Locations::LocationList& locations, const string& path); void export_toc_file (ARDOUR::Locations::LocationList& locations, const string& path);
void do_export (); void do_export ();
@ -151,10 +184,6 @@ class ExportDialog : public ArdourDialog
void set_state(); void set_state();
void save_state(); void save_state();
static void* _export_region_thread (void *);
void export_region ();
}; };
#endif // __ardour_export_dialog_h__ #endif // __ardour_export_dialog_h__

View file

@ -21,6 +21,8 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include <gtkmm/messagedialog.h>
#include <pbd/lockmonitor.h> #include <pbd/lockmonitor.h>
#include <ardour/io.h> #include <ardour/io.h>
@ -36,7 +38,6 @@
#include <gtkmm2ext/utils.h> #include <gtkmm2ext/utils.h>
#include "utils.h" #include "utils.h"
#include "ardour_message.h"
#include "io_selector.h" #include "io_selector.h"
#include "keyboard.h" #include "keyboard.h"
#include "gui_thread.h" #include "gui_thread.h"
@ -557,7 +558,8 @@ IOSelector::add_port ()
} }
catch (AudioEngine::PortRegistrationFailure& err) { 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()) { if (io.input_maximum() >= 0 && io.input_maximum() <= (int) io.n_inputs()) {
@ -575,8 +577,8 @@ IOSelector::add_port ()
} }
catch (AudioEngine::PortRegistrationFailure& err) { catch (AudioEngine::PortRegistrationFailure& err) {
ArdourMessage msg (0, X_("noport dialog"), MessageDialog msg (0, _("There are no more JACK ports available."));
_("There are no more JACK ports available.")); msg.run ();
} }
if (io.output_maximum() >= 0 && io.output_maximum() <= (int) io.n_outputs()) { if (io.output_maximum() >= 0 && io.output_maximum() <= (int) io.n_outputs()) {

View file

@ -791,3 +791,14 @@ Keyboard::modifier_state_equals (guint state, ModifierMask mask)
return (state & RelevantModifierKeyMask) == (guint) 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;
}
}

View file

@ -30,6 +30,8 @@
#include <ardour/types.h> #include <ardour/types.h>
#include <ardour/stateful.h> #include <ardour/stateful.h>
#include "selection.h"
using std::vector; using std::vector;
using std::string; 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_contains (guint state, ModifierMask);
static bool modifier_state_equals (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 bool no_modifiers_active (guint state);
static void set_meta_modifier (guint); static void set_meta_modifier (guint);

View file

@ -784,7 +784,8 @@ LocationUI::add_new_range()
{ {
if (session) { if (session) {
jack_nframes_t where = session->audible_frame(); 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->begin_reversible_command (_("add range marker"));
session->add_undo (session->locations()->get_memento()); session->add_undo (session->locations()->get_memento());
session->locations()->add (location, true); session->locations()->add (location, true);

View file

@ -46,7 +46,6 @@
#include "ardour_ui.h" #include "ardour_ui.h"
#include "ardour_dialog.h" #include "ardour_dialog.h"
#include "ardour_message.h"
#include "mixer_strip.h" #include "mixer_strip.h"
#include "mixer_ui.h" #include "mixer_ui.h"
#include "keyboard.h" #include "keyboard.h"
@ -528,8 +527,9 @@ MixerStrip::output_press (GdkEventButton *ev)
using namespace Menu_Helpers; using namespace Menu_Helpers;
if (!_session.engine().connected()) { 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"));
return TRUE; msg.run ();
return true;
} }
MenuList& citems = output_menu.items(); MenuList& citems = output_menu.items();
@ -586,8 +586,9 @@ MixerStrip::input_press (GdkEventButton *ev)
citems.clear(); citems.clear();
if (!_session.engine().connected()) { 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"));
return TRUE; msg.run ();
return true;
} }
#if ADVANCED_ROUTE_DISKSTREAM_CONNECTIVITY #if ADVANCED_ROUTE_DISKSTREAM_CONNECTIVITY

View file

@ -94,6 +94,7 @@ class PublicEditor : public Gtk::Window, public Stateful {
virtual bool show_measures () const = 0; virtual bool show_measures () const = 0;
virtual void export_session() = 0; virtual void export_session() = 0;
virtual void export_selection() = 0; virtual void export_selection() = 0;
virtual void export_range_markers() = 0;
virtual void register_actions() = 0; virtual void register_actions() = 0;
virtual void add_toplevel_controls (Gtk::Container&) = 0; virtual void add_toplevel_controls (Gtk::Container&) = 0;
virtual void set_zoom_focus (Editing::ZoomFocus) = 0; virtual void set_zoom_focus (Editing::ZoomFocus) = 0;
@ -172,4 +173,4 @@ class PublicEditor : public Gtk::Window, public Stateful {
static PublicEditor* _instance; static PublicEditor* _instance;
}; };
#endif // __gtk_ardour_public_editor_h__ #endif // __gtk_ardour_public_editor_h__

View file

@ -23,6 +23,8 @@
#include <sigc++/bind.h> #include <sigc++/bind.h>
#include <gtkmm/messagedialog.h>
#include <gtkmm2ext/gtk_ui.h> #include <gtkmm2ext/gtk_ui.h>
#include <gtkmm2ext/utils.h> #include <gtkmm2ext/utils.h>
#include <gtkmm2ext/choice.h> #include <gtkmm2ext/choice.h>
@ -44,7 +46,6 @@
#include "ardour_ui.h" #include "ardour_ui.h"
#include "ardour_dialog.h" #include "ardour_dialog.h"
#include "ardour_message.h"
#include "public_editor.h" #include "public_editor.h"
#include "redirect_box.h" #include "redirect_box.h"
#include "keyboard.h" #include "keyboard.h"
@ -318,10 +319,7 @@ void
RedirectBox::selection_changed () RedirectBox::selection_changed ()
{ {
bool sensitive = (redirect_display.get_selection()->count_selected_rows()) ? true : false; bool sensitive = (redirect_display.get_selection()->count_selected_rows()) ? true : false;
ActionManager::set_sensitive (ActionManager::plugin_selection_sensitive_actions, sensitive);
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);
}
} }
void void
@ -830,7 +828,8 @@ RedirectBox::paste_redirect_list (list<Redirect*>& redirects)
"Copying the set of redirects on the clipboard failed,\n\ "Copying the set of redirects on the clipboard failed,\n\
probably because the I/O configuration of the plugins\n\ probably because the I/O configuration of the plugins\n\
could not match the configuration of this track."); 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\ "Copying the set of redirects on the clipboard failed,\n\
probably because the I/O configuration of the plugins\n\ probably because the I/O configuration of the plugins\n\
could not match the configuration of this track."); 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) { } else if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
if (!_session.engine().connected()) { 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; return;
} }

View 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 void
Selection::add (Redirect* r) Selection::add (Redirect* r)
{ {
@ -247,6 +357,8 @@ Selection::add (jack_nframes_t start, jack_nframes_t end)
{ {
AudioRangeComparator cmp; AudioRangeComparator cmp;
/* XXX this implementation is incorrect */
time.push_back (AudioRange (start, end, next_time_id++)); time.push_back (AudioRange (start, end, next_time_id++));
time.consolidate (); time.consolidate ();
time.sort (cmp); time.sort (cmp);

View file

@ -21,6 +21,8 @@
#ifndef __ardour_gtk_selection_h__ #ifndef __ardour_gtk_selection_h__
#define __ardour_gtk_selection_h__ #define __ardour_gtk_selection_h__
#include <vector>
#include <sigc++/signal.h> #include <sigc++/signal.h>
#include "time_selection.h" #include "time_selection.h"
@ -35,6 +37,14 @@ class TimeAxisView;
class AudioRegionView; class AudioRegionView;
class Selectable; class Selectable;
namespace ARDOUR {
class Region;
class AudioRegion;
class Playlist;
class Redirect;
class AutomationList;
}
class Selection : public sigc::trackable class Selection : public sigc::trackable
{ {
public: public:
@ -43,6 +53,12 @@ class Selection : public sigc::trackable
Range = 0x2 Range = 0x2
}; };
enum Operation {
Set,
Toggle,
Extend
};
TrackSelection tracks; TrackSelection tracks;
AudioRegionSelection audio_regions; AudioRegionSelection audio_regions;
TimeSelection time; TimeSelection time;
@ -88,6 +104,16 @@ class Selection : public sigc::trackable
void set (ARDOUR::Redirect*); void set (ARDOUR::Redirect*);
void set (AutomationSelectable*); 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 (TimeAxisView*);
void add (const list<TimeAxisView*>&); void add (const list<TimeAxisView*>&);
void add (AudioRegionView*); void add (AudioRegionView*);
@ -97,7 +123,7 @@ class Selection : public sigc::trackable
void add (ARDOUR::Playlist*); void add (ARDOUR::Playlist*);
void add (const list<ARDOUR::Playlist*>&); void add (const list<ARDOUR::Playlist*>&);
void add (ARDOUR::Redirect*); void add (ARDOUR::Redirect*);
void remove (TimeAxisView*); void remove (TimeAxisView*);
void remove (const list<TimeAxisView*>&); void remove (const list<TimeAxisView*>&);
void remove (AudioRegionView*); void remove (AudioRegionView*);
@ -126,7 +152,7 @@ class Selection : public sigc::trackable
private: private:
uint32_t next_time_id; uint32_t next_time_id;
void add (vector<AutomationSelectable*>&); void add (std::vector<AutomationSelectable*>&);
}; };
bool operator==(const Selection& a, const Selection& b); bool operator==(const Selection& a, const Selection& b);

View 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 */ /* 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 { } else {
@ -419,7 +419,7 @@ pane_handler (GdkEventButton* ev, Gtk::Paned* pane)
/* collapse to show the relevant child in full */ /* 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) { if (collapse_direction) {
pane->set_position (1); pane->set_position (1);

View file

@ -28,6 +28,7 @@ namespace ARDOUR {
class Session; class Session;
class DiskStream; class DiskStream;
class AudioPlaylist; class AudioPlaylist;
class RouteGroup;
class AudioTrack : public Route class AudioTrack : public Route
{ {

View file

@ -50,7 +50,8 @@ class Location : public Stateful, public sigc::trackable
IsAutoLoop = 0x4, IsAutoLoop = 0x4,
IsHidden = 0x8, IsHidden = 0x8,
IsCDMarker = 0x10, IsCDMarker = 0x10,
IsEnd = 0x20 IsEnd = 0x20,
IsRangeMarker = 0x40
}; };
Location (jack_nframes_t sample_start, 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_hidden () { return _flags & IsHidden; }
bool is_cd_marker () { return _flags & IsCDMarker; } bool is_cd_marker () { return _flags & IsCDMarker; }
bool is_end() { return _flags & IsEnd; } bool is_end() { return _flags & IsEnd; }
bool is_range_marker() { return _flags & IsRangeMarker; }
sigc::signal<void,Location*> name_changed; sigc::signal<void,Location*> name_changed;
sigc::signal<void,Location*> end_changed; sigc::signal<void,Location*> end_changed;
@ -145,6 +147,8 @@ class Locations : public Stateful, public StateManager
Location* auto_punch_location () const; Location* auto_punch_location () const;
Location* end_location() const; Location* end_location() const;
uint32_t num_range_markers() const;
int set_current (Location *, bool want_lock = true); int set_current (Location *, bool want_lock = true);
Location *current () const { return current_location; } Location *current () const { return current_location; }
@ -179,7 +183,7 @@ class Locations : public Stateful, public StateManager
LocationList locations; LocationList locations;
Location *current_location; Location *current_location;
PBD::Lock lock; mutable PBD::Lock lock;
int set_current_unlocked (Location *); int set_current_unlocked (Location *);
void location_changed (Location*); void location_changed (Location*);

View file

@ -22,6 +22,7 @@
#define __ardour_route_group_h__ #define __ardour_route_group_h__
#include <list> #include <list>
#include <set>
#include <string> #include <string>
#include <stdint.h> #include <stdint.h>
#include <sigc++/signal.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); 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 () { void clear () {
routes.clear (); routes.clear ();
changed(); changed();

View file

@ -16,7 +16,7 @@ RouteGroup::apply (void (AudioTrack::*func)(T, void *), T val, void *src)
} }
} }
} }
} /* namespace ARDOUR */ } /* namespace ARDOUR */
#endif /* __ardour_route_group_specialized_h__ */ #endif /* __ardour_route_group_specialized_h__ */

View file

@ -10,6 +10,7 @@ using std::string;
#define SNDFILE_HEADER_FORMATS 7 #define SNDFILE_HEADER_FORMATS 7
extern const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1]; 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]; 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_bitdepth_format_from_string(string);
int sndfile_header_format_from_string(string); int sndfile_header_format_from_string(string);
int sndfile_endian_format_from_string(string); int sndfile_endian_format_from_string(string);
string sndfile_file_ending_from_string(string);
int sndfile_data_width (int format); int sndfile_data_width (int format);

View file

@ -4,8 +4,13 @@
#include <pbd/compose.h> #include <pbd/compose.h>
#include "gettext.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 N_(Text) gettext_noop (Text)
#define X_(Text) (Text) #define X_(Text) Text
#endif // __i18n_h__ #endif // __i18n_h__

View file

@ -719,3 +719,16 @@ Locations::get_memento () const
{ {
return sigc::bind (mem_fun (*(const_cast<Locations*> (this)), &StateManager::use_state), _current_state_id); 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;
}

View file

@ -28,6 +28,7 @@
#include <pbd/error.h> #include <pbd/error.h>
#include <ardour/route_group.h> #include <ardour/route_group.h>
#include <ardour/audio_track.h>
#include <ardour/diskstream.h> #include <ardour/diskstream.h>
#include <ardour/configuration.h> #include <ardour/configuration.h>
@ -182,3 +183,15 @@ RouteGroup::set_hidden (bool yn, void *src)
} }
FlagsChanged (src); /* EMIT SIGNAL */ 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);
}
}
}

View file

@ -1,12 +1,13 @@
#include <map> #include <map>
#include <vector>
#include <sndfile.h> #include <sndfile.h>
#include <ardour/sndfile_helpers.h> #include <ardour/sndfile_helpers.h>
#include "i18n.h" #include "i18n.h"
using std::map; using std::map;
using namespace std;
const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1] = { const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1] = {
N_("WAV"), N_("WAV"),
@ -19,6 +20,17 @@ const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1] = {
0 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] = { int sndfile_header_formats[SNDFILE_HEADER_FORMATS] = {
SF_FORMAT_WAV, SF_FORMAT_WAV,
SF_FORMAT_AIFF, SF_FORMAT_AIFF,
@ -90,6 +102,23 @@ sndfile_endian_format_from_string (string str)
return -1; 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 int
sndfile_data_width (int format) sndfile_data_width (int format)
{ {