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
add_route_dialog.cc
ardour_dialog.cc
ardour_message.cc
ardour_ui.cc
ardour_ui2.cc
ardour_ui_dependents.cc
@ -113,6 +112,9 @@ editor_selection_list.cc
editor_tempodisplay.cc
editor_timefx.cc
export_dialog.cc
export_session_dialog.cc
export_region_dialog.cc
export_range_markers_dialog.cc
gain_automation_time_axis.cc
gain_meter.cc
ghostregion.cc

View File

@ -42,9 +42,14 @@ using namespace sigc;
vector<RefPtr<Gtk::Action> > ActionManager::session_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::region_list_selection_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::plugin_selection_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::region_selection_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::track_selection_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::plugin_selection_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::point_selection_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::time_selection_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::line_selection_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::playlist_selection_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::range_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::jack_sensitive_actions;
vector<RefPtr<Gtk::Action> > ActionManager::jack_opposite_sensitive_actions;

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> > region_list_selection_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > plugin_selection_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > region_selection_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > track_selection_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > plugin_selection_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > point_selection_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > time_selection_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > line_selection_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > playlist_selection_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > range_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > transport_sensitive_actions;
static std::vector<Glib::RefPtr<Gtk::Action> > jack_sensitive_actions;

View File

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

View File

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

View File

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

View File

@ -53,6 +53,24 @@ ARDOUR_UI::connect_to_session (Session *s)
/* sensitize menu bar options that are now valid */
ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true);
if (session->locations()->num_range_markers()) {
ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
} else {
ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
}
/* there are never any selections on startup */
ActionManager::set_sensitive (ActionManager::region_selection_sensitive_actions, false);
ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, false);
ActionManager::set_sensitive (ActionManager::line_selection_sensitive_actions, false);
ActionManager::set_sensitive (ActionManager::point_selection_sensitive_actions, false);
ActionManager::set_sensitive (ActionManager::playlist_selection_sensitive_actions, false);
session->locations()->added.connect (mem_fun (*this, &ARDOUR_UI::handle_locations_change));
session->locations()->removed.connect (mem_fun (*this, &ARDOUR_UI::handle_locations_change));
rec_button.set_sensitive (true);
shuttle_box.set_sensitive (true);
@ -366,3 +384,14 @@ ARDOUR_UI::toggle_sound_file_browser ()
}
}
void
ARDOUR_UI::handle_locations_change (Location* ignored)
{
if (session) {
if (session->locations()->num_range_markers()) {
ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
} else {
ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
}
}
}

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));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("ExportRange"), _("Export range to audiofile..."), mem_fun (*editor, &PublicEditor::export_selection));
act = ActionManager::register_action (main_actions, X_("ExportSelection"), _("Export selection to audiofile..."), mem_fun (*editor, &PublicEditor::export_selection));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::time_selection_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("ExportRangeMarkers"), _("Export range markers to audiofile..."), mem_fun (*editor, &PublicEditor::export_range_markers));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::range_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("Export"), _("Export"));
ActionManager::session_sensitive_actions.push_back (act);
@ -475,4 +480,3 @@ ARDOUR_UI::build_menu_bar ()
menu_bar_base.set_name ("MainMenuBar");
menu_bar_base.add (menu_hbox);
}

View File

@ -832,6 +832,11 @@ AudioTimeAxisView::rename_current_playlist ()
AudioPlaylist *pl;
DiskStream *ds;
/* neither conditions are supposed to be true at this
time, but to leave the design flexible, allow
them to be in the future without causing crashes
*/
if (((ds = get_diskstream()) == 0) ||((pl = ds->playlist()) == 0)) {
return;
}
@ -852,16 +857,6 @@ AudioTimeAxisView::rename_current_playlist ()
}
}
void
AudioTimeAxisView::playlist_selected (AudioPlaylist *pl)
{
DiskStream *ds;
if ((ds = get_diskstream()) != 0) {
ds->use_playlist (pl);
}
}
void
AudioTimeAxisView::use_copy_playlist ()
{
@ -869,6 +864,11 @@ AudioTimeAxisView::use_copy_playlist ()
DiskStream *ds;
string name;
/* neither conditions are supposed to be true at this
time, but to leave the design flexible, allow
them to be in the future without causing crashes
*/
if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) {
return;
}
@ -902,6 +902,11 @@ AudioTimeAxisView::use_new_playlist ()
DiskStream *ds;
string name;
/* neither conditions are supposed to be true at this
time, but to leave the design flexible, allow
them to be in the future without causing crashes
*/
if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) {
return;
}
@ -1003,14 +1008,18 @@ AudioTimeAxisView::selection_click (GdkEventButton* ev)
{
PublicEditor::TrackViewList* tracks = editor.get_valid_views (this, _route.edit_group());
if (Keyboard::modifier_state_contains (ev->state, Keyboard::Shift)) {
if (editor.get_selection().selected (this)) {
editor.get_selection().remove (*tracks);
} else {
editor.get_selection().add (*tracks);
}
} else {
switch (Keyboard::selection_type (ev->state)) {
case Selection::Toggle:
editor.get_selection().toggle (*tracks);
break;
case Selection::Set:
editor.get_selection().set (*tracks);
break;
case Selection::Extend:
/* not defined yet */
break;
}
delete tracks;

View File

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

View File

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

View File

@ -215,8 +215,8 @@ class Editor : public PublicEditor
Selection& get_cut_buffer() const { return *cut_buffer; }
void play_selection ();
void select_all_in_track (bool add);
void select_all (bool add);
void select_all_in_track (Selection::Operation op);
void select_all (Selection::Operation op);
void invert_selection_in_track ();
void invert_selection ();
@ -442,11 +442,19 @@ class Editor : public PublicEditor
CrossfadeView* clicked_crossfadeview;
ControlPoint* clicked_control_point;
void mapover_audio_tracks (sigc::slot<void,AudioTimeAxisView&> sl);
/* functions to be passed to mapover_audio_tracks(), possibly with sigc::bind()-supplied arguments */
void track_set_selected_regionview_from_click (AudioTimeAxisView&, AudioRegionView*, vector<AudioRegionView*>*);
/* end */
void catch_vanishing_audio_regionview (AudioRegionView *);
void set_selected_control_point_from_click (bool add = false, bool with_undo = true, bool no_remove=false);
void set_selected_track_from_click (bool add = false, bool with_undo = true, bool no_remove=false);
void set_selected_regionview_from_click (bool add = false, bool no_track_remove=false);
void set_selected_regionview_from_region_list (ARDOUR::Region& region, bool add = false);
void set_selected_control_point_from_click (Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false);
void set_selected_track_from_click (Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false);
void set_selected_regionview_from_click (Selection::Operation op = Selection::Set, bool no_track_remove=false);
void set_selected_regionview_from_region_list (ARDOUR::Region& region, Selection::Operation op = Selection::Set);
bool set_selected_regionview_from_map_event (GdkEventAny*, StreamView*, ARDOUR::Region*);
void collect_new_region_view (AudioRegionView *);
@ -1121,7 +1129,9 @@ class Editor : public PublicEditor
void start_line_grab_from_line (ArdourCanvas::Item*, GdkEvent*);
void start_line_grab (AutomationLine *, GdkEvent*);
void start_tempo_marker_grab (ArdourCanvas::Item*, GdkEvent*);
void start_tempo_marker_copy_grab (ArdourCanvas::Item*, GdkEvent*);
void start_meter_marker_grab (ArdourCanvas::Item*, GdkEvent*);
void start_meter_marker_copy_grab (ArdourCanvas::Item*, GdkEvent*);
void region_view_item_click (AudioRegionView&, GdkEventButton*);
@ -1440,7 +1450,7 @@ class Editor : public PublicEditor
void drag_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event);
void end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event);
bool select_all_within (jack_nframes_t start, jack_nframes_t end, gdouble topy, gdouble boty, bool add);
bool select_all_within (jack_nframes_t start, jack_nframes_t end, gdouble topy, gdouble boty, Selection::Operation op);
ArdourCanvas::SimpleRect *rubberband_rect;
@ -1616,7 +1626,10 @@ class Editor : public PublicEditor
/* audio export */
ExportDialog *export_dialog;
ExportDialog *export_range_markers_dialog;
void export_range (jack_nframes_t start, jack_nframes_t end);
void export_range_markers ();
int write_region_selection(AudioRegionSelection&);
bool write_region (string path, ARDOUR::AudioRegion&);

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));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "select-all", _("select all"), bind (mem_fun(*this, &Editor::select_all), false));
act = ActionManager::register_action (editor_actions, "select-all", _("select all"), bind (mem_fun(*this, &Editor::select_all), Selection::Set));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "select-all-after-edit-cursor", _("select all after edit cursor"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), edit_cursor, true));
ActionManager::session_sensitive_actions.push_back (act);

View File

@ -20,14 +20,18 @@
#include <unistd.h>
#include <climits>
#include "export_dialog.h"
#include <gtkmm/messagedialog.h>
#include "export_session_dialog.h"
#include "export_region_dialog.h"
#include "export_range_markers_dialog.h"
#include "editor.h"
#include "public_editor.h"
#include "selection.h"
#include "time_axis_view.h"
#include "audio_time_axis.h"
#include "regionview.h"
#include "ardour_message.h"
#include <pbd/pthread_utils.h>
#include <ardour/types.h>
@ -57,12 +61,12 @@ Editor::export_selection ()
{
if (session) {
if (selection->time.empty()) {
ArdourMessage message (this, X_("norange"), _("There is no range to export.\n\nSelect a range using the range mouse mode"));
MessageDialog message (*this, _("There is no selection to export.\n\nSelect a selection using the range mouse mode"));
message.run ();
return;
}
export_range (selection->time.front().start,
selection->time.front().end);
export_range (selection->time.front().start, selection->time.front().end);
}
}
@ -71,7 +75,7 @@ Editor::export_range (jack_nframes_t start, jack_nframes_t end)
{
if (session) {
if (export_dialog == 0) {
export_dialog = new ExportDialog (*this);
export_dialog = new ExportSessionDialog (*this);
}
export_dialog->connect_to_session (session);
@ -87,13 +91,36 @@ Editor::export_region ()
return;
}
ExportDialog* dialog = new ExportDialog (*this, &clicked_regionview->region);
ExportDialog* dialog = new ExportRegionDialog (*this, &clicked_regionview->region);
dialog->connect_to_session (session);
dialog->set_range (0, clicked_regionview->region.length());
dialog->set_range (
clicked_regionview->region.first_frame(),
clicked_regionview->region.last_frame());
dialog->start_export();
}
void
Editor::export_range_markers ()
{
if (session) {
if (session->locations()->num_range_markers() == 0) {
MessageDialog message (*this, _("There are no ranges to export.\n\nCreate 1 or more ranges by dragging the mouse in the range bar"));
message.run ();
return;
}
if (export_range_markers_dialog == 0) {
export_range_markers_dialog = new ExportRangeMarkersDialog(*this);
}
export_range_markers_dialog->connect_to_session (session);
export_range_markers_dialog->start_export();
}
}
int
Editor::write_region_selection (AudioRegionSelection& regions)
{

View File

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

View File

@ -30,10 +30,10 @@
#include "editor.h"
#include "marker.h"
#include "selection.h"
#include "simplerect.h"
#include "editing.h"
#include "gui_thread.h"
#include "simplerect.h"
#include "actions.h"
#include "i18n.h"
@ -564,7 +564,7 @@ Editor::marker_menu_select_all_selectables_using_range ()
bool is_start;
if (((l = find_location_from_marker (marker, is_start)) != 0) && (l->end() > l->start())) {
select_all_within (l->start(), l->end(), 0, DBL_MAX, false);
select_all_within (l->start(), l->end(), 0, DBL_MAX, Selection::Set);
}
}

View File

@ -314,21 +314,21 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
switch (item_type) {
case RegionItem:
set_selected_regionview_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true);
set_selected_regionview_from_click (Keyboard::selection_type (event->button.state), true);
break;
case AudioRegionViewNameHighlight:
case AudioRegionViewName:
if ((rv = reinterpret_cast<AudioRegionView *> (item->get_data ("regionview"))) != 0) {
set_selected_regionview_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true);
if ((rv = static_cast<AudioRegionView *> (item->get_data ("regionview"))) != 0) {
set_selected_regionview_from_click (Keyboard::selection_type (event->button.state), true);
}
break;
case GainAutomationControlPointItem:
case PanAutomationControlPointItem:
case RedirectAutomationControlPointItem:
if ((cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"))) != 0) {
set_selected_control_point_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true);
if ((cp = static_cast<ControlPoint *> (item->get_data ("control_point"))) != 0) {
set_selected_control_point_from_click (Keyboard::selection_type (event->button.state), true);
}
break;
@ -357,7 +357,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
case StreamItem:
case RegionItem:
case AutomationTrackItem:
set_selected_track_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true, true);
set_selected_track_from_click (Keyboard::selection_type (event->button.state), true, true);
break;
case AudioRegionViewNameHighlight:
@ -409,11 +409,19 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
return TRUE;
case TempoMarkerItem:
start_tempo_marker_grab (item, event);
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
start_tempo_marker_copy_grab (item, event);
} else {
start_tempo_marker_grab (item, event);
}
return TRUE;
case MeterMarkerItem:
start_meter_marker_grab (item, event);
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
start_meter_marker_copy_grab (item, event);
} else {
start_meter_marker_grab (item, event);
}
return TRUE;
case TempoBarItem:
@ -2142,6 +2150,39 @@ Editor::start_meter_marker_grab (ArdourCanvas::Item* item, GdkEvent* event)
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
}
void
Editor::start_meter_marker_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
{
Marker* marker;
MeterMarker* meter_marker;
if ((marker = reinterpret_cast<Marker *> (item->get_data ("marker"))) == 0) {
fatal << _("programming error: meter marker canvas item has no marker object pointer!") << endmsg;
/*NOTREACHED*/
}
meter_marker = dynamic_cast<MeterMarker*> (marker);
// create a dummy marker for visual representation of moving the copy.
// The actual copying is not done before we reach the finish callback.
char name[64];
snprintf (name, sizeof(name), "%g/%g", meter_marker->meter().beats_per_bar(), meter_marker->meter().note_divisor ());
MeterMarker* new_marker = new MeterMarker(*this, *meter_group, color_map[cMeterMarker], name,
*new MeterSection(meter_marker->meter()));
drag_info.item = &new_marker->the_item();
drag_info.copy = true;
drag_info.data = new_marker;
drag_info.motion_callback = &Editor::meter_marker_drag_motion_callback;
drag_info.finished_callback = &Editor::meter_marker_drag_finished_callback;
start_grab (event);
drag_info.pointer_frame_offset = drag_info.grab_frame - meter_marker->meter().frame();
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
}
void
Editor::meter_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
{
@ -2175,7 +2216,7 @@ Editor::meter_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
{
if (drag_info.first_move) return;
meter_marker_drag_motion_callback (item, event);
meter_marker_drag_motion_callback (drag_info.item, event);
MeterMarker* marker = (MeterMarker *) drag_info.data;
BBT_Time when;
@ -2183,11 +2224,23 @@ Editor::meter_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
TempoMap& map (session->tempo_map());
map.bbt_time (drag_info.last_pointer_frame, when);
begin_reversible_command (_("move meter mark"));
session->add_undo (map.get_memento());
map.move_meter (marker->meter(), when);
session->add_redo_no_execute (map.get_memento());
commit_reversible_command ();
if (drag_info.copy == true) {
begin_reversible_command (_("copy meter mark"));
session->add_undo (map.get_memento());
map.add_meter (marker->meter(), when);
session->add_redo_no_execute (map.get_memento());
commit_reversible_command ();
// delete the dummy marker we used for visual representation of copying.
// a new visual marker will show up automatically.
delete marker;
} else {
begin_reversible_command (_("move meter mark"));
session->add_undo (map.get_memento());
map.move_meter (marker->meter(), when);
session->add_redo_no_execute (map.get_memento());
commit_reversible_command ();
}
}
void
@ -2223,6 +2276,42 @@ Editor::start_tempo_marker_grab (ArdourCanvas::Item* item, GdkEvent* event)
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
}
void
Editor::start_tempo_marker_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
{
Marker* marker;
TempoMarker* tempo_marker;
if ((marker = reinterpret_cast<Marker *> (item->get_data ("marker"))) == 0) {
fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
/*NOTREACHED*/
}
if ((tempo_marker = dynamic_cast<TempoMarker *> (marker)) == 0) {
fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg;
/*NOTREACHED*/
}
// create a dummy marker for visual representation of moving the copy.
// The actual copying is not done before we reach the finish callback.
char name[64];
snprintf (name, sizeof (name), "%.2f", tempo_marker->tempo().beats_per_minute());
TempoMarker* new_marker = new TempoMarker(*this, *tempo_group, color_map[cTempoMarker], name,
*new TempoSection(tempo_marker->tempo()));
drag_info.item = &new_marker->the_item();
drag_info.copy = true;
drag_info.data = new_marker;
drag_info.motion_callback = &Editor::tempo_marker_drag_motion_callback;
drag_info.finished_callback = &Editor::tempo_marker_drag_finished_callback;
start_grab (event);
drag_info.pointer_frame_offset = drag_info.grab_frame - tempo_marker->tempo().frame();
show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
}
void
Editor::tempo_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
{
@ -2257,7 +2346,7 @@ Editor::tempo_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
{
if (drag_info.first_move) return;
tempo_marker_drag_motion_callback (item, event);
tempo_marker_drag_motion_callback (drag_info.item, event);
TempoMarker* marker = (TempoMarker *) drag_info.data;
BBT_Time when;
@ -2265,11 +2354,23 @@ Editor::tempo_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
TempoMap& map (session->tempo_map());
map.bbt_time (drag_info.last_pointer_frame, when);
begin_reversible_command (_("move tempo mark"));
session->add_undo (map.get_memento());
map.move_tempo (marker->tempo(), when);
session->add_redo_no_execute (map.get_memento());
commit_reversible_command ();
if (drag_info.copy == true) {
begin_reversible_command (_("copy tempo mark"));
session->add_undo (map.get_memento());
map.add_tempo (marker->tempo(), when);
session->add_redo_no_execute (map.get_memento());
commit_reversible_command ();
// delete the dummy marker we used for visual representation of copying.
// a new visual marker will show up automatically.
delete marker;
} else {
begin_reversible_command (_("move tempo mark"));
session->add_undo (map.get_memento());
map.move_tempo (marker->tempo(), when);
session->add_redo_no_execute (map.get_memento());
commit_reversible_command ();
}
}
void
@ -4243,7 +4344,7 @@ Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event)
case CreateRangeMarker:
begin_reversible_command (_("new range marker"));
session->add_undo (session->locations()->get_memento());
newloc = new Location(temp_location->start(), temp_location->end(), "unnamed");
newloc = new Location(temp_location->start(), temp_location->end(), "unnamed", Location::IsRangeMarker);
session->locations()->add (newloc, true);
session->add_redo_no_execute (session->locations()->get_memento());
commit_reversible_command ();
@ -4453,15 +4554,15 @@ Editor::end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event)
}
bool add = Keyboard::modifier_state_contains (event->button.state, Keyboard::Shift);
Selection::Operation op = Keyboard::selection_type (event->button.state);
bool commit;
begin_reversible_command (_("select regions"));
if (drag_info.grab_frame < drag_info.last_pointer_frame) {
commit = select_all_within (drag_info.grab_frame, drag_info.last_pointer_frame, y1, y2, add);
commit = select_all_within (drag_info.grab_frame, drag_info.last_pointer_frame, y1, y2, op);
} else {
commit = select_all_within (drag_info.last_pointer_frame, drag_info.grab_frame, y1, y2, add);
commit = select_all_within (drag_info.last_pointer_frame, drag_info.grab_frame, y1, y2, op);
}
if (commit) {

View File

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

View File

@ -195,7 +195,7 @@ Editor::region_list_selection_changed()
*/
if ((iter = region_list_model->get_iter (*i))) {
set_selected_regionview_from_region_list (*((*iter)[region_list_columns.region]), false);
set_selected_regionview_from_region_list (*((*iter)[region_list_columns.region]), Selection::Set);
}
}
}

View File

@ -26,7 +26,6 @@
#include <fstream>
#include <samplerate.h>
#include <pbd/pthread_utils.h>
#include <pbd/xml++.h>
#include <pbd/dirname.h>
@ -43,7 +42,6 @@
#include "ardour_ui.h"
#include "public_editor.h"
#include "keyboard.h"
#include "ardour_message.h"
#include "i18n.h"
@ -95,7 +93,7 @@ static const gchar* cue_file_types[] = {
0
};
ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
ExportDialog::ExportDialog(PublicEditor& e)
: ArdourDialog ("export dialog"),
editor (e),
format_table (9, 2),
@ -117,9 +115,10 @@ ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
guint32 len;
guint32 maxlen;
audio_region = r;
session = 0;
track_and_master_selection_allowed = true;
channel_count_selection_allowed = true;
export_cd_markers_allowed = true;
set_title (_("ardour: export"));
set_wmclass (_("ardour_export"), "Ardour");
@ -177,23 +176,18 @@ ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
hpacker.set_border_width (5);
hpacker.pack_start (format_frame, false, false);
if (!audio_region) {
master_scroll.add (master_selector);
track_scroll.add (track_selector);
master_scroll.set_size_request (220, 100);
track_scroll.set_size_request (220, 100);
master_scroll.add (master_selector);
track_scroll.add (track_selector);
master_scroll.set_size_request (220, 100);
track_scroll.set_size_request (220, 100);
/* we may hide some of these later */
track_vpacker.pack_start (master_scroll);
track_vpacker.pack_start (track_scroll);
track_vpacker.pack_start (track_selector_button, Gtk::PACK_EXPAND_PADDING);
/* we may hide some of these later */
track_vpacker.pack_start (master_scroll);
track_vpacker.pack_start (track_scroll);
track_vpacker.pack_start (track_selector_button, Gtk::PACK_EXPAND_PADDING);
hpacker.pack_start (track_vpacker);
}
hpacker.pack_start (track_vpacker);
get_vbox()->pack_start (hpacker);
@ -251,7 +245,7 @@ ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
/* determine longest strings at runtime */
maxlen = 0;
const char *longest = "gl";
const char *longest = X_("gl"); /* translators: one ascender, one descender */
string longest_str;
for (n = 0; n < SNDFILE_HEADER_FORMATS; ++n) {
@ -321,11 +315,9 @@ ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
format_table.set_col_spacings (5);
format_table.set_row_spacings (5);
if (!audio_region) {
format_table.attach (channel_count_label, 0, 1, 0, 1);
format_table.attach (channel_count_combo, 1, 2, 0, 1);
}
format_table.attach (channel_count_label, 0, 1, 0, 1);
format_table.attach (channel_count_combo, 1, 2, 0, 1);
format_table.attach (header_format_label, 0, 1, 1, 2);
format_table.attach (header_format_combo, 1, 2, 1, 2);
@ -374,6 +366,30 @@ ExportDialog::~ExportDialog()
}
}
void
ExportDialog::do_not_allow_track_and_master_selection()
{
track_and_master_selection_allowed = false;
track_vpacker.set_no_show_all();
}
void
ExportDialog::do_not_allow_channel_count_selection()
{
channel_count_selection_allowed = false;
channel_count_combo.set_no_show_all();
channel_count_label.set_no_show_all();
}
void
ExportDialog::do_not_allow_export_cd_markers()
{
export_cd_markers_allowed = false;
cue_file_label.set_no_show_all();
cue_file_combo.set_no_show_all();
cuefile_only_checkbox.set_no_show_all();
}
void
ExportDialog::connect_to_session (Session *s)
{
@ -571,35 +587,15 @@ ExportDialog::set_range (jack_nframes_t start, jack_nframes_t end)
{
spec.start_frame = start;
spec.end_frame = end;
if (!audio_region) {
// XXX: this is a hack until we figure out what is really wrong
session->request_locate (spec.start_frame, false);
}
}
gint
ExportDialog::progress_timeout ()
{
progress_bar.set_fraction (spec.progress/100);
progress_bar.set_fraction (spec.progress);
return TRUE;
}
void*
ExportDialog::_export_region_thread (void *arg)
{
PBD::ThreadCreated (pthread_self(), X_("Export Region"));
static_cast<ExportDialog*>(arg)->export_region ();
return 0;
}
void
ExportDialog::export_region ()
{
audio_region->exportme (*session, spec);
}
void
frames_to_cd_frames_string (char* buf, jack_nframes_t when, jack_nframes_t fr)
{
@ -625,8 +621,11 @@ struct LocationSortByStart {
void
ExportDialog::export_toc_file (Locations::LocationList& locations, const string& path)
{
if(!export_cd_markers_allowed){
return;
}
string filepath = path + ".toc";
string filepath = path + ".toc";
ofstream out (filepath.c_str());
long unsigned int last_end_time = spec.start_frame, last_start_time = spec.start_frame;
int numtracks = 0;
@ -748,7 +747,11 @@ ExportDialog::export_toc_file (Locations::LocationList& locations, const string&
void
ExportDialog::export_cue_file (Locations::LocationList& locations, const string& path)
{
string filepath = path + ".cue";
if(!export_cd_markers_allowed){
return;
}
string filepath = path + ".cue";
ofstream out (filepath.c_str());
gchar buf[18];
long unsigned int last_track_end = spec.start_frame;
@ -867,7 +870,7 @@ ExportDialog::export_cue_file (Locations::LocationList& locations, const string&
}
}
void
ExportDialog::do_export_cd_markers (const string& path,const string& cuefile_type)
{
@ -882,52 +885,21 @@ ExportDialog::do_export_cd_markers (const string& path,const string& cuefile_typ
void
ExportDialog::do_export ()
{
// sanity check file name first
string filepath = file_entry.get_text();
struct stat statbuf;
if (filepath.empty()) {
// warning dialog
string txt = _("Please enter a valid filename.");
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
msg.run();
return;
}
string filepath = file_entry.get_text();
// check if file exists already and warn
if (stat (filepath.c_str(), &statbuf) == 0) {
if (S_ISDIR (statbuf.st_mode)) {
string txt = _("Please specify a complete filename for the audio file.");
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
msg.run();
return;
}
else {
string txt = _("File already exists, do you want to overwrite it?");
MessageDialog msg (*this, txt, false, MESSAGE_QUESTION, BUTTONS_YES_NO, true);
//ArdourMessage msg (this, X_("exportoverwrite"), txt, true, false, Gtk::BUTTONS_YES_NO);
if ((ResponseType) msg.run() == Gtk::RESPONSE_NO) {
return;
}
}
}
// directory needs to exist and be writable
string dirpath = PBD::dirname (filepath);
if (::access (dirpath.c_str(), W_OK) != 0) {
string txt = _("Cannot write file in: ") + dirpath;
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
msg.run();
return;
}
if (cue_file_combo.get_active_text () != _("None")) {
do_export_cd_markers (file_entry.get_text(), cue_file_combo.get_active_text ());
if(!is_filepath_valid(filepath)){
return;
}
if (cuefile_only_checkbox.get_active()) {
end_dialog ();
return;
if (export_cd_markers_allowed) {
if (cue_file_combo.get_active_text () != _("None")) {
do_export_cd_markers (file_entry.get_text(), cue_file_combo.get_active_text ());
}
if (cuefile_only_checkbox.get_active()) {
end_dialog ();
return;
}
}
ok_button->set_sensitive(false);
@ -935,148 +907,15 @@ ExportDialog::do_export ()
set_modal (true);
spec.path = filepath;
spec.progress = 0;
spec.running = true;
spec.stop = false;
spec.port_map.clear();
// read user input into spec
initSpec(filepath);
if (channel_count_combo.get_active_text() == _("mono")) {
spec.channels = 1;
} else {
spec.channels = 2;
}
spec.format = 0;
spec.format |= sndfile_header_format_from_string (header_format_combo.get_active_text ());
if ((spec.format & SF_FORMAT_WAV) == 0) {
/* RIFF/WAV specifies endianess */
spec.format |= sndfile_endian_format_from_string (endian_format_combo.get_active_text ());
}
spec.format |= sndfile_bitdepth_format_from_string (bitdepth_format_combo.get_active_text ());
string sr_str = sample_rate_combo.get_active_text();
if (sr_str == N_("22.05kHz")) {
spec.sample_rate = 22050;
} else if (sr_str == N_("44.1kHz")) {
spec.sample_rate = 44100;
} else if (sr_str == N_("48kHz")) {
spec.sample_rate = 48000;
} else if (sr_str == N_("88.2kHz")) {
spec.sample_rate = 88200;
} else if (sr_str == N_("96kHz")) {
spec.sample_rate = 96000;
} else if (sr_str == N_("192kHz")) {
spec.sample_rate = 192000;
} else {
spec.sample_rate = session->frame_rate();
}
string src_str = src_quality_combo.get_active_text();
if (src_str == _("fastest")) {
spec.src_quality = SRC_ZERO_ORDER_HOLD;
} else if (src_str == _("linear")) {
spec.src_quality = SRC_LINEAR;
} else if (src_str == _("better")) {
spec.src_quality = SRC_SINC_FASTEST;
} else if (src_str == _("intermediate")) {
spec.src_quality = SRC_SINC_MEDIUM_QUALITY;
} else {
spec.src_quality = SRC_SINC_BEST_QUALITY;
}
string dither_str = dither_type_combo.get_active_text();
if (dither_str == _("None")) {
spec.dither_type = GDitherNone;
} else if (dither_str == _("Rectangular")) {
spec.dither_type = GDitherRect;
} else if (dither_str == _("Triangular")) {
spec.dither_type = GDitherTri;
} else {
spec.dither_type = GDitherShaped;
}
if (!audio_region) {
uint32_t chan=0;
Port *last_port = 0;
TreeModel::Children rows = master_selector.get_model()->children();
TreeModel::Children::iterator ri;
TreeModel::Row row;
for (ri = rows.begin(); ri != rows.end(); ++ri) {
row = *ri;
Port* port = row[exp_cols.port];
if (last_port != port) {
chan = 0;
}
if (row[exp_cols.left]) {
spec.port_map[0].push_back (std::pair<Port*,uint32_t>(port, chan));
}
if (spec.channels == 2) {
if (row[exp_cols.right]) {
spec.port_map[1].push_back (std::pair<Port*,uint32_t>(port, chan));
}
}
}
chan = 0;
rows = track_selector.get_model()->children();
for (ri = rows.begin(); ri != rows.end(); ++ri) {
row = *ri;
Port* port = row[exp_cols.port];
if (last_port != port) {
chan = 0;
}
if (row[exp_cols.left]) {
spec.port_map[0].push_back (std::pair<Port*,uint32_t>(port, chan));
}
if (spec.channels == 2) {
if (row[exp_cols.right]) {
spec.port_map[1].push_back (std::pair<Port*,uint32_t>(port, chan));
}
}
last_port = port;
++chan;
}
}
progress_connection = Glib::signal_timeout().connect (mem_fun(*this, &ExportDialog::progress_timeout), 100);
cancel_label.set_text (_("Stop Export"));
if (!audio_region) {
if (session->start_audio_export (spec)) {
goto out;
}
} else {
pthread_t thr;
pthread_create_and_store ("region export", &thr, 0, ExportDialog::_export_region_thread, this);
}
gtk_main_iteration ();
while (spec.running) {
if (gtk_events_pending()) {
gtk_main_iteration ();
} else {
usleep (10000);
}
}
export_audio_data();
out:
progress_connection.disconnect ();
progress_connection.disconnect ();
end_dialog ();
}
@ -1116,7 +955,7 @@ ExportDialog::start_export ()
return;
}
/* If it the filename hasn't been set before, use the
/* If the filename hasn't been set before, use the
directory above the current session as a default
location for the export.
*/
@ -1286,12 +1125,191 @@ ExportDialog::fill_lists ()
}
}
bool
ExportDialog::is_filepath_valid(string &filepath)
{
// sanity check file name first
struct stat statbuf;
if (filepath.empty()) {
string txt = _("Please enter a valid filename.");
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
msg.run();
return false;
}
// check if file exists already and warn
if (stat (filepath.c_str(), &statbuf) == 0) {
if (S_ISDIR (statbuf.st_mode)) {
string txt = _("Please specify a complete filename for the audio file.");
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
msg.run();
return false;
}
else {
string txt = _("File already exists, do you want to overwrite it?");
MessageDialog msg (*this, txt, false, MESSAGE_QUESTION, BUTTONS_YES_NO, true);
if ((ResponseType) msg.run() == Gtk::RESPONSE_NO) {
return false;
}
}
}
// directory needs to exist and be writable
string dirpath = PBD::dirname (filepath);
if (::access (dirpath.c_str(), W_OK) != 0) {
string txt = _("Cannot write file in: ") + dirpath;
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
msg.run();
return false;
}
return true;
}
void
ExportDialog::initSpec(string &filepath)
{
spec.path = filepath;
spec.progress = 0;
spec.running = true;
spec.stop = false;
spec.port_map.clear();
if (channel_count_combo.get_active_text() == _("mono")) {
spec.channels = 1;
} else {
spec.channels = 2;
}
spec.format = 0;
spec.format |= sndfile_header_format_from_string (header_format_combo.get_active_text ());
if ((spec.format & SF_FORMAT_WAV) == 0) {
/* RIFF/WAV specifies endianess */
spec.format |= sndfile_endian_format_from_string (endian_format_combo.get_active_text ());
}
spec.format |= sndfile_bitdepth_format_from_string (bitdepth_format_combo.get_active_text ());
string sr_str = sample_rate_combo.get_active_text();
if (sr_str == N_("22.05kHz")) {
spec.sample_rate = 22050;
} else if (sr_str == N_("44.1kHz")) {
spec.sample_rate = 44100;
} else if (sr_str == N_("48kHz")) {
spec.sample_rate = 48000;
} else if (sr_str == N_("88.2kHz")) {
spec.sample_rate = 88200;
} else if (sr_str == N_("96kHz")) {
spec.sample_rate = 96000;
} else if (sr_str == N_("192kHz")) {
spec.sample_rate = 192000;
} else {
spec.sample_rate = session->frame_rate();
}
string src_str = src_quality_combo.get_active_text();
if (src_str == _("fastest")) {
spec.src_quality = SRC_ZERO_ORDER_HOLD;
} else if (src_str == _("linear")) {
spec.src_quality = SRC_LINEAR;
} else if (src_str == _("better")) {
spec.src_quality = SRC_SINC_FASTEST;
} else if (src_str == _("intermediate")) {
spec.src_quality = SRC_SINC_MEDIUM_QUALITY;
} else {
spec.src_quality = SRC_SINC_BEST_QUALITY;
}
string dither_str = dither_type_combo.get_active_text();
if (dither_str == _("None")) {
spec.dither_type = GDitherNone;
} else if (dither_str == _("Rectangular")) {
spec.dither_type = GDitherRect;
} else if (dither_str == _("Triangular")) {
spec.dither_type = GDitherTri;
} else {
spec.dither_type = GDitherShaped;
}
write_track_and_master_selection_to_spec();
}
void
ExportDialog::write_track_and_master_selection_to_spec()
{
if(!track_and_master_selection_allowed){
return;
}
uint32_t chan=0;
Port *last_port = 0;
TreeModel::Children rows = master_selector.get_model()->children();
TreeModel::Children::iterator ri;
TreeModel::Row row;
for (ri = rows.begin(); ri != rows.end(); ++ri) {
row = *ri;
Port* port = row[exp_cols.port];
if (last_port != port) {
chan = 0;
}
if (row[exp_cols.left]) {
spec.port_map[0].push_back (std::pair<Port*,uint32_t>(port, chan));
}
if (spec.channels == 2) {
if (row[exp_cols.right]) {
spec.port_map[1].push_back (std::pair<Port*,uint32_t>(port, chan));
}
}
}
chan = 0;
rows = track_selector.get_model()->children();
for (ri = rows.begin(); ri != rows.end(); ++ri) {
row = *ri;
Port* port = row[exp_cols.port];
if (last_port != port) {
chan = 0;
}
if (row[exp_cols.left]) {
spec.port_map[0].push_back (std::pair<Port*,uint32_t>(port, chan));
}
if (spec.channels == 2) {
if (row[exp_cols.right]) {
spec.port_map[1].push_back (std::pair<Port*,uint32_t>(port, chan));
}
}
last_port = port;
++chan;
}
}
gint
ExportDialog::window_closed (GdkEventAny *ignored)
{
end_dialog ();
return TRUE;
}
void
ExportDialog::initiate_browse ()
{

View File

@ -49,15 +49,17 @@ namespace ARDOUR {
class ExportDialog : public ArdourDialog
{
public:
ExportDialog (PublicEditor&, ARDOUR::AudioRegion* r = 0);
ExportDialog (PublicEditor&);
~ExportDialog ();
void connect_to_session (ARDOUR::Session*);
void set_range (jack_nframes_t start, jack_nframes_t end);
virtual void set_range (jack_nframes_t start, jack_nframes_t end);
void start_export ();
protected:
struct ExportModelColumns : public Gtk::TreeModel::ColumnRecord
ARDOUR::AudioExportSpecification spec;
struct ExportModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
Gtk::TreeModelColumn<std::string> output;
@ -69,11 +71,41 @@ class ExportDialog : public ArdourDialog
};
ExportModelColumns exp_cols;
// These methods are intended to be used in constructors of subclasses
void do_not_allow_track_and_master_selection();
void do_not_allow_channel_count_selection();
void do_not_allow_export_cd_markers();
// Checks the given filename for validity when export gets started.
// Export will interrupt when this method returns 'false'.
// Method is responsible for informing user.
virtual bool is_filepath_valid(string &filepath);
// Gets called from within do_export. Is responsible for exporting the
// audio data. spec has already been filled with user input before calling
// this method. The dialog will be closed after this function exited.
virtual void export_audio_data() = 0;
// reads the user input and fills spec with the according values
// filepath: complete path to the target file, including filename
void initSpec(string &filepath);
void set_progress_fraction(double progress) {
progress_bar.set_fraction (progress); }
ARDOUR::Session& getSession() { return *session; };
string get_selected_header_format() {
return header_format_combo.get_active_text(); };
string get_selected_file_name() { return file_entry.get_text(); };
private:
PublicEditor& editor;
ARDOUR::Session* session;
ARDOUR::AudioRegion* audio_region;
bool track_and_master_selection_allowed;
bool channel_count_selection_allowed;
bool export_cd_markers_allowed;
Gtk::VBox track_vpacker;
Gtk::HBox hpacker;
@ -123,10 +155,10 @@ class ExportDialog : public ArdourDialog
Gtk::TreeView master_selector;
Glib::RefPtr<Gtk::ListStore> master_list;
Gtk::FileSelection *file_selector;
ARDOUR::AudioExportSpecification spec;
static void *_thread (void *arg);
gint progress_timeout ();
// sets the export progress in the progress bar
virtual gint progress_timeout ();
sigc::connection progress_connection;
void build_window ();
void end_dialog();
@ -137,8 +169,9 @@ class ExportDialog : public ArdourDialog
void cue_file_type_chosen();
void fill_lists();
void write_track_and_master_selection_to_spec();
void do_export_cd_markers (const string& path, const string& cuefile_type);
void do_export_cd_markers (const string& path, const string& cuefile_type);
void export_cue_file (ARDOUR::Locations::LocationList& locations, const string& path);
void export_toc_file (ARDOUR::Locations::LocationList& locations, const string& path);
void do_export ();
@ -151,10 +184,6 @@ class ExportDialog : public ArdourDialog
void set_state();
void save_state();
static void* _export_region_thread (void *);
void export_region ();
};
#endif // __ardour_export_dialog_h__

View File

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

View File

@ -791,3 +791,14 @@ Keyboard::modifier_state_equals (guint state, ModifierMask mask)
return (state & RelevantModifierKeyMask) == (guint) mask;
}
Selection::Operation
Keyboard::selection_type (guint state)
{
if (modifier_state_equals (state, Shift)) {
return Selection::Extend;
} else if (modifier_state_equals (state, Control)) {
return Selection::Toggle;
} else {
return Selection::Set;
}
}

View File

@ -30,6 +30,8 @@
#include <ardour/types.h>
#include <ardour/stateful.h>
#include "selection.h"
using std::vector;
using std::string;
@ -71,6 +73,8 @@ class Keyboard : public sigc::trackable, Stateful
static bool modifier_state_contains (guint state, ModifierMask);
static bool modifier_state_equals (guint state, ModifierMask);
static Selection::Operation selection_type (guint state);
static bool no_modifiers_active (guint state);
static void set_meta_modifier (guint);

View File

@ -784,7 +784,8 @@ LocationUI::add_new_range()
{
if (session) {
jack_nframes_t where = session->audible_frame();
Location *location = new Location (where, where, "unnamed");
Location *location = new Location (where, where, "unnamed",
Location::IsRangeMarker);
session->begin_reversible_command (_("add range marker"));
session->add_undo (session->locations()->get_memento());
session->locations()->add (location, true);

View File

@ -46,7 +46,6 @@
#include "ardour_ui.h"
#include "ardour_dialog.h"
#include "ardour_message.h"
#include "mixer_strip.h"
#include "mixer_ui.h"
#include "keyboard.h"
@ -528,8 +527,9 @@ MixerStrip::output_press (GdkEventButton *ev)
using namespace Menu_Helpers;
if (!_session.engine().connected()) {
ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible"));
return TRUE;
MessageDialog msg (_("Not connected to JACK - no I/O changes are possible"));
msg.run ();
return true;
}
MenuList& citems = output_menu.items();
@ -586,8 +586,9 @@ MixerStrip::input_press (GdkEventButton *ev)
citems.clear();
if (!_session.engine().connected()) {
ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible"));
return TRUE;
MessageDialog msg (_("Not connected to JACK - no I/O changes are possible"));
msg.run ();
return true;
}
#if ADVANCED_ROUTE_DISKSTREAM_CONNECTIVITY

View File

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

View File

@ -23,6 +23,8 @@
#include <sigc++/bind.h>
#include <gtkmm/messagedialog.h>
#include <gtkmm2ext/gtk_ui.h>
#include <gtkmm2ext/utils.h>
#include <gtkmm2ext/choice.h>
@ -44,7 +46,6 @@
#include "ardour_ui.h"
#include "ardour_dialog.h"
#include "ardour_message.h"
#include "public_editor.h"
#include "redirect_box.h"
#include "keyboard.h"
@ -318,10 +319,7 @@ void
RedirectBox::selection_changed ()
{
bool sensitive = (redirect_display.get_selection()->count_selected_rows()) ? true : false;
for (vector<Glib::RefPtr<Gtk::Action> >::iterator i = ActionManager::plugin_selection_sensitive_actions.begin(); i != ActionManager::plugin_selection_sensitive_actions.end(); ++i) {
(*i)->set_sensitive (sensitive);
}
ActionManager::set_sensitive (ActionManager::plugin_selection_sensitive_actions, sensitive);
}
void
@ -830,7 +828,8 @@ RedirectBox::paste_redirect_list (list<Redirect*>& redirects)
"Copying the set of redirects on the clipboard failed,\n\
probably because the I/O configuration of the plugins\n\
could not match the configuration of this track.");
ArdourMessage am (0, X_("bad redirect copy dialog"), msg);
MessageDialog am (msg);
am.run ();
}
}
@ -877,7 +876,8 @@ RedirectBox::clone_redirects ()
"Copying the set of redirects on the clipboard failed,\n\
probably because the I/O configuration of the plugins\n\
could not match the configuration of this track.");
ArdourMessage am (0, X_("bad redirect copy dialog"), msg);
MessageDialog am (msg);
am.run ();
}
}
}
@ -1011,7 +1011,8 @@ RedirectBox::edit_redirect (Redirect* redirect)
} else if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
if (!_session.engine().connected()) {
ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible"));
MessageDialog msg ( _("Not connected to JACK - no I/O changes are possible"));
msg.run ();
return;
}

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

View File

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

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

View File

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

View File

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

View File

@ -22,6 +22,7 @@
#define __ardour_route_group_h__
#include <list>
#include <set>
#include <string>
#include <stdint.h>
#include <sigc++/signal.h>
@ -84,6 +85,10 @@ class RouteGroup : public Stateful, public sigc::trackable {
template<class T> void apply (void (AudioTrack::*func)(T, void *), T val, void *src);
/* fills at_set with all members of the group that are AudioTracks */
void audio_track_group (std::set<AudioTrack*>& at_set);
void clear () {
routes.clear ();
changed();

View File

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

View File

@ -10,6 +10,7 @@ using std::string;
#define SNDFILE_HEADER_FORMATS 7
extern const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1];
extern const char * const sndfile_file_endings_strings[SNDFILE_HEADER_FORMATS+1];
extern int sndfile_header_formats[SNDFILE_HEADER_FORMATS];
@ -26,6 +27,7 @@ extern int sndfile_endian_formats[SNDFILE_ENDIAN_FORMATS];
int sndfile_bitdepth_format_from_string(string);
int sndfile_header_format_from_string(string);
int sndfile_endian_format_from_string(string);
string sndfile_file_ending_from_string(string);
int sndfile_data_width (int format);

View File

@ -4,8 +4,13 @@
#include <pbd/compose.h>
#include "gettext.h"
#define _(Text) dgettext (PACKAGE, Text)
#include <vector>
#include <string>
std::vector<std::string> internationalize (const char **);
#define _(Text) dgettext (PACKAGE,Text)
#define N_(Text) gettext_noop (Text)
#define X_(Text) (Text)
#define X_(Text) Text
#endif // __i18n_h__

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);
}
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 <ardour/route_group.h>
#include <ardour/audio_track.h>
#include <ardour/diskstream.h>
#include <ardour/configuration.h>
@ -182,3 +183,15 @@ RouteGroup::set_hidden (bool yn, void *src)
}
FlagsChanged (src); /* EMIT SIGNAL */
}
void
RouteGroup::audio_track_group (set<AudioTrack*>& ats)
{
for (list<Route*>::iterator i = routes.begin(); i != routes.end(); ++i) {
AudioTrack* at = dynamic_cast<AudioTrack*>(*i);
if (at) {
ats.insert (at);
}
}
}

View File

@ -1,12 +1,13 @@
#include <map>
#include <vector>
#include <sndfile.h>
#include <ardour/sndfile_helpers.h>
#include "i18n.h"
using std::map;
using namespace std;
const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1] = {
N_("WAV"),
@ -19,6 +20,17 @@ const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1] = {
0
};
const char* const sndfile_file_endings_strings[SNDFILE_HEADER_FORMATS+1] = {
N_(".wav"),
N_(".aiff"),
N_(".raw"),
N_(".paf"),
N_(".au"),
N_(".ircam"),
N_(".w64"),
0
};
int sndfile_header_formats[SNDFILE_HEADER_FORMATS] = {
SF_FORMAT_WAV,
SF_FORMAT_AIFF,
@ -90,6 +102,23 @@ sndfile_endian_format_from_string (string str)
return -1;
}
string
sndfile_file_ending_from_string (string str)
{
static vector<string> file_endings;
if (file_endings.empty()) {
file_endings = internationalize((const char **) sndfile_file_endings_strings);
}
for (int n = 0; sndfile_header_formats_strings[n]; ++n) {
if (str == sndfile_header_formats_strings[n]) {
return file_endings[n];
}
}
return 0;
}
int
sndfile_data_width (int format)
{