diff options
author | David Robillard <d@drobilla.net> | 2008-02-02 17:22:04 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2008-02-02 17:22:04 +0000 |
commit | 80c3677c837cc9eb432df3d65a34aba543fa7258 (patch) | |
tree | ca23bb7e5bff6c35c151d73221002a9ce3abfe1a /gtk2_ardour | |
parent | 9f63ab9931e6478472853bdda58da47ea29ac125 (diff) |
Merge with 2.0-ongoing R2988
git-svn-id: svn://localhost/ardour2/branches/3.0@2991 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour')
29 files changed, 379 insertions, 122 deletions
diff --git a/gtk2_ardour/ardour.bindings.in b/gtk2_ardour/ardour.bindings.in index 3d488c1ec4..0465889f74 100644 --- a/gtk2_ardour/ardour.bindings.in +++ b/gtk2_ardour/ardour.bindings.in @@ -182,9 +182,12 @@ (gtk_accel_path "<Actions>/Editor/cycle-snap-choice" "3") (gtk_accel_path "<Actions>/Transport/ToggleAutoReturn" "4") (gtk_accel_path "<Actions>/Transport/ToggleClick" "5") +(gtk_accel_path "<Actions>/Editor/tab-to-transient-forwards" "7") +(gtk_accel_path "<Actions>/Editor/tab-to-transient-backwards" "8") (gtk_accel_path "<Actions>/Editor/set-tempo-from-region" "9") (gtk_accel_path "<Actions>/Editor/set-tempo-from-edit-range" "0") + ;; ;; unbound actions ;; diff --git a/gtk2_ardour/ardour3_ui_default.conf b/gtk2_ardour/ardour3_ui_default.conf index b64296ae02..aed0f07bca 100644 --- a/gtk2_ardour/ardour3_ui_default.conf +++ b/gtk2_ardour/ardour3_ui_default.conf @@ -4,11 +4,13 @@ <Option name="ui-rc-file" value="ardour3_ui_dark.rc"/> </UI> <Canvas> - <Option name="waveform outline" value="0f0f0fcc"/> - <Option name="waveform fill" value="3d475378"/> + <Option name="waveform outline" value="0f0f0fc8"/> + <Option name="waveform fill" value="3d4753dc"/> + <Option name="selected waveform outline" value="0f0f0fcc"/> + <Option name="selected waveform fill" value="51518ac8"/> <Option name="clipped waveform" value="ff0000e5"/> - <Option name="region base" value="99a7b5aa"/> - <Option name="selected region base" value="b591a8ff"/> + <Option name="region base" value="99a7b5a0"/> + <Option name="selected region base" value="51518aa0"/> <Option name="midi frame base" value="698f9d6d"/> <Option name="audio track base" value="c6d3d868"/> <Option name="audio bus base" value="dbd1ea68"/> diff --git a/gtk2_ardour/ardour_dialog.cc b/gtk2_ardour/ardour_dialog.cc index 795b924075..bc24389948 100644 --- a/gtk2_ardour/ardour_dialog.cc +++ b/gtk2_ardour/ardour_dialog.cc @@ -24,7 +24,7 @@ #include "ardour_dialog.h" #include "keyboard.h" #include "ardour_ui.h" - +#include "splash.h" ArdourDialog::ArdourDialog (string title, bool modal, bool use_seperator) : Dialog (title, modal, use_seperator) @@ -66,3 +66,17 @@ ArdourDialog::on_unmap () { Dialog::on_unmap (); } + +void +ArdourDialog::on_show () +{ + // never allow the splash screen to obscure any dialog + + Splash* spl = Splash::instance(); + + if (spl) { + spl->pop_back (); + } + + Dialog::on_show (); +} diff --git a/gtk2_ardour/ardour_dialog.h b/gtk2_ardour/ardour_dialog.h index 13248e14de..264dcfcd58 100644 --- a/gtk2_ardour/ardour_dialog.h +++ b/gtk2_ardour/ardour_dialog.h @@ -43,6 +43,7 @@ class ArdourDialog : public Gtk::Dialog bool on_enter_notify_event (GdkEventCrossing*); bool on_leave_notify_event (GdkEventCrossing*); void on_unmap (); + void on_show (); ARDOUR::Session *session; diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index b563fc4186..271cbab85b 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -242,6 +242,10 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[]) ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog)); + /* handle sr mismatch with a dialog */ + + ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog)); + /* lets get this party started */ try { @@ -403,6 +407,15 @@ ARDOUR_UI::~ARDOUR_UI () } } +void +ARDOUR_UI::pop_back_splash () +{ + if (Splash::instance()) { + // Splash::instance()->pop_back(); + Splash::instance()->hide (); + } +} + gint ARDOUR_UI::configure_timeout () { @@ -609,6 +622,7 @@ Please consider the possibilities, and perhaps (re)start JACK.")); win.show_all (); win.set_position (Gtk::WIN_POS_CENTER); + pop_back_splash (); /* we just don't care about the result, but we want to block */ @@ -691,6 +705,8 @@ ARDOUR_UI::check_memory_locking () cb.show(); vbox->show(); hbox.show (); + + pop_back_splash (); editor->ensure_float (msg); msg.run (); @@ -725,6 +741,7 @@ ARDOUR_UI::finish() Ardour was unable to save your session.\n\n\ If you still wish to quit, please use the\n\n\ \"Just quit\" option.")); + pop_back_splash(); msg.run (); return; } @@ -997,8 +1014,27 @@ ARDOUR_UI::redisplay_recent_sessions () get_state_files_in_directory (*i, state_file_paths); - if (state_file_paths.empty()) { - // no state file? + vector<string*>* states; + vector<const gchar*> item; + string fullpath = (*i).to_string(); + + /* remove any trailing / */ + + if (fullpath[fullpath.length()-1] == '/') { + fullpath = fullpath.substr (0, fullpath.length()-1); + } + + /* check whether session still exists */ + if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) { + /* session doesn't exist */ + cerr << "skipping non-existent session " << fullpath << endl; + continue; + } + + /* now get available states for this session */ + + if ((states = Session::possible_states (fullpath)) == 0) { + /* no state file? */ continue; } @@ -1006,8 +1042,6 @@ ARDOUR_UI::redisplay_recent_sessions () Gtk::TreeModel::Row row = *(recent_session_model->append()); - const string fullpath = (*i).to_string(); - row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath); row[recent_session_columns.fullpath] = fullpath; @@ -1153,6 +1187,7 @@ ARDOUR_UI::check_audioengine () if (!engine->connected()) { MessageDialog msg (_("Ardour is not connected to JACK\n" "You cannot open or close sessions in this condition")); + pop_back_splash (); msg.run (); return false; } @@ -1309,6 +1344,7 @@ ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t to create a new track or bus.\n\ You should save Ardour, exit and\n\ restart JACK with more ports.")); + pop_back_splash (); msg.run (); } } @@ -1685,6 +1721,7 @@ 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 .")); + pop_back_splash (); msg.run (); } @@ -2026,6 +2063,7 @@ ARDOUR_UI::fontconfig_dialog () true, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK); + pop_back_splash (); msg.show_all (); msg.present (); msg.run (); @@ -2116,7 +2154,8 @@ ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path msg.set_name (X_("CleanupDialog")); msg.set_wmclass (X_("existing_session"), "Ardour"); msg.set_position (Gtk::WIN_POS_MOUSE); - + pop_back_splash (); + switch (msg.run()) { case RESPONSE_YES: return true; @@ -2325,6 +2364,7 @@ ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be session_path = new_session_dialog->session_folder(); } + template_name = Glib::ustring(); switch (new_session_dialog->which_page()) { case NewSessionDialog::OpenPage: @@ -2374,7 +2414,7 @@ ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be loadit: new_session_dialog->hide (); - if (load_session (session_path, session_name)) { + if (load_session (session_path, session_name, template_name)) { /* force a retry */ response = Gtk::RESPONSE_NONE; } @@ -2435,6 +2475,7 @@ ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_na if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) { MessageDialog msg (*editor, _("You do not have write access to this session.\n" "This prevents the session from being loaded.")); + pop_back_splash (); msg.run (); goto out; } @@ -2458,6 +2499,7 @@ ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_na msg.set_title (_("Loading Error")); msg.set_secondary_text (_("Click the OK button to try again.")); msg.set_position (Gtk::WIN_POS_CENTER); + pop_back_splash (); msg.present (); int response = msg.run (); @@ -2483,6 +2525,7 @@ ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_na msg.set_title (_("Loading Error")); msg.set_secondary_text (_("Click the OK button to try again.")); msg.set_position (Gtk::WIN_POS_CENTER); + pop_back_splash (); msg.present (); int response = msg.run (); @@ -2555,6 +2598,7 @@ ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_n catch (...) { MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path)); + pop_back_splash (); msg.run (); return -1; } @@ -3030,6 +3074,38 @@ what you would like to do.\n")); return 0; } } + +int +ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual) +{ + HBox* hbox = new HBox(); + Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG); + ArdourDialog dialog (_("Sample Rate Mismatch"), true); + Label message (string_compose (_("\ +This session was created with a sample rate of %1 Hz\n\ +\n\ +The audioengine is currently running at %2 Hz\n"), desired, actual)); + + image->set_alignment(ALIGN_CENTER, ALIGN_TOP); + hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12); + hbox->pack_end (message, PACK_EXPAND_PADDING, 12); + dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6); + dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT); + dialog.add_button (_("Do not load session"), RESPONSE_REJECT); + dialog.set_default_response (RESPONSE_ACCEPT); + dialog.set_position (WIN_POS_CENTER); + message.show(); + image->show(); + hbox->show(); + + switch (dialog.run ()) { + case RESPONSE_ACCEPT: + return 0; + default: + return 1; + } +} + void ARDOUR_UI::disconnect_from_jack () diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 247d4cf6b3..01e53c7d54 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -660,7 +660,9 @@ class ARDOUR_UI : public Gtkmm2ext::UI About* about; Splash* splash; + void pop_back_splash (); bool shown_flag; + /* cleanup */ Gtk::MenuItem *cleanup_item; @@ -682,6 +684,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI void disk_underrun_handler (); int pending_state_dialog (); + int sr_mismatch_dialog (nframes_t, nframes_t); void disconnect_from_jack (); void reconnect_to_jack (); diff --git a/gtk2_ardour/ardour_ui_dependents.cc b/gtk2_ardour/ardour_ui_dependents.cc index d4dda9c540..a2ac809203 100644 --- a/gtk2_ardour/ardour_ui_dependents.cc +++ b/gtk2_ardour/ardour_ui_dependents.cc @@ -52,6 +52,7 @@ ARDOUR_UI::shutdown () session->remove_pending_capture_state (); session = 0; } + ui_config->save_state(); } diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index efd1bdd503..d19abf2ce5 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -1220,14 +1220,15 @@ AudioRegionView::set_frame_color () uint32_t r,g,b,a; if (_selected && should_show_selection) { - frame->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_WaveForm.get(); + UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_SelectedFrameBase.get(), &r, &g, &b, &a); + frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, fill_opacity ? fill_opacity : a); - UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_FrameBase.get(), &r, &g, &b, &a); for (vector<ArdourCanvas::WaveView*>::iterator w = waves.begin(); w != waves.end(); ++w) { if (_region->muted()) { - (*w)->property_wave_color() = RGBA_TO_UINT(r, g, b, MUTED_ALPHA); + (*w)->property_wave_color() = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->canvasvar_SelectedWaveForm.get(), MUTED_ALPHA); } else { - (*w)->property_wave_color() = RGBA_TO_UINT(r, g, b, fill_opacity ? fill_opacity : a);// Lets still use the theme's opacity value if Opaque is not set + (*w)->property_wave_color() = ARDOUR_UI::config()->canvasvar_SelectedWaveForm.get(); + (*w)->property_fill_color() = ARDOUR_UI::config()->canvasvar_SelectedWaveFormFill.get(); } } } else { diff --git a/gtk2_ardour/canvas_vars.h b/gtk2_ardour/canvas_vars.h index 354618e176..8085ec0227 100644 --- a/gtk2_ardour/canvas_vars.h +++ b/gtk2_ardour/canvas_vars.h @@ -1,5 +1,7 @@ CANVAS_VARIABLE(canvasvar_WaveForm, "waveform outline") CANVAS_VARIABLE(canvasvar_WaveFormFill, "waveform fill") +CANVAS_VARIABLE(canvasvar_SelectedWaveForm, "selected waveform outline") +CANVAS_VARIABLE(canvasvar_SelectedWaveFormFill, "selected waveform fill") CANVAS_VARIABLE(canvasvar_WaveFormClip, "clipped waveform") CANVAS_VARIABLE(canvasvar_FrameBase, "region base") CANVAS_VARIABLE(canvasvar_SelectedFrameBase, "selected region base") diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 5c93877e07..d26f01f76b 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1803,12 +1803,25 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi items.push_back (CheckMenuElem (_("Lock"))); CheckMenuItem* region_lock_item = static_cast<CheckMenuItem*>(&items.back()); - fooc = region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock)); if (region->locked()) { - fooc.block (true); region_lock_item->set_active(); - fooc.block (false); } + region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock)); + + items.push_back (CheckMenuElem (_("Glue to Bars&Beats"))); + CheckMenuItem* bbt_glue_item = static_cast<CheckMenuItem*>(&items.back()); + + switch (region->positional_lock_style()) { + case Region::MusicTime: + bbt_glue_item->set_active (true); + break; + default: + bbt_glue_item->set_active (true); + break; + } + + bbt_glue_item->signal_activate().connect (bind (mem_fun (*this, &Editor::set_region_lock_style), Region::MusicTime)); + items.push_back (CheckMenuElem (_("Mute"))); CheckMenuItem* region_mute_item = static_cast<CheckMenuItem*>(&items.back()); fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute)); @@ -3366,15 +3379,25 @@ Editor::hide_verbose_canvas_cursor () verbose_cursor_visible = false; } +double +Editor::clamp_verbose_cursor_x (double x) +{ + return min (horizontal_adjustment.get_value() + canvas_width - 75.0, x); +} + +double +Editor::clamp_verbose_cursor_y (double y) +{ + return min (vertical_adjustment.get_value() + canvas_height - 50.0, y); +} + void Editor::set_verbose_canvas_cursor (const string & txt, double x, double y) { - /* XXX get origin of canvas relative to root window, - add x and y and check compared to gdk_screen_{width,height} - */ verbose_canvas_cursor->property_text() = txt.c_str(); - verbose_canvas_cursor->property_x() = x; - verbose_canvas_cursor->property_y() = y; + /* don't get too close to the edge */ + verbose_canvas_cursor->property_x() = clamp_verbose_cursor_x (x); + verbose_canvas_cursor->property_y() = clamp_verbose_cursor_x (y); } void diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 56b0077b99..5b4e54f4f6 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1019,7 +1019,7 @@ class Editor : public PublicEditor void toggle_region_mute (); void toggle_region_lock (); void toggle_region_opaque (); - void toggle_region_position_lock (); + void set_region_lock_style (ARDOUR::Region::PositionLockStyle); void raise_region (); void raise_region_to_top (); void lower_region (); @@ -1028,7 +1028,7 @@ class Editor : public PublicEditor void split_region_at (nframes_t); void split_regions_at (nframes_t, RegionSelection&); void split_region_at_transients (); - void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, std::vector<nframes64_t>&); + void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&); void crop_region_to_selection (); void crop_region_to (nframes_t start, nframes_t end); void set_sync_point (nframes64_t, const RegionSelection&); @@ -1334,6 +1334,8 @@ class Editor : public PublicEditor void show_verbose_time_cursor (nframes_t frame, double offset = 0, double xpos=-1, double ypos=-1); void show_verbose_duration_cursor (nframes_t start, nframes_t end, double offset = 0, double xpos=-1, double ypos=-1); + double clamp_verbose_cursor_x (double); + double clamp_verbose_cursor_y (double); /* Canvas event handlers */ diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 51752fb6bb..3627a7fe23 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -377,7 +377,7 @@ Editor::register_actions () act = ActionManager::register_action (editor_actions, "tab-to-transient-forwards", _("Move Forward to Transient"), bind (mem_fun(*this, &Editor::tab_to_transient), true)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "tab-to-transient-backwards", _("Move Forward to Transient"), bind (mem_fun(*this, &Editor::tab_to_transient), false)); + act = ActionManager::register_action (editor_actions, "tab-to-transient-backwards", _("Move Backwards to Transient"), bind (mem_fun(*this, &Editor::tab_to_transient), false)); ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (editor_actions, "crop", _("Crop"), mem_fun(*this, &Editor::crop_region_to_selection)); diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index a69dcf935a..3de7dc5c21 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -19,6 +19,7 @@ #include <cstdlib> #include <cmath> +#include <algorithm> #include <pbd/stacktrace.h> @@ -43,6 +44,7 @@ #include "i18n.h" using namespace sigc; +using namespace std; using namespace ARDOUR; using namespace PBD; using namespace Gtk; @@ -245,8 +247,8 @@ bool Editor::track_canvas_motion (GdkEvent *ev) { if (verbose_cursor_visible) { - verbose_canvas_cursor->property_x() = ev->motion.x + 20; - verbose_canvas_cursor->property_y() = ev->motion.y + 20; + verbose_canvas_cursor->property_x() = clamp_verbose_cursor_x (ev->motion.x + 20); + verbose_canvas_cursor->property_y() = clamp_verbose_cursor_y (ev->motion.y + 20); } #ifdef GTKOSX diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 9689cdc64a..4234368acd 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -3382,7 +3382,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) } if (sync_frame - sync_offset <= sync_frame) { - pending_region_position = sync_frame + (sync_dir*sync_offset); + pending_region_position = sync_frame - (sync_dir*sync_offset); } else { pending_region_position = 0; } diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 1f833e8337..77b0883fc1 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -57,6 +57,7 @@ #include "ardour_ui.h" #include "editor.h" #include "time_axis_view.h" +#include "route_time_axis.h" #include "audio_time_axis.h" #include "automation_time_axis.h" #include "streamview.h" @@ -1659,7 +1660,6 @@ Editor::temporal_zoom_region () ensure_entered_region_selected (true); if (selection->regions.empty()) { - info << _("cannot set loop: no region selected") << endmsg; return; } @@ -3540,13 +3540,11 @@ Editor::cut_copy (CutCopyOp op) switch (current_mouse_mode()) { case MouseObject: - cerr << "cutting in object mode\n"; if (!selection->regions.empty() || !selection->points.empty()) { begin_reversible_command (opname + _(" objects")); if (!selection->regions.empty()) { - cerr << "have regions to cut" << endl; cut_copy_regions (op); if (op == Cut) { @@ -3565,7 +3563,6 @@ Editor::cut_copy (CutCopyOp op) commit_reversible_command (); break; // terminate case statement here } - cerr << "nope, now cutting time range" << endl; if (!selection->time.empty()) { /* don't cause suprises */ break; @@ -3575,9 +3572,7 @@ Editor::cut_copy (CutCopyOp op) case MouseRange: if (selection->time.empty()) { nframes64_t start, end; - cerr << "no time selection, get edit op range" << endl; if (!get_edit_op_range (start, end)) { - cerr << "no edit op range" << endl; return; } selection->set ((TimeAxisView*) 0, start, end); @@ -4376,6 +4371,15 @@ Editor::toggle_region_lock () } void +Editor::set_region_lock_style (Region::PositionLockStyle ps) +{ + for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { + (*i)->region()->set_position_lock_style (ps); + } +} + + +void Editor::toggle_region_mute () { for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { @@ -5013,31 +5017,70 @@ void Editor::define_one_bar (nframes64_t start, nframes64_t end) { nframes64_t length = end - start; - + const Meter& m (session->tempo_map().meter_at (start)); - /* region length = 1 bar */ + /* length = 1 bar */ - /* 1 bar = how many beats per bar */ - - double beats_per_bar = m.beats_per_bar(); - /* now we want frames per beat. we have frames per bar, and beats per bar, so ... */ - double frames_per_beat = length / beats_per_bar; + double frames_per_beat = length / m.beats_per_bar(); /* beats per minute = */ double beats_per_minute = (session->frame_rate() * 60.0) / frames_per_beat; + /* now decide whether to: + + (a) set global tempo + (b) add a new tempo marker + + */ + const TempoSection& t (session->tempo_map().tempo_section_at (start)); + bool do_global = false; + + if ((session->tempo_map().n_tempos() == 1) && (session->tempo_map().n_meters() == 1)) { + + /* only 1 tempo & 1 meter: ask if the user wants to set the tempo + at the start, or create a new marker + */ + + vector<string> options; + options.push_back (_("Set global tempo")); + options.push_back (_("Add new marker")); + options.push_back (_("Cancel")); + Choice c (_("Do you want to set the global tempo or add new tempo marker?"), + options); + + switch (c.run()) { + case 0: + do_global = true; + break; + case 2: + return; + + default: + do_global = false; + } + + } else { + + /* more than 1 tempo and/or meter section already, go ahead do the "usual": + if the marker is at the region starter, change it, otherwise add + a new tempo marker + */ + } + begin_reversible_command (_("set tempo from region")); XMLNode& before (session->tempo_map().get_state()); - if (t.frame() == start) { + if (do_global) { + session->tempo_map().change_initial_tempo (beats_per_minute, t.note_type()); + } else if (t.frame() == start) { session->tempo_map().change_existing_tempo_at (start, beats_per_minute, t.note_type()); } else { session->tempo_map().add_tempo (Tempo (beats_per_minute, t.note_type()), start); @@ -5052,7 +5095,7 @@ Editor::define_one_bar (nframes64_t start, nframes64_t end) void Editor::split_region_at_transients () { - vector<nframes64_t> positions; + AnalysisFeatureList positions; if (!session) { return; @@ -5088,7 +5131,7 @@ Editor::split_region_at_transients () } void -Editor::split_region_at_points (boost::shared_ptr<Region> r, vector<nframes64_t>& positions) +Editor::split_region_at_points (boost::shared_ptr<Region> r, AnalysisFeatureList& positions) { boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r); @@ -5106,7 +5149,7 @@ Editor::split_region_at_points (boost::shared_ptr<Region> r, vector<nframes64_t> return; } - vector<nframes64_t>::const_iterator x; + AnalysisFeatureList::const_iterator x; nframes64_t pos = ar->position(); @@ -5163,30 +5206,52 @@ Editor::split_region_at_points (boost::shared_ptr<Region> r, vector<nframes64_t> void Editor::tab_to_transient (bool forward) { - - vector<nframes64_t> positions; + AnalysisFeatureList positions; if (!session) { return; } - ExclusiveRegionSelection esr (*this, entered_regionview); + nframes64_t pos = session->audible_frame (); - if (selection->regions.empty()) { - return; - } - - boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (selection->regions.front()->region()); + if (!selection->tracks.empty()) { - if (!ar) { - return; + for (TrackSelection::iterator t = selection->tracks.begin(); t != selection->tracks.end(); ++t) { + + RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*t); + + if (rtv) { + boost::shared_ptr<Diskstream> ds = rtv->get_diskstream(); + if (ds) { + boost::shared_ptr<Playlist> pl = rtv->get_diskstream()->playlist (); + if (pl) { + nframes64_t result = pl->find_next_transient (pos, forward ? 1 : -1); + + if (result >= 0) { + positions.push_back (result); + } + } + } + } + } + + } else { + + ExclusiveRegionSelection esr (*this, entered_regionview); + + if (selection->regions.empty()) { + return; + } + + for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) { + (*r)->region()->get_transients (positions); + } } - ar->get_transients (positions); - nframes64_t pos = session->audible_frame (); + TransientDetector::cleanup_transients (positions, session->frame_rate(), 3.0); if (forward) { - vector<nframes64_t>::iterator x; + AnalysisFeatureList::iterator x; for (x = positions.begin(); x != positions.end(); ++x) { if ((*x) > pos) { @@ -5199,7 +5264,7 @@ Editor::tab_to_transient (bool forward) } } else { - vector<nframes64_t>::reverse_iterator x; + AnalysisFeatureList::reverse_iterator x; for (x = positions.rbegin(); x != positions.rend(); ++x) { if ((*x) < pos) { diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc index 591c3d12fe..39c74323f3 100644 --- a/gtk2_ardour/editor_tempodisplay.cc +++ b/gtk2_ardour/editor_tempodisplay.cc @@ -365,10 +365,14 @@ Editor::edit_tempo_section (TempoSection* section) tempo_dialog.get_bbt_time(when); bpm = max (0.01, bpm); + cerr << "Editing tempo section to be at " << when << endl; + session->tempo_map().dump (cerr); begin_reversible_command (_("replace tempo mark")); XMLNode &before = session->tempo_map().get_state(); session->tempo_map().replace_tempo (*section, Tempo (bpm,nt)); + session->tempo_map().dump (cerr); session->tempo_map().move_tempo (*section, when); + session->tempo_map().dump (cerr); XMLNode &after = session->tempo_map().get_state(); session->add_command (new MementoCommand<TempoMap>(session->tempo_map(), &before, &after)); commit_reversible_command (); diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc index 9835901a24..4e5e068f65 100644 --- a/gtk2_ardour/engine_dialog.cc +++ b/gtk2_ardour/engine_dialog.cc @@ -553,10 +553,12 @@ EngineControl::setup_engine () error << string_compose (_("cannot open JACK rc file %1 to store parameters"), jackdrc_path) << endmsg; return -1; } - + cerr << "JACK COMMAND: "; for (vector<string>::iterator i = args.begin(); i != args.end(); ++i) { + cerr << (*i) << ' '; jackdrc << (*i) << ' '; } + cerr << endl; jackdrc << endl; jackdrc.close (); @@ -915,7 +917,7 @@ EngineControl::find_jack_servers (vector<string>& strings) _NSGetExecutablePath (execpath, &pathsz); - Glib::ustring path (Glib::path_get_dirname (execpath)); + string path (Glib::path_get_dirname (execpath)); path += "/jackd"; if (Glib::file_test (path, FILE_TEST_EXISTS)) { @@ -937,8 +939,36 @@ EngineControl::find_jack_servers (vector<string>& strings) PathScanner scanner; vector<string *> *jack_servers; std::map<string,int> un; - - path = getenv ("PATH"); + char *p; + bool need_minimal_path = false; + + p = getenv ("PATH"); + + if (p && *p) { + path = p; + } else { + need_minimal_path = true; + } + +#ifdef __APPLE__ + // many mac users don't have PATH set up to include + // likely installed locations of JACK + need_minimal_path = true; +#endif + + if (need_minimal_path) { + if (path.empty()) { + path = "/usr/bin:/bin:/usr/local/bin:/opt/local/bin"; + } else { + path += ":/usr/local/bin:/opt/local/bin"; + } + } + +#ifdef __APPLE__ + // push it back into the environment so that auto-started JACK can find it. + // XXX why can't we just expect OS X users to have PATH set correctly? we can't ... + setenv ("PATH", path.c_str(), 1); +#endif jack_servers = scanner (path, jack_server_filter, 0, false, true); diff --git a/gtk2_ardour/generic_pluginui.cc b/gtk2_ardour/generic_pluginui.cc index ed185c33bc..6e3119b373 100644 --- a/gtk2_ardour/generic_pluginui.cc +++ b/gtk2_ardour/generic_pluginui.cc @@ -38,7 +38,9 @@ #include <ardour/plugin.h> #include <ardour/plugin_insert.h> #include <ardour/ladspa_plugin.h> +#ifdef HAVE_LV2 #include <ardour/lv2_plugin.h> +#endif #include <lrdf.h> @@ -385,8 +387,9 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat if (plugin->parameter_is_input (port_index)) { boost::shared_ptr<LadspaPlugin> lp; +#ifdef HAVE_LV2 boost::shared_ptr<LV2Plugin> lv2p; - +#endif if ((lp = boost::dynamic_pointer_cast<LadspaPlugin>(plugin)) != 0) { // FIXME: not all plugins have a numeric unique ID @@ -409,6 +412,7 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat return control_ui; } +#ifdef HAVE_LV2 } else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin>(plugin)) != 0) { SLV2Port port = lv2p->slv2_port(port_index); @@ -428,6 +432,7 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat slv2_scale_points_free(points); return control_ui; } +#endif } if (desc.toggled) { @@ -757,7 +762,9 @@ GenericPluginUI::setup_scale_values(guint32 port_index, ControlUI* cui) { vector<string> enums; boost::shared_ptr<LadspaPlugin> lp; +#ifdef HAVE_LV2 boost::shared_ptr<LV2Plugin> lv2p; +#endif if ((lp = boost::dynamic_pointer_cast<LadspaPlugin>(plugin)) != 0) { // all LADPSA plugins have a numeric unique ID @@ -777,6 +784,7 @@ GenericPluginUI::setup_scale_values(guint32 port_index, ControlUI* cui) lrdf_free_setting_values(defaults); } +#ifdef HAVE_LV2 } else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin>(plugin)) != 0) { SLV2Port port = lv2p->slv2_port(port_index); @@ -797,6 +805,7 @@ GenericPluginUI::setup_scale_values(guint32 port_index, ControlUI* cui) } slv2_scale_points_free(points); +#endif } diff --git a/gtk2_ardour/icons/ferret_02.png b/gtk2_ardour/icons/ferret_02.png Binary files differnew file mode 100644 index 0000000000..a6d625b64e --- /dev/null +++ b/gtk2_ardour/icons/ferret_02.png diff --git a/gtk2_ardour/new_session_dialog.cc b/gtk2_ardour/new_session_dialog.cc index 1b9d81df22..e995ff1a8e 100644 --- a/gtk2_ardour/new_session_dialog.cc +++ b/gtk2_ardour/new_session_dialog.cc @@ -971,6 +971,8 @@ NewSessionDialog::reset_recent() i != session_directories.end(); ++i) { std::vector<sys::path> state_file_paths; + std::vector<std::string*>* states; + const string fullpath = (*i).to_string(); // now get available states for this session @@ -980,28 +982,37 @@ NewSessionDialog::reset_recent() // no state file? continue; } - - std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths)); - + + /* check whether session still exists */ + if (!Glib::file_test(fullpath, Glib::FILE_TEST_EXISTS)) { + /* session doesn't exist */ + continue; + } + + /* now get available states for this session */ + + if ((states = ARDOUR::Session::possible_states (fullpath)) == 0) { + /* no state file? */ + continue; + } + Gtk::TreeModel::Row row = *(recent_model->append()); - - const string fullpath = (*i).to_string(); row[recent_columns.visible_name] = Glib::path_get_basename (fullpath); row[recent_columns.fullpath] = fullpath; - if (state_file_names.size() > 1) { - - // add the children - - for (std::vector<std::string>::iterator i2 = state_file_names.begin(); - i2 != state_file_names.end(); ++i2) - { - - Gtk::TreeModel::Row child_row = *(recent_model->append (row.children())); - - child_row[recent_columns.visible_name] = *i2; + if (states->size()) { + + /* add the children */ + + for (std::vector<std::string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) { + + Gtk::TreeModel::Row child_row = *(recent_model->append (row.children())); + + child_row[recent_columns.visible_name] = **i2; child_row[recent_columns.fullpath] = fullpath; + + delete *i2; } } } diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index f279f93c39..3f2c90e05a 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -254,7 +254,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway virtual void restore_editing_space () = 0; virtual nframes64_t get_preferred_edit_position (bool ignore_playhead = false) = 0; virtual void toggle_meter_updating() = 0; - virtual void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, std::vector<nframes64_t>&) = 0; + virtual void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&) = 0; #ifdef WITH_CMT virtual void add_imageframe_time_axis(const std::string & track_name, void*) = 0; diff --git a/gtk2_ardour/rhythm_ferret.cc b/gtk2_ardour/rhythm_ferret.cc index 980b36e1d1..d8d2f3c28b 100644 --- a/gtk2_ardour/rhythm_ferret.cc +++ b/gtk2_ardour/rhythm_ferret.cc @@ -13,6 +13,7 @@ #include "rhythm_ferret.h" #include "audio_region_view.h" #include "public_editor.h" +#include "utils.h" #include "i18n.h" @@ -57,9 +58,9 @@ RhythmFerret::RhythmFerret (PublicEditor& e) { upper_hpacker.set_spacing (6); - upper_hpacker.pack_start (operation_frame, true, true); - upper_hpacker.pack_start (selection_frame, true, true); upper_hpacker.pack_start (ferret_frame, true, true); + upper_hpacker.pack_start (selection_frame, true, true); + upper_hpacker.pack_start (operation_frame, true, true); op_packer.pack_start (region_split_button, false, false); op_packer.pack_start (tempo_button, false, false); @@ -107,15 +108,17 @@ RhythmFerret::RhythmFerret (PublicEditor& e) analyze_button.signal_clicked().connect (mem_fun (*this, &RhythmFerret::run_analysis)); ferret_frame.add (ferret_packer); - - // Glib::RefPtr<Pixbuf> logo_pixbuf ("somefile"); + logo = manage (new Gtk::Image (::get_icon (X_("ferret_02")))); + if (logo) { lower_hpacker.pack_start (*logo, false, false); } - lower_hpacker.pack_start (operation_clarification_label, false, false); + lower_hpacker.pack_start (operation_clarification_label, true, true); lower_hpacker.pack_start (action_button, false, false); + lower_hpacker.set_border_width (6); + lower_hpacker.set_spacing (6); action_button.signal_clicked().connect (mem_fun (*this, &RhythmFerret::do_action)); @@ -194,13 +197,13 @@ RhythmFerret::run_analysis () } int -RhythmFerret::run_percussion_onset_analysis (boost::shared_ptr<Readable> readable, nframes64_t offset, vector<nframes64_t>& results) +RhythmFerret::run_percussion_onset_analysis (boost::shared_ptr<Readable> readable, nframes64_t offset, AnalysisFeatureList& results) { TransientDetector t (session->frame_rate()); for (uint32_t i = 0; i < readable->n_channels(); ++i) { - vector<nframes64_t> these_results; + AnalysisFeatureList these_results; t.reset (); t.set_threshold (detection_threshold_adjustment.get_value()); @@ -212,38 +215,18 @@ RhythmFerret::run_percussion_onset_analysis (boost::shared_ptr<Readable> readabl /* translate all transients to give absolute position */ - for (vector<nframes64_t>::iterator i = these_results.begin(); i != these_results.end(); ++i) { - (*i) += offset; + for (AnalysisFeatureList::iterator x = these_results.begin(); x != these_results.end(); ++x) { + (*x) += offset; } /* merge */ results.insert (results.end(), these_results.begin(), these_results.end()); + these_results.clear (); } - - if (!results.empty()) { - - /* now resort to bring transients from different channels together */ - - sort (results.begin(), results.end()); - - /* remove duplicates or other things that are too close */ - - vector<nframes64_t>::iterator i = results.begin(); - nframes64_t curr = (*i); - nframes64_t gap_frames = (nframes64_t) floor (trigger_gap_adjustment.get_value() * (session->frame_rate() / 1000.0)); - - ++i; - - while (i != results.end()) { - if (((*i) == curr) || (((*i) - curr) < gap_frames)) { - i = results.erase (i); - } else { - ++i; - curr = *i; - } - } + if (!results.empty()) { + TransientDetector::cleanup_transients (results, session->frame_rate(), trigger_gap_adjustment.get_value()); } return 0; diff --git a/gtk2_ardour/rhythm_ferret.h b/gtk2_ardour/rhythm_ferret.h index 36d4450939..891b447a11 100644 --- a/gtk2_ardour/rhythm_ferret.h +++ b/gtk2_ardour/rhythm_ferret.h @@ -84,17 +84,17 @@ class RhythmFerret : public ArdourDialog { std::vector<std::string> analysis_mode_strings; - std::vector<nframes64_t> current_results; + ARDOUR::AnalysisFeatureList current_results; AnalysisMode get_analysis_mode () const; Action get_action() const; void run_analysis (); - int run_percussion_onset_analysis (boost::shared_ptr<ARDOUR::Readable> region, nframes64_t offset, std::vector<nframes64_t>& results); + int run_percussion_onset_analysis (boost::shared_ptr<ARDOUR::Readable> region, nframes64_t offset, ARDOUR::AnalysisFeatureList& results); void do_action (); void do_split_action (); - void do_region_split (RegionView* rv, const std::vector<nframes64_t>&); + void do_region_split (RegionView* rv, const ARDOUR::AnalysisFeatureList&); }; #endif /* __gtk2_ardour_rhythm_ferret_h__ */ diff --git a/gtk2_ardour/splash.cc b/gtk2_ardour/splash.cc index 9317ec1caa..e901521e37 100644 --- a/gtk2_ardour/splash.cc +++ b/gtk2_ardour/splash.cc @@ -14,6 +14,8 @@ using namespace Glib; using namespace std; using namespace ARDOUR; +Splash* Splash::the_splash = 0; + Splash::Splash () { sys::path splash_file; @@ -47,6 +49,14 @@ Splash::Splash () darea.signal_expose_event().connect (mem_fun (*this, &Splash::expose)); add (darea); + + the_splash = this; +} + +void +Splash::pop_back () +{ + set_keep_above (false); } void diff --git a/gtk2_ardour/splash.h b/gtk2_ardour/splash.h index 5ba5478941..07532d9344 100644 --- a/gtk2_ardour/splash.h +++ b/gtk2_ardour/splash.h @@ -34,13 +34,19 @@ class Splash : public Gtk::Window Splash (); ~Splash () {} + static Splash* instance() { return the_splash; } + + void pop_back (); + bool expose (GdkEventExpose*); bool on_button_release_event (GdkEventButton*); void on_realize (); - + void message (const std::string& msg); private: + static Splash* the_splash; + Glib::RefPtr<Gdk::Pixbuf> pixbuf; Gtk::DrawingArea darea; Glib::RefPtr<Pango::Layout> layout; diff --git a/gtk2_ardour/tempo_dialog.cc b/gtk2_ardour/tempo_dialog.cc index 0c99a4eeb0..6f46ec1a9d 100644 --- a/gtk2_ardour/tempo_dialog.cc +++ b/gtk2_ardour/tempo_dialog.cc @@ -243,7 +243,6 @@ TempoDialog::get_note_type () } } - cerr << "returning " << note_type << " based on " << text << endl; return note_type; } diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc index a3262baec5..abe4e93043 100644 --- a/gtk2_ardour/time_axis_view.cc +++ b/gtk2_ardour/time_axis_view.cc @@ -1104,7 +1104,7 @@ TimeAxisView::covers_y_position (double y) } void -TimeAxisView::show_temporary_lines (const vector<nframes64_t>& pos) +TimeAxisView::show_temporary_lines (const AnalysisFeatureList& pos) { while (temp_lines.size()< pos.size()) { ArdourCanvas::SimpleLine* l = new ArdourCanvas::SimpleLine (*canvas_display); @@ -1120,7 +1120,7 @@ TimeAxisView::show_temporary_lines (const vector<nframes64_t>& pos) delete line; } - vector<nframes64_t>::const_iterator i; + AnalysisFeatureList::const_iterator i; list<ArdourCanvas::SimpleLine*>::iterator l; for (i = pos.begin(), l = temp_lines.begin(); i != pos.end() && l != temp_lines.end(); ++i, ++l) { diff --git a/gtk2_ardour/time_axis_view.h b/gtk2_ardour/time_axis_view.h index f3bdbec706..c210d6deb0 100644 --- a/gtk2_ardour/time_axis_view.h +++ b/gtk2_ardour/time_axis_view.h @@ -172,7 +172,7 @@ class TimeAxisView : public virtual AxisView virtual ARDOUR::RouteGroup* edit_group() const { return 0; } virtual boost::shared_ptr<ARDOUR::Playlist> playlist() const { return boost::shared_ptr<ARDOUR::Playlist> (); } - virtual void show_temporary_lines (const std::vector<nframes64_t>&); + virtual void show_temporary_lines (const ARDOUR::AnalysisFeatureList&); virtual void hide_temporary_lines (); virtual void set_samples_per_unit (double); diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc index a523878446..3a61a8676a 100644 --- a/gtk2_ardour/utils.cc +++ b/gtk2_ardour/utils.cc @@ -466,6 +466,16 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) int ret = false; switch (ev->keyval) { + case GDK_Tab: + ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_nabla, GdkModifierType(ev->state)); + break; + + // some X and/or GDK implementations do Shift-Tab -> GDK_ISO_Left_Tab + + case GDK_ISO_Left_Tab: + ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_nabla, GdkModifierType(ev->state)); + break; + case GDK_Up: ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_uparrow, GdkModifierType(ev->state)); break; |