diff --git a/SConstruct b/SConstruct index db2c095250..c887145a0c 100644 --- a/SConstruct +++ b/SConstruct @@ -5,6 +5,7 @@ # import os +import os.path import sys import re import shutil @@ -35,7 +36,6 @@ opts.AddOptions( BoolOption('AUDIOUNITS', 'Compile with Apple\'s AudioUnit library. (experimental)', 0), BoolOption('COREAUDIO', 'Compile with Apple\'s CoreAudio library', 0), BoolOption('GTKOSX', 'Compile for use with GTK-OSX, not GTK-X11', 0), - BoolOption('NATIVE_OSX_KEYS', 'Build key bindings file that matches OS X conventions', 0), BoolOption('OLDFONTS', 'Old school font sizes', 0), BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 0), BoolOption('STL_DEBUG', 'Set to build with Standard Template Library Debugging', 0), @@ -57,7 +57,8 @@ opts.AddOptions( BoolOption('LV2', 'Compile with support for LV2 (if slv2 is available)', 0), BoolOption('GPROFILE', 'Compile with support for gprofile (Developers only)', 0), BoolOption('FREEDESKTOP', 'Install MIME type, icons and .desktop file as per the freedesktop.org spec (requires xdg-utils and shared-mime-info). "scons uninstall" removes associations in desktop database', 0), - BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1) + BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1), + BoolOption('AUBIO', "Use Paul Brossier's aubio library for feature detection (if available)", 1) ) #---------------------------------------------------------------------- @@ -450,7 +451,8 @@ deps = \ 'raptor' : '1.4.2', 'lrdf' : '0.4.0', 'jack' : '0.109.0', - 'libgnomecanvas-2.0' : '2.0' + 'libgnomecanvas-2.0' : '2.0', + 'aubio' : '0.3.2' } def DependenciesRequiredMessage(): @@ -523,6 +525,13 @@ if conf.CheckPKGExists ('fftw3'): libraries['fftw3'] = LibraryInfo() libraries['fftw3'].ParseConfig('pkg-config --cflags --libs fftw3') +if conf.CheckPKGExists ('aubio'): + libraries['aubio'] = LibraryInfo() + libraries['aubio'].ParseConfig('pkg-config --cflags --libs aubio') + env['AUBIO'] = 1 +else: + env['AUBIO'] = 0 + env = conf.Finish () if env['FFT_ANALYSIS']: @@ -828,8 +837,9 @@ def prep_libcheck(topenv, libinfo): # rationale: GTK-Quartz uses jhbuild and installs to /opt/gtk by default. # All libraries needed should be built against this location if topenv['GTKOSX']: - libinfo.Append(CPPPATH="/opt/gtk/include", LIBPATH="/opt/gtk/lib") - libinfo.Append(CXXFLAGS="-I/opt/gtk/include", LINKFLAGS="-L/opt/gtk/lib") + gtkroot = os.path.expanduser ("~"); + libinfo.Append(CPPPATH="$GTKROOT/include", LIBPATH="$GTKROOT/lib") + libinfo.Append(CXXFLAGS="-I$GTKROOT/include", LINKFLAGS="-L$GTKROOT/lib") libinfo.Append(CPPPATH="/opt/local/include", LIBPATH="/opt/local/lib") libinfo.Append(CXXFLAGS="-I/opt/local/include", LINKFLAGS="-L/opt/local/lib") @@ -921,7 +931,7 @@ prep_libcheck(env, libraries['boost']) libraries['boost'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib") conf = Configure (libraries['boost']) if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == False: - print "Boost header files do not appear to be installed." + print "Boost header files do not appear to be installed. You also might be running a buggy version of scons. Try scons 0.97 if you can." sys.exit (1) libraries['boost'] = conf.Finish () @@ -1081,7 +1091,8 @@ if env['SYSLIBS']: CPPPATH='#libs/appleutility') coredirs = [ - 'templates' + 'templates', + 'manual' ] subdirs = [ @@ -1155,7 +1166,8 @@ else: CPPPATH='#libs/appleutility') coredirs = [ - 'templates' + 'templates', + 'manual' ] subdirs = [ diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript index ebc4529490..836755c064 100644 --- a/gtk2_ardour/SConscript +++ b/gtk2_ardour/SConscript @@ -6,8 +6,8 @@ import glob Import('env install_prefix final_prefix config_prefix libraries i18n ardour_version') -gtkardour = env.Copy() -gtkmmtests = env.Copy() +gtkardour = env.Clone() +gtkmmtests = env.Clone() # # this defines the version number of the GTK interface to ardour @@ -409,7 +409,7 @@ my_subst_dict = { } keybindings_dict = { } -if gtkardour['GTKOSX'] and gtkardour['NATIVE_OSX_KEYS']: +if gtkardour['GTKOSX']: # # Command(Meta), Alt(Mod1), Ctrl, Shift # **** as of february 4th 2008, OUR VERSION OF ***** @@ -487,6 +487,7 @@ env.Alias('install', env.Install(os.path.join(install_prefix, 'share', 'ardour3' env.Alias('install', env.Install(os.path.join(install_prefix, 'share', 'ardour3', 'pixmaps'), pixmap_files)) env.Alias('install', env.Install(os.path.join(install_prefix, 'share', 'ardour3', 'icons'), icon_files)) env.Alias ('version', gtkardour.VersionBuild(['version.cc','version.h'], [])) +env.Alias ('version', gtkardour.VersionBuild(['version.cc','version.h'], [])) # This will install icons and MIME type as per freedesktop.org specs. # if env['FREEDESKTOP']: diff --git a/gtk2_ardour/actions.cc b/gtk2_ardour/actions.cc index f25dc1c9b2..fcfc6d75ce 100644 --- a/gtk2_ardour/actions.cc +++ b/gtk2_ardour/actions.cc @@ -162,6 +162,50 @@ struct SortActionsByLabel { } }; +void +ActionManager::get_all_actions (vector& groups, vector& names, vector& bindings) +{ + /* the C++ API for functions used here appears to be broken in + gtkmm2.6, so we fall back to the C level. + */ + + GList* list = gtk_ui_manager_get_action_groups (ui_manager->gobj()); + GList* node; + GList* acts; + + for (node = list; node; node = g_list_next (node)) { + + GtkActionGroup* group = (GtkActionGroup*) node->data; + + /* first pass: collect them all */ + + typedef std::list > action_list; + action_list the_acts; + + for (acts = gtk_action_group_list_actions (group); acts; acts = g_list_next (acts)) { + GtkAction* action = (GtkAction*) acts->data; + the_acts.push_back (Glib::wrap (action, true)); + } + + /* now sort by label */ + + SortActionsByLabel cmp; + the_acts.sort (cmp); + + for (action_list::iterator a = the_acts.begin(); a != the_acts.end(); ++a) { + + string accel_path = (*a)->get_accel_path (); + + groups.push_back (gtk_action_group_get_name(group)); + names.push_back (accel_path.substr (accel_path.find_last_of ('/') + 1)); + + AccelKey key; + lookup_entry (accel_path, key); + bindings.push_back (AccelKey (key.get_key(), Gdk::ModifierType (key.get_mod()))); + } + } +} + void ActionManager::get_all_actions (vector& names, vector& paths, vector& keys, vector& bindings) { @@ -226,6 +270,19 @@ ActionManager::get_widget (const char * name) return ui_manager->get_widget (name); } +RefPtr +ActionManager::get_action (const char* path) +{ + GtkAction* _act; + RefPtr act; + + if ((_act = gtk_ui_manager_get_action (ui_manager->gobj(), path)) != 0) { + return Glib::wrap (_act, true); + } + + return act; +} + RefPtr ActionManager::get_action (const char* group_name, const char* action_name) { diff --git a/gtk2_ardour/actions.h b/gtk2_ardour/actions.h index e05f3194bd..d8b2c64eda 100644 --- a/gtk2_ardour/actions.h +++ b/gtk2_ardour/actions.h @@ -70,6 +70,7 @@ class ActionManager static Gtk::Widget* get_widget (const char * name); static Glib::RefPtr get_action (const char* group, const char* name); + static Glib::RefPtr get_action (const char* path); static void add_action_group (Glib::RefPtr); @@ -100,6 +101,10 @@ class ActionManager std::vector& keys, std::vector& bindings); + static void get_all_actions (std::vector& groups, + std::vector& paths, + std::vector& bindings); + static void uncheck_toggleaction (const char * actionname); }; diff --git a/gtk2_ardour/analysis_window.cc b/gtk2_ardour/analysis_window.cc index 8f84febbba..b76a1b356e 100644 --- a/gtk2_ardour/analysis_window.cc +++ b/gtk2_ardour/analysis_window.cc @@ -262,7 +262,8 @@ AnalysisWindow::analyze_data (Gtk::Button *button) continue; RouteUI *rui = dynamic_cast(*i); - + int n_inputs = rui->route()->n_inputs().n_audio(); // FFT is audio only + // Busses don't have playlists, so we need to check that we actually are working with a playlist if (!pl || !rui) continue; @@ -275,29 +276,31 @@ AnalysisWindow::analyze_data (Gtk::Button *button) for (std::list::iterator j = ts.begin(); j != ts.end(); ++j) { - nframes_t i = 0; int n; - - while ( i < (*j).length() ) { - // TODO: What about stereo+ channels? composite all to one, I guess + for (int channel = 0; channel < n_inputs; channel++) { + nframes_t x = 0; - n = fft_graph.windowSize(); + while ( x < (*j).length() ) { + // TODO: What about stereo+ channels? composite all to one, I guess - if (i + n >= (*j).length() ) { - n = (*j).length() - i; - } - - n = pl->read(buf, mixbuf, gain, (*j).start + i, n); - - if ( n < fft_graph.windowSize()) { - for (int j = n; j < fft_graph.windowSize(); j++) { - buf[j] = 0.0; + n = fft_graph.windowSize(); + + if (x + n >= (*j).length() ) { + n = (*j).length() - x; } + + n = pl->read(buf, mixbuf, gain, (*j).start + x, n, channel); + + if ( n < fft_graph.windowSize()) { + for (int j = n; j < fft_graph.windowSize(); j++) { + buf[j] = 0.0; + } + } + + res->analyzeWindow(buf); + + x += n; } - - res->analyzeWindow(buf); - - i += n; } } } else if (source_selection_regions_rb.get_active()) { @@ -316,28 +319,36 @@ AnalysisWindow::analyze_data (Gtk::Button *button) continue; // cerr << " - " << (*j)->region().name() << ": " << (*j)->region().length() << " samples starting at " << (*j)->region().position() << endl; - nframes_t i = 0; int n; + for (int channel = 0; channel < n_inputs; channel++) { - while ( i < arv->region()->length() ) { - // TODO: What about stereo+ channels? composite all to one, I guess + nframes_t x = 0; - n = fft_graph.windowSize(); - if (i + n >= arv->region()->length() ) { - n = arv->region()->length() - i; - } + nframes_t length = arv->region()->length(); - n = arv->audio_region()->read_at(buf, mixbuf, gain, arv->region()->position() + i, n); - - if ( n < fft_graph.windowSize()) { - for (int j = n; j < fft_graph.windowSize(); j++) { - buf[j] = 0.0; + while ( x < length ) { + // TODO: What about stereo+ channels? composite all to one, I guess + + n = fft_graph.windowSize(); + if (x + n >= length ) { + n = length - x; } + + n = arv->audio_region()->read_at(buf, mixbuf, gain, arv->region()->position() + x, n, channel); + + if (n == 0) + break; + + if ( n < fft_graph.windowSize()) { + for (int j = n; j < fft_graph.windowSize(); j++) { + buf[j] = 0.0; + } + } + + res->analyzeWindow(buf); + + x += n; } - - res->analyzeWindow(buf); - - i += n; } // cerr << "Found: " << (*j)->get_item_name() << endl; diff --git a/gtk2_ardour/ardour-sae.menus b/gtk2_ardour/ardour-sae.menus index dc9d7d1b5f..c2721f2a29 100644 --- a/gtk2_ardour/ardour-sae.menus +++ b/gtk2_ardour/ardour-sae.menus @@ -326,6 +326,7 @@ +<<<<<<< .working @@ -339,6 +340,21 @@ +======= + + + + + + + + + + + + + +>>>>>>> .merge-right.r3622 diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus index e9b4800ae9..8e316de05c 100644 --- a/gtk2_ardour/ardour.menus +++ b/gtk2_ardour/ardour.menus @@ -56,7 +56,6 @@ - @@ -82,6 +81,8 @@ + + @@ -251,6 +252,14 @@ + + + + + + + + @@ -325,19 +334,38 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -450,6 +478,7 @@ + @@ -536,7 +565,7 @@ - + diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 8ca22b2dd5..1e55d2be1f 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -72,6 +73,8 @@ #include #include +typedef uint64_t microseconds_t; + #include "actions.h" #include "ardour_ui.h" #include "public_editor.h" @@ -88,6 +91,8 @@ #include "gui_thread.h" #include "theme_manager.h" #include "bundle_manager.h" +#include "gain_meter.h" +#include "route_time_axis.h" #include "i18n.h" @@ -114,10 +119,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[]) preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true), postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true), - /* adjuster table */ - - adjuster_table (3, 3), - /* preroll stuff */ preroll_button (_("pre\nroll")), @@ -129,14 +130,14 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[]) /* transport */ - roll_controllable ("transport roll", *this, TransportControllable::Roll), - stop_controllable ("transport stop", *this, TransportControllable::Stop), - goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart), - goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd), - auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop), - play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection), - rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable), - shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl), + roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)), + stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)), + goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)), + goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)), + auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)), + play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)), + rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)), + shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)), shuttle_controller_binding_proxy (shuttle_controllable), roll_button (roll_controllable), @@ -210,8 +211,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[]) last_speed_displayed = -1.0f; ignore_dual_punch = false; - last_configure_time.tv_sec = 0; - last_configure_time.tv_usec = 0; + last_configure_time= 0; shuttle_grabbed = false; shuttle_fract = 0.0; @@ -220,8 +220,9 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[]) shuttle_style_menu = 0; shuttle_unit_menu = 0; - gettimeofday (&last_peak_grab, 0); - gettimeofday (&last_shuttle_request, 0); + // We do not have jack linked in yet so; + + last_shuttle_request = last_peak_grab = 0; // get_microseconds(); ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler)); ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler)); @@ -249,6 +250,9 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[]) Config->set_current_owner (ConfigVariableBase::Interface); setup_profile (); + GainMeter::setup_slider_pix (); + RouteTimeAxisView::setup_slider_pix (); + } catch (failed_constructor& err) { error << _("could not initialize Ardour.") << endmsg; // pass it on up @@ -417,21 +421,15 @@ ARDOUR_UI::pop_back_splash () gint ARDOUR_UI::configure_timeout () { - struct timeval now; - struct timeval diff; - - if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) { + if (last_configure_time == 0) { /* no configure events yet */ return TRUE; } - gettimeofday (&now, 0); - timersub (&now, &last_configure_time, &diff); - /* force a gap of 0.5 seconds since the last configure event */ - if (diff.tv_sec == 0 && diff.tv_usec < 500000) { + if (get_microseconds() - last_configure_time < 500000) { return TRUE; } else { have_configure_timeout = false; @@ -444,7 +442,7 @@ gboolean ARDOUR_UI::configure_handler (GdkEventConfigure* conf) { if (have_configure_timeout) { - gettimeofday (&last_configure_time, 0); + last_configure_time = get_microseconds(); } else { Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100); have_configure_timeout = true; @@ -459,28 +457,28 @@ ARDOUR_UI::set_transport_controllable_state (const XMLNode& node) const XMLProperty* prop; if ((prop = node.property ("roll")) != 0) { - roll_controllable.set_id (prop->value()); + roll_controllable->set_id (prop->value()); } if ((prop = node.property ("stop")) != 0) { - stop_controllable.set_id (prop->value()); + stop_controllable->set_id (prop->value()); } if ((prop = node.property ("goto_start")) != 0) { - goto_start_controllable.set_id (prop->value()); + goto_start_controllable->set_id (prop->value()); } if ((prop = node.property ("goto_end")) != 0) { - goto_end_controllable.set_id (prop->value()); + goto_end_controllable->set_id (prop->value()); } if ((prop = node.property ("auto_loop")) != 0) { - auto_loop_controllable.set_id (prop->value()); + auto_loop_controllable->set_id (prop->value()); } if ((prop = node.property ("play_selection")) != 0) { - play_selection_controllable.set_id (prop->value()); + play_selection_controllable->set_id (prop->value()); } if ((prop = node.property ("rec")) != 0) { - rec_controllable.set_id (prop->value()); + rec_controllable->set_id (prop->value()); } if ((prop = node.property ("shuttle")) != 0) { - shuttle_controllable.set_id (prop->value()); + shuttle_controllable->set_id (prop->value()); } } @@ -490,21 +488,21 @@ ARDOUR_UI::get_transport_controllable_state () XMLNode* node = new XMLNode(X_("TransportControllables")); char buf[64]; - roll_controllable.id().print (buf, sizeof (buf)); + roll_controllable->id().print (buf, sizeof (buf)); node->add_property (X_("roll"), buf); - stop_controllable.id().print (buf, sizeof (buf)); + stop_controllable->id().print (buf, sizeof (buf)); node->add_property (X_("stop"), buf); - goto_start_controllable.id().print (buf, sizeof (buf)); + goto_start_controllable->id().print (buf, sizeof (buf)); node->add_property (X_("goto_start"), buf); - goto_end_controllable.id().print (buf, sizeof (buf)); + goto_end_controllable->id().print (buf, sizeof (buf)); node->add_property (X_("goto_end"), buf); - auto_loop_controllable.id().print (buf, sizeof (buf)); + auto_loop_controllable->id().print (buf, sizeof (buf)); node->add_property (X_("auto_loop"), buf); - play_selection_controllable.id().print (buf, sizeof (buf)); + play_selection_controllable->id().print (buf, sizeof (buf)); node->add_property (X_("play_selection"), buf); - rec_controllable.id().print (buf, sizeof (buf)); + rec_controllable->id().print (buf, sizeof (buf)); node->add_property (X_("rec"), buf); - shuttle_controllable.id().print (buf, sizeof (buf)); + shuttle_controllable->id().print (buf, sizeof (buf)); node->add_property (X_("shuttle"), buf); return *node; @@ -544,13 +542,22 @@ ARDOUR_UI::save_ardour_state () gint ARDOUR_UI::autosave_session () { - if (!Config->get_periodic_safety_backups()) + if (g_main_depth() > 1) { + /* inside a recursive main loop, + give up because we may not be able to + take a lock. + */ return 1; - - if (session) { - session->maybe_write_autosave(); } + if (!Config->get_periodic_safety_backups()) { + return 1; + } + + if (session) { + session->maybe_write_autosave(); + } + return 1; } @@ -796,8 +803,7 @@ ARDOUR_UI::ask_about_saving_session (const string & what) prompt_label.set_name (X_("PrompterLabel")); prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP); - dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP) -; + dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP); dhbox.set_homogeneous (false); dhbox.pack_start (*dimage, false, false, 5); dhbox.pack_start (prompt_label, true, false, 5); @@ -812,9 +818,6 @@ ARDOUR_UI::ask_about_saving_session (const string & what) prompt_label.show(); dimage->show(); window.show(); - - save_the_session = 0; - window.set_keep_above (true); window.present (); @@ -1152,33 +1155,6 @@ ARDOUR_UI::open_recent_session () } } -bool -ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) -{ - struct stat statbuf; - - if (stat (info.filename.c_str(), &statbuf) != 0) { - return false; - } - - if (!S_ISDIR(statbuf.st_mode)) { - return false; - } - - // XXX Portability - - string session_file = info.filename; - session_file += '/'; - session_file += Glib::path_get_basename (info.filename); - session_file += ".ardour"; - - if (stat (session_file.c_str(), &statbuf) != 0) { - return false; - } - - return S_ISREG (statbuf.st_mode); -} - bool ARDOUR_UI::check_audioengine () { @@ -1401,6 +1377,34 @@ ARDOUR_UI::transport_goto_zero () } } +void +ARDOUR_UI::transport_goto_wallclock () +{ + if (session && editor) { + + time_t now; + struct tm tmnow; + nframes64_t frames; + + time (&now); + localtime_r (&now, &tmnow); + + frames = tmnow.tm_hour * (60 * 60 * session->frame_rate()); + frames += tmnow.tm_min * (60 * session->frame_rate()); + frames += tmnow.tm_sec * session->frame_rate(); + + session->request_locate (frames); + + /* force displayed area in editor to start no matter + what "follow playhead" setting is. + */ + + if (editor) { + editor->reset_x_origin (frames - (editor->current_page_frames()/2)); + } + } +} + void ARDOUR_UI::transport_goto_end () { @@ -1916,17 +1920,6 @@ ARDOUR_UI::save_state_canfail (string name) return 0; } -void -ARDOUR_UI::restore_state (string name) -{ - if (session) { - if (name.length() == 0) { - name = session->name(); - } - session->restore_state (name); - } -} - void ARDOUR_UI::primary_clock_value_changed () { @@ -1951,37 +1944,6 @@ ARDOUR_UI::secondary_clock_value_changed () } } -void -ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w) -{ - if (session && dstream && dstream->record_enabled()) { - - Session::RecordState rs; - - rs = session->record_status (); - - switch (rs) { - case Session::Disabled: - case Session::Enabled: - if (w->get_state() != STATE_SELECTED) { - w->set_state (STATE_SELECTED); - } - break; - - case Session::Recording: - if (w->get_state() != STATE_ACTIVE) { - w->set_state (STATE_ACTIVE); - } - break; - } - - } else { - if (w->get_state() != STATE_NORMAL) { - w->set_state (STATE_NORMAL); - } - } -} - void ARDOUR_UI::transport_rec_enable_blink (bool onoff) { @@ -2352,10 +2314,13 @@ ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be fontconfig_dialog(); if (!backend_audio_is_running) { - if (new_session_dialog->engine_control.setup_engine ()) { - new_session_dialog->hide (); + int ret = new_session_dialog->engine_control.setup_engine (); + if (ret < 0) { return false; - } + } else if (ret > 0) { + response = Gtk::RESPONSE_REJECT; + goto try_again; + } } if (create_engine ()) { @@ -2459,7 +2424,7 @@ ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be } } - } while (response == Gtk::RESPONSE_NONE); + } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT); done: show(); @@ -2861,8 +2826,11 @@ After cleanup, unused audio files will be moved to a \ } if (session->cleanup_sources (rep)) { + editor->finish_cleanup (); return; } + + editor->finish_cleanup (); checker.hide(); display_cleanup_results (rep, @@ -2876,8 +2844,6 @@ release an additional\n\ %4 %5bytes of disk space.\n" )); - - } void @@ -3024,7 +2990,6 @@ ARDOUR_UI::keyboard_settings () const void ARDOUR_UI::create_xrun_marker(nframes_t where) { - ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::create_xrun_marker), where)); editor->mouse_add_new_marker (where, false, true); } @@ -3039,6 +3004,8 @@ ARDOUR_UI::halt_on_xrun_message () void ARDOUR_UI::xrun_handler(nframes_t where) { + ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where)); + if (Config->get_create_xrun_marker() && session->actively_recording()) { create_xrun_marker(where); } diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 442d319f77..6be85f6a80 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -59,6 +59,7 @@ #include #include #include +#include #include "audio_clock.h" #include "ardour_dialog.h" @@ -152,7 +153,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI int save_state_canfail (string state_name = ""); void save_state (const string & state_name = ""); - void restore_state (string state_name = ""); static double gain_to_slider_position (ARDOUR::gain_t g); static ARDOUR::gain_t slider_position_to_gain (double pos); @@ -181,12 +181,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI static sigc::signal SuperRapidScreenUpdate; static sigc::signal Clock; - /* this is a helper function to centralize the (complex) logic for - blinking rec-enable buttons. - */ - - void rec_enable_button_blink (bool onoff, ARDOUR::AudioDiskstream *, Gtk::Widget *w); - void name_io_setup (ARDOUR::AudioEngine&, string&, ARDOUR::IO& io, bool in); static gint hide_and_quit (GdkEventAny *ev, ArdourDialog *); @@ -309,9 +303,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI Gtk::ToggleButton preroll_button; Gtk::ToggleButton postroll_button; - Gtk::Table transport_table; - Gtk::Table option_table; - int setup_windows (); void setup_transport (); void setup_clock (); @@ -324,7 +315,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI void finish(); int ask_about_saving_session (const string & why); - int save_the_session; /* periodic safety backup, to be precise */ gint autosave_session(); @@ -361,9 +351,11 @@ class ARDOUR_UI : public Gtkmm2ext::UI void manage_window (Gtk::Window&); AudioClock big_clock; - Gtk::Frame big_clock_frame; Gtk::Window* big_clock_window; + void float_big_clock (Gtk::Window* parent); + bool main_window_state_event_handler (GdkEventWindowState*, bool window_was_editor); + void update_transport_clocks (nframes_t pos); void record_state_changed (); @@ -412,14 +404,14 @@ class ARDOUR_UI : public Gtkmm2ext::UI ToggleType type; }; - TransportControllable roll_controllable; - TransportControllable stop_controllable; - TransportControllable goto_start_controllable; - TransportControllable goto_end_controllable; - TransportControllable auto_loop_controllable; - TransportControllable play_selection_controllable; - TransportControllable rec_controllable; - TransportControllable shuttle_controllable; + boost::shared_ptr roll_controllable; + boost::shared_ptr stop_controllable; + boost::shared_ptr goto_start_controllable; + boost::shared_ptr goto_end_controllable; + boost::shared_ptr auto_loop_controllable; + boost::shared_ptr play_selection_controllable; + boost::shared_ptr rec_controllable; + boost::shared_ptr shuttle_controllable; BindingProxy shuttle_controller_binding_proxy; void set_transport_controllable_state (const XMLNode&); @@ -589,6 +581,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI void transport_goto_zero (); void transport_goto_start (); void transport_goto_end (); + void transport_goto_wallclock (); void transport_stop (); void transport_stop_and_forget_capture (); void transport_record (bool roll); @@ -675,11 +668,11 @@ class ARDOUR_UI : public Gtkmm2ext::UI void flush_trash (); bool have_configure_timeout; - struct timeval last_configure_time; + ARDOUR::microseconds_t last_configure_time; gint configure_timeout (); - struct timeval last_peak_grab; - struct timeval last_shuttle_request; + ARDOUR::microseconds_t last_peak_grab; + ARDOUR::microseconds_t last_shuttle_request; bool have_disk_speed_dialog_displayed; void disk_speed_dialog_gone (int ignored_response, Gtk::MessageDialog*); @@ -698,9 +691,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI Gtk::MenuItem* jack_reconnect_item; Gtk::Menu* jack_bufsize_menu; - int make_session_clean (); - bool filter_ardour_session_dirs (const Gtk::FileFilter::Info&); - Glib::RefPtr common_actions; void editor_realized (); @@ -742,6 +732,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI void toggle_ShowTrackMeters (); void toggle_only_copy_imported_files (); void toggle_use_narrow_ms(); + void toggle_NameNewMarkers (); void toggle_rubberbanding_snaps_to_grid (); void toggle_auto_analyse_audio (); void toggle_TapeMachineMode(); diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc index b497d6ab32..568bfb54ed 100644 --- a/gtk2_ardour/ardour_ui2.cc +++ b/gtk2_ardour/ardour_ui2.cc @@ -773,17 +773,13 @@ ARDOUR_UI::set_shuttle_fract (double f) void ARDOUR_UI::use_shuttle_fract (bool force) { - struct timeval now; - struct timeval diff; + microseconds_t now = get_microseconds(); /* do not attempt to submit a motion-driven transport speed request more than once per process cycle. */ - gettimeofday (&now, 0); - timersub (&now, &last_shuttle_request, &diff); - - if (!force && (diff.tv_usec + (diff.tv_sec * 1000000)) < engine->usecs_per_cycle()) { + if (!force && (last_shuttle_request - now) < (microseconds_t) engine->usecs_per_cycle()) { return; } diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index 32b9f5adc7..f87ce85476 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -433,3 +433,24 @@ ARDOUR_UI::handle_locations_change (Location* ignored) } } } + +bool +ARDOUR_UI::main_window_state_event_handler (GdkEventWindowState* ev, bool window_was_editor) +{ + if (window_was_editor) { + + if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) && + (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) { + float_big_clock (editor); + } + + } else { + + if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) && + (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) { + float_big_clock (mixer); + } + } + + return false; +} diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index 7eb13892ee..504205dbf4 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -30,6 +30,7 @@ #include #include +#include #include "ardour_ui.h" #include "public_editor.h" @@ -73,6 +74,7 @@ ARDOUR_UI::create_editor () } editor->Realized.connect (mem_fun (*this, &ARDOUR_UI::editor_realized)); + editor->signal_window_state_event().connect (sigc::bind (mem_fun (*this, &ARDOUR_UI::main_window_state_event_handler), true)); return 0; } @@ -303,6 +305,9 @@ ARDOUR_UI::install_actions () act = ActionManager::register_action (transport_actions, X_("GotoEnd"), _("Goto End"), mem_fun(*this, &ARDOUR_UI::transport_goto_end)); ActionManager::session_sensitive_actions.push_back (act); ActionManager::transport_sensitive_actions.push_back (act); + act = ActionManager::register_action (transport_actions, X_("GotoWallClock"), _("Goto Wall Clock"), mem_fun(*this, &ARDOUR_UI::transport_goto_wallclock)); + ActionManager::session_sensitive_actions.push_back (act); + ActionManager::transport_sensitive_actions.push_back (act); act = ActionManager::register_action (transport_actions, X_("focus-on-clock"), _("Focus On Clock"), mem_fun(primary_clock, &AudioClock::focus)); ActionManager::session_sensitive_actions.push_back (act); @@ -460,6 +465,7 @@ ARDOUR_UI::install_actions () ActionManager::register_toggle_action (option_actions, X_("AutoAnalyseAudio"), _("Auto-analyse new audio"), mem_fun (*this, &ARDOUR_UI::toggle_auto_analyse_audio)); ActionManager::register_toggle_action (option_actions, X_("DefaultNarrowMS"), _("Use narrow mixer strips"), mem_fun (*this, &ARDOUR_UI::toggle_use_narrow_ms)); + ActionManager::register_toggle_action (option_actions, X_("NameNewMarkers"), _("Name New Markers"), mem_fun (*this, &ARDOUR_UI::toggle_NameNewMarkers)); RadioAction::Group denormal_group; @@ -864,3 +870,16 @@ ARDOUR_UI::setup_clock () manage_window (*big_clock_window); } + +void +ARDOUR_UI::float_big_clock (Gtk::Window* parent) +{ + if (big_clock_window) { + if (parent) { + big_clock_window->set_transient_for (*parent); + } else { + gtk_window_set_transient_for (big_clock_window->gobj(), (GtkWindow*) 0); + } + } +} + diff --git a/gtk2_ardour/ardour_ui_mixer.cc b/gtk2_ardour/ardour_ui_mixer.cc index dfc5d644b0..6373bc8b8c 100644 --- a/gtk2_ardour/ardour_ui_mixer.cc +++ b/gtk2_ardour/ardour_ui_mixer.cc @@ -41,6 +41,8 @@ ARDOUR_UI::create_mixer () return -1; } + mixer->signal_window_state_event().connect (bind (mem_fun (*this, &ARDOUR_UI::main_window_state_event_handler), false)); + return 0; } diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc index 75d33d9416..4c1aae1583 100644 --- a/gtk2_ardour/ardour_ui_options.cc +++ b/gtk2_ardour/ardour_ui_options.cc @@ -587,6 +587,12 @@ ARDOUR_UI::toggle_use_narrow_ms() ActionManager::toggle_config_state ("options", "DefaultNarrowMS", &Configuration::set_default_narrow_ms, &Configuration::get_default_narrow_ms); } +void +ARDOUR_UI::toggle_NameNewMarkers() +{ + ActionManager::toggle_config_state ("options", "NameNewMarkers", &Configuration::set_name_new_markers, &Configuration::get_name_new_markers); +} + void ARDOUR_UI::toggle_rubberbanding_snaps_to_grid () { diff --git a/gtk2_ardour/au_pluginui.mm b/gtk2_ardour/au_pluginui.mm index ab14d4aafd..977e5762a7 100644 --- a/gtk2_ardour/au_pluginui.mm +++ b/gtk2_ardour/au_pluginui.mm @@ -518,6 +518,8 @@ AUPluginUI::parent_cocoa_window () return -1; } + [win setAutodisplay:YES]; // turn of GTK stuff for this window + Gtk::Container* toplevel = get_toplevel(); if (!toplevel || !toplevel->is_toplevel()) { @@ -530,6 +532,7 @@ AUPluginUI::parent_cocoa_window () NSView* view = gdk_quartz_window_get_nsview (low_box.get_window()->gobj()); + [view setFrame:packFrame]; [view addSubview:packView]; diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc index 5ce5159e72..a3dbc1d3d0 100644 --- a/gtk2_ardour/audio_clock.cc +++ b/gtk2_ardour/audio_clock.cc @@ -828,13 +828,15 @@ AudioClock::field_key_release_event (GdkEventKey *ev, Field field) break; case GDK_Tab: + case GDK_Return: + case GDK_KP_Enter: move_on = true; break; case GDK_Escape: - case GDK_Return: - case GDK_KP_Enter: + key_entry_state = 0; clock_base.grab_focus (); + ChangeAborted(); /* EMIT SIGNAL */ return true; default: @@ -960,6 +962,13 @@ AudioClock::field_key_release_event (GdkEventKey *ev, Field field) } + //if user hit Enter, lose focus + switch (ev->keyval) { + case GDK_Return: + case GDK_KP_Enter: + clock_base.grab_focus (); + } + return true; } diff --git a/gtk2_ardour/audio_clock.h b/gtk2_ardour/audio_clock.h index 426b2f02fc..fe3eef30dc 100644 --- a/gtk2_ardour/audio_clock.h +++ b/gtk2_ardour/audio_clock.h @@ -61,6 +61,7 @@ class AudioClock : public Gtk::HBox void set_session (ARDOUR::Session *s); sigc::signal ValueChanged; + sigc::signal ChangeAborted; static sigc::signal ModeChanged; static std::vector clocks; diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index e66b184adb..3a269c04bc 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -78,9 +78,10 @@ AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView { } + AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, boost::shared_ptr r, double spu, - Gdk::Color& basic_color, TimeAxisViewItem::Visibility visibility) - : RegionView (parent, tv, r, spu, basic_color, visibility) + Gdk::Color& basic_color, bool recording, TimeAxisViewItem::Visibility visibility) + : RegionView (parent, tv, r, spu, basic_color, recording, visibility) , sync_mark(0) , zero_line(0) , fade_in_shape(0) @@ -213,7 +214,7 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfd) gain_line->reset (); - set_y_position_and_height (0, trackview.height); + set_y_position_and_height (0, trackview.current_height()); region_muted (); region_sync_changed (); @@ -264,6 +265,7 @@ void AudioRegionView::region_changed (Change what_changed) { ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionView::region_changed), what_changed)); + //cerr << "AudioRegionView::region_changed() called" << endl; RegionView::region_changed(what_changed); @@ -433,51 +435,6 @@ AudioRegionView::region_muted () } } -void -AudioRegionView::set_y_position_and_height (double y, double h) -{ - RegionView::set_y_position_and_height(y, h - 1); - - const uint32_t wcnt = waves.size(); - - _y_position = y; - _height = h; - - for (uint32_t n = 0; n < wcnt; ++n) { - double ht; - - if (h <= NAME_HIGHLIGHT_THRESH) { - ht = ((_height - 2 * wcnt) / (double) wcnt); - } else { - ht = (((_height - 2 * wcnt) - NAME_HIGHLIGHT_SIZE) / (double) wcnt); - } - - double const yoff = n * (ht + 1); - - waves[n]->property_height() = ht; - waves[n]->property_y() = _y_position + yoff + 2; - } - - if (gain_line) { - if ((_height / wcnt) < NAME_HIGHLIGHT_SIZE) { - gain_line->hide (); - } else { - if (_flags & EnvelopeVisible) { - gain_line->show (); - } - } - gain_line->set_y_position_and_height ((uint32_t) _y_position, (uint32_t) rint (_height - NAME_HIGHLIGHT_SIZE)); - } - - setup_fade_handle_positions (); - manage_zero_line (); - reset_fade_shapes (); - - if (name_text) { - name_text->raise_to_top(); - } -} - void AudioRegionView::setup_fade_handle_positions() { @@ -497,6 +454,52 @@ AudioRegionView::setup_fade_handle_positions() } } +void +AudioRegionView::set_y_position_and_height (double y, double h) +{ + RegionView::set_y_position_and_height (y, h - 1); + + /* XXX why is this code here */ + + _y_position = y; + _height = h; + + const uint32_t wcnt = waves.size(); + + for (uint32_t n=0; n < wcnt; ++n) { + gdouble ht; + + if ((h) < NAME_HIGHLIGHT_THRESH) { + ht = ((_height-2*wcnt) / (double) wcnt); + } else { + ht = (((_height-2*wcnt) - NAME_HIGHLIGHT_SIZE) / (double) wcnt); + } + + gdouble yoff = n * (ht+1); + + waves[n]->property_height() = ht; + waves[n]->property_y() = yoff + 2; + } + + if (gain_line) { + if ((_height/wcnt) < NAME_HIGHLIGHT_THRESH) { + gain_line->hide (); + } else { + if (_flags & EnvelopeVisible) { + gain_line->show (); + } + } + gain_line->set_y_position_and_height ((uint32_t) _y_position, (uint32_t) rint (_height - NAME_HIGHLIGHT_SIZE)); + } + + manage_zero_line (); + reset_fade_shapes (); + + if (name_text) { + name_text->raise_to_top(); + } +} + void AudioRegionView::manage_zero_line () { @@ -573,7 +576,7 @@ AudioRegionView::reset_fade_in_shape_width (nframes_t width) points = get_canvas_points ("fade in shape", npoints+3); - if (_height > NAME_HIGHLIGHT_THRESH) { + if (_height >= NAME_HIGHLIGHT_THRESH) { h = _height - NAME_HIGHLIGHT_SIZE; } else { h = _height; @@ -657,7 +660,7 @@ AudioRegionView::reset_fade_out_shape_width (nframes_t width) float curve[npoints]; audio_region()->fade_out()->curve().get_vector (0, audio_region()->fade_out()->back()->when, curve, npoints); - if (_height > NAME_HIGHLIGHT_THRESH) { + if (_height >= NAME_HIGHLIGHT_THRESH) { h = _height - NAME_HIGHLIGHT_SIZE; } else { h = _height; @@ -853,6 +856,7 @@ AudioRegionView::create_waves () if (audio_region()->audio_source(n)->peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), data_ready_connection)) { // cerr << "\tData is ready\n"; cerr << "\tData is ready\n"; + // cerr << "\tData is ready\n"; create_one_wave (n, true); } else { // cerr << "\tdata is not ready\n"; @@ -878,10 +882,10 @@ AudioRegionView::create_one_wave (uint32_t which, bool direct) uint32_t nwaves = std::min (nchans, audio_region()->n_channels()); gdouble ht; - if (trackview.height < NAME_HIGHLIGHT_SIZE) { - ht = ((trackview.height) / (double) nchans); + if (trackview.current_height() < NAME_HIGHLIGHT_THRESH) { + ht = ((trackview.current_height()) / (double) nchans); } else { - ht = ((trackview.height - NAME_HIGHLIGHT_SIZE) / (double) nchans); + ht = ((trackview.current_height() - NAME_HIGHLIGHT_SIZE) / (double) nchans); } gdouble yoff = which * ht; @@ -900,8 +904,15 @@ AudioRegionView::create_one_wave (uint32_t which, bool direct) wave->property_height() = (double) ht; wave->property_samples_per_unit() = samples_per_unit; wave->property_amplitude_above_axis() = _amplitude_above_axis; - wave->property_wave_color() = _region->muted() ? UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->canvasvar_WaveForm.get(), MUTED_ALPHA) : ARDOUR_UI::config()->canvasvar_WaveForm.get(); - wave->property_fill_color() = ARDOUR_UI::config()->canvasvar_WaveFormFill.get(); + + if (_recregion) { + wave->property_wave_color() = _region->muted() ? UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->canvasvar_RecWaveForm.get(), MUTED_ALPHA) : ARDOUR_UI::config()->canvasvar_RecWaveForm.get(); + wave->property_fill_color() = ARDOUR_UI::config()->canvasvar_RecWaveFormFill.get(); + } else { + wave->property_wave_color() = _region->muted() ? UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->canvasvar_WaveForm.get(), MUTED_ALPHA) : ARDOUR_UI::config()->canvasvar_WaveForm.get(); + wave->property_fill_color() = ARDOUR_UI::config()->canvasvar_WaveFormFill.get(); + } + wave->property_clip_color() = ARDOUR_UI::config()->canvasvar_WaveFormClip.get(); wave->property_zero_color() = ARDOUR_UI::config()->canvasvar_ZeroLine.get(); wave->property_region_start() = _region->start(); @@ -986,7 +997,7 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev) /* compute vertical fractional position */ - y = 1.0 - ((y - _y_position) / (_height - NAME_HIGHLIGHT_SIZE)); + y = 1.0 - (y / (trackview.current_height() - NAME_HIGHLIGHT_SIZE)); /* map using gain line */ @@ -1275,16 +1286,31 @@ AudioRegionView::set_frame_color () } } } else { - UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_FrameBase.get(), &r, &g, &b, &a); - frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, fill_opacity ? fill_opacity : a); + if (_recregion) { + UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_RecordingRect.get(), &r, &g, &b, &a); + frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, a); - for (vector::iterator w = waves.begin(); w != waves.end(); ++w) { - if (_region->muted()) { - (*w)->property_wave_color() = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->canvasvar_WaveForm.get(), MUTED_ALPHA); - } else { - (*w)->property_wave_color() = ARDOUR_UI::config()->canvasvar_WaveForm.get(); - (*w)->property_fill_color() = ARDOUR_UI::config()->canvasvar_WaveFormFill.get(); + for (vector::iterator w = waves.begin(); w != waves.end(); ++w) { + if (_region->muted()) { + (*w)->property_wave_color() = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->canvasvar_RecWaveForm.get(), MUTED_ALPHA); + } else { + (*w)->property_wave_color() = ARDOUR_UI::config()->canvasvar_RecWaveForm.get(); + (*w)->property_fill_color() = ARDOUR_UI::config()->canvasvar_RecWaveFormFill.get(); + } + } + } else { + UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_FrameBase.get(), &r, &g, &b, &a); + frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, fill_opacity ? fill_opacity : a); + + for (vector::iterator w = waves.begin(); w != waves.end(); ++w) { + if (_region->muted()) { + (*w)->property_wave_color() = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->canvasvar_WaveForm.get(), MUTED_ALPHA); + } else { + (*w)->property_wave_color() = ARDOUR_UI::config()->canvasvar_WaveForm.get(); + (*w)->property_fill_color() = ARDOUR_UI::config()->canvasvar_WaveFormFill.get(); + } } } } } + diff --git a/gtk2_ardour/audio_region_view.h b/gtk2_ardour/audio_region_view.h index 58e3c7fce6..d93534cff7 100644 --- a/gtk2_ardour/audio_region_view.h +++ b/gtk2_ardour/audio_region_view.h @@ -54,6 +54,14 @@ class AudioRegionView : public RegionView double initial_samples_per_unit, Gdk::Color& basic_color); + AudioRegionView (ArdourCanvas::Group *, + RouteTimeAxisView&, + boost::shared_ptr, + double samples_per_unit, + Gdk::Color& basic_color, + bool recording, + TimeAxisViewItem::Visibility); + AudioRegionView (const AudioRegionView& other); AudioRegionView (const AudioRegionView& other, boost::shared_ptr); @@ -108,13 +116,6 @@ class AudioRegionView : public RegionView to the TimeAxisViewItem parent class */ - AudioRegionView (ArdourCanvas::Group *, - RouteTimeAxisView&, - boost::shared_ptr, - double samples_per_unit, - Gdk::Color& basic_color, - TimeAxisViewItem::Visibility); - enum Flags { EnvelopeVisible = 0x1, WaveformVisible = 0x4, diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc index 08ac532319..0e3dda0bd6 100644 --- a/gtk2_ardour/audio_streamview.cc +++ b/gtk2_ardour/audio_streamview.cc @@ -112,7 +112,7 @@ AudioStreamView::set_amplitude_above_axis (gdouble app) } RegionView* -AudioStreamView::add_region_view_internal (boost::shared_ptr r, bool wait_for_waves) +AudioStreamView::add_region_view_internal (boost::shared_ptr r, bool wait_for_waves, bool recording) { AudioRegionView *region_view = 0; @@ -142,8 +142,13 @@ AudioStreamView::add_region_view_internal (boost::shared_ptr r, bool wai switch (_trackview.audio_track()->mode()) { case Normal: - region_view = new AudioRegionView (canvas_group, _trackview, region, + if (recording) { + region_view = new AudioRegionView (canvas_group, _trackview, region, + _samples_per_unit, region_color, recording, TimeAxisViewItem::Visibility(TimeAxisViewItem::ShowFrame | TimeAxisViewItem::HideFrameRight)); + } else { + region_view = new AudioRegionView (canvas_group, _trackview, region, _samples_per_unit, region_color); + } break; case Destructive: region_view = new TapeAudioRegionView (canvas_group, _trackview, region, @@ -159,7 +164,6 @@ AudioStreamView::add_region_view_internal (boost::shared_ptr r, bool wai region_view->set_amplitude_above_axis(_amplitude_above_axis); region_views.push_front (region_view); - /* if its the special single-sample length that we use for rec-regions, make it insensitive to events */ @@ -456,7 +460,7 @@ AudioStreamView::redisplay_diskstream () for (RegionViewList::iterator j = copy.begin(); j != copy.end(); ++j) { (*j)->enable_display(true); - (*j)->set_y_position_and_height(0, height); + (*j)->set_height (height); region_layered (*j); } } @@ -497,7 +501,7 @@ AudioStreamView::set_waveform_scale (WaveformScale scale) void AudioStreamView::setup_rec_box () { - // cerr << _trackview.name() << " streamview SRB\n"; + //cerr << _trackview.name() << " streamview SRB region_views.size() = " << region_views.size() << endl; if (_trackview.session().transport_rolling()) { @@ -506,7 +510,6 @@ AudioStreamView::setup_rec_box () if (!rec_active && _trackview.session().record_status() == Session::Recording && _trackview.get_diskstream()->record_enabled()) { - if (_trackview.audio_track()->mode() == Normal && use_rec_regions && rec_regions.size() == rec_rects.size()) { /* add a new region, but don't bother if they set use_rec_regions mid-record */ @@ -578,8 +581,9 @@ AudioStreamView::setup_rec_box () rec_rect->property_x1() = xstart; rec_rect->property_y1() = 1.0; rec_rect->property_x2() = xend; - rec_rect->property_y2() = (double) _trackview.height - 1; - rec_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_RecordingRect.get(); + rec_rect->property_y2() = (double) _trackview.current_height() - 1; + rec_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_TimeAxisFrame.get(); + rec_rect->property_outline_what() = 0x1 | 0x2 | 0x4 | 0x8; rec_rect->property_fill_color_rgba() = fill_color; rec_rect->lower_to_bottom(); @@ -598,11 +602,9 @@ AudioStreamView::setup_rec_box () } else if (rec_active && (_trackview.session().record_status() != Session::Recording || !_trackview.get_diskstream()->record_enabled())) { - screen_update_connection.disconnect(); rec_active = false; rec_updating = false; - } } else { @@ -688,7 +690,6 @@ void AudioStreamView::update_rec_regions () { if (use_rec_regions) { - uint32_t n = 0; for (list,RegionView*> >::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) { @@ -726,7 +727,7 @@ AudioStreamView::update_rec_regions () if (origlen == 1) { /* our special initial length */ - add_region_view_internal (region, false); + add_region_view_internal (region, false, true); } /* also update rect */ @@ -751,7 +752,7 @@ AudioStreamView::update_rec_regions () if (origlen == 1) { /* our special initial length */ - add_region_view_internal (region, false); + add_region_view_internal (region, false, true); } /* also hide rect */ diff --git a/gtk2_ardour/audio_streamview.h b/gtk2_ardour/audio_streamview.h index 326a05f240..74868ea1a2 100644 --- a/gtk2_ardour/audio_streamview.h +++ b/gtk2_ardour/audio_streamview.h @@ -82,7 +82,7 @@ class AudioStreamView : public StreamView void rec_peak_range_ready (nframes_t start, nframes_t cnt, boost::weak_ptr src); void update_rec_regions (); - RegionView* add_region_view_internal (boost::shared_ptr, bool wait_for_waves); + RegionView* add_region_view_internal (boost::shared_ptr, bool wait_for_waves, bool recording = false); void remove_region_view (boost::weak_ptr ); void remove_audio_region_view (boost::shared_ptr ); @@ -106,10 +106,15 @@ class AudioStreamView : public StreamView CrossfadeViewList crossfade_views; bool crossfades_visible; + + std::list rec_data_ready_connections; + nframes_t last_rec_data_frame; + map, bool> rec_data_ready_map; + + bool outline_region; + Editing::WaveformShape _waveform_shape; Editing::WaveformScale _waveform_scale; - - map, bool> rec_data_ready_map; }; #endif /* __ardour_audio_streamview_h__ */ diff --git a/gtk2_ardour/audio_time_axis.h b/gtk2_ardour/audio_time_axis.h index 565d7cda9f..1b090d881e 100644 --- a/gtk2_ardour/audio_time_axis.h +++ b/gtk2_ardour/audio_time_axis.h @@ -86,6 +86,8 @@ class AudioTimeAxisView : public RouteTimeAxisView void first_idle (); + XMLNode* get_child_xml_node (const string & childname); + void set_waveform_shape (Editing::WaveformShape); void set_waveform_scale (Editing::WaveformScale); diff --git a/gtk2_ardour/automation_controller.cc b/gtk2_ardour/automation_controller.cc index dfbdb30ffe..0bf1482224 100644 --- a/gtk2_ardour/automation_controller.cc +++ b/gtk2_ardour/automation_controller.cc @@ -33,7 +33,7 @@ using namespace Gtk; AutomationController::AutomationController(boost::shared_ptr ac, Adjustment* adj) - : BarController(*adj, *ac) + : BarController(*adj, ac) , _ignore_change(false) , _controllable(ac) , _adjustment(adj) diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index 8c721c7e84..b112a9481e 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -154,17 +154,17 @@ AutomationLine::control_point_box_size () } void -AutomationLine::set_y_position_and_height (guint32 y, guint32 h) +AutomationLine::set_y_position_and_height (double y, double h) { bool changed = false; if (y != _y_position) { - _y_position = y; + _y_position = (guint32) floor (y); changed = true; } if (h != _height) { - _height = h; + _height = (guint32) floor (h); double const bsz = control_point_box_size(); diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h index 6ce548e55d..9e35903671 100644 --- a/gtk2_ardour/automation_line.h +++ b/gtk2_ardour/automation_line.h @@ -94,7 +94,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin void show (); void hide (); - void set_y_position_and_height (uint32_t, uint32_t); + void set_y_position_and_height (double, double); void set_verbose_cursor_uses_gain_mapping (bool yn); TimeAxisView& trackview; diff --git a/gtk2_ardour/automation_region_view.cc b/gtk2_ardour/automation_region_view.cc index f0dc23e043..0ba14398e6 100644 --- a/gtk2_ardour/automation_region_view.cc +++ b/gtk2_ardour/automation_region_view.cc @@ -53,7 +53,7 @@ AutomationRegionView::init (Gdk::Color& basic_color, bool wfd) reset_width_dependent_items ((double) _region->length() / samples_per_unit); - set_y_position_and_height (0, trackview.height); + set_height (trackview.current_height()); _region->StateChanged.connect (mem_fun(*this, &AutomationRegionView::region_changed)); @@ -90,8 +90,8 @@ AutomationRegionView::add_automation_event (GdkEvent* event, nframes_t when, dou /* compute vertical fractional position */ - const double height = trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 2; - y = 1.0 - (y / height); + const double h = trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 2; + y = 1.0 - (y / h); /* map using line */ diff --git a/gtk2_ardour/automation_streamview.cc b/gtk2_ardour/automation_streamview.cc index d068c51e5e..5803d283dc 100644 --- a/gtk2_ardour/automation_streamview.cc +++ b/gtk2_ardour/automation_streamview.cc @@ -70,7 +70,7 @@ AutomationStreamView::~AutomationStreamView () RegionView* -AutomationStreamView::add_region_view_internal (boost::shared_ptr region, bool wfd) +AutomationStreamView::add_region_view_internal (boost::shared_ptr region, bool wfd, bool recording) { if ( ! region) { cerr << "No region" << endl; diff --git a/gtk2_ardour/automation_streamview.h b/gtk2_ardour/automation_streamview.h index c5eac37021..5eebfaf28d 100644 --- a/gtk2_ardour/automation_streamview.h +++ b/gtk2_ardour/automation_streamview.h @@ -51,15 +51,16 @@ class AutomationStreamView : public StreamView void redisplay_diskstream (); - inline double contents_height() const - { return (_trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 2); } + inline double contents_height() const { + return (_trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 2); + } private: void setup_rec_box (); void rec_data_range_ready (jack_nframes_t start, jack_nframes_t dur); void update_rec_regions (jack_nframes_t start, jack_nframes_t dur); - RegionView* add_region_view_internal (boost::shared_ptr, bool wait_for_data); + RegionView* add_region_view_internal (boost::shared_ptr, bool wait_for_data, bool recording = false); void display_region(AutomationRegionView* region_view); void color_handler (); diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc index 099a36c822..36d615453c 100644 --- a/gtk2_ardour/automation_time_axis.cc +++ b/gtk2_ardour/automation_time_axis.cc @@ -373,15 +373,19 @@ AutomationTimeAxisView::clear_clicked () } void -AutomationTimeAxisView::set_height (TrackHeight ht) +AutomationTimeAxisView::set_height (uint32_t h) { - uint32_t h = height_to_pixels (ht); bool changed = (height != (uint32_t) h) || first_call_to_set_height; if (first_call_to_set_height) first_call_to_set_height = false; + bool changed_between_small_and_normal = ( (h == hSmall || h == hSmaller) ^ (height == hSmall || height == hSmaller) ); - TimeAxisView::set_height (ht); + TimeAxisView* state_parent = get_parent_with_state (); + assert(state_parent); + XMLNode* xml_node = state_parent->get_automation_child_xml_node (_control->parameter()); + + TimeAxisView::set_height (h); _base_rect->property_y2() = h; if (_line) @@ -392,50 +396,16 @@ AutomationTimeAxisView::set_height (TrackHeight ht) _view->update_contents_y_position_and_height(); } - TimeAxisView* state_parent = get_parent_with_state (); - assert(state_parent); + char buf[32]; + snprintf (buf, sizeof (buf), "%u", height); + xml_node->add_property ("height", buf); - XMLNode* xml_node = state_parent->get_automation_child_xml_node(_control->parameter()); - assert(xml_node); - - switch (ht) { - case Largest: - xml_node->add_property ("track_height", "largest"); - break; - - case Large: - xml_node->add_property ("track_height", "large"); - break; - - case Larger: - xml_node->add_property ("track_height", "larger"); - break; - - case Normal: - xml_node->add_property ("track_height", "normal"); - break; - - case Smaller: - xml_node->add_property ("track_height", "smaller"); - break; - - case Small: - xml_node->add_property ("track_height", "small"); - break; - } - - switch (ht) { - case Large: - case Larger: - case Largest: - _controller->show (); - - case Normal: - if (ht == Normal) - _controller->hide(); + if (changed_between_small_and_normal || first_call_to_set_height) { + first_call_to_set_height = false; + if (h >= hNormal) { controls_table.remove (name_hbox); - + if (plugname) { if (plugname_packed) { controls_table.remove (*plugname); @@ -450,18 +420,13 @@ AutomationTimeAxisView::set_height (TrackHeight ht) hide_name_entry (); show_name_label (); name_hbox.show_all (); - + auto_button.show(); height_button.show(); clear_button.show(); hide_button.show_all(); - break; - - case Smaller: - _controller->hide(); - - case Small: + } else if (h >= hSmall) { controls_table.remove (name_hbox); if (plugname) { if (plugname_packed) { @@ -474,17 +439,17 @@ AutomationTimeAxisView::set_height (TrackHeight ht) hide_name_entry (); show_name_label (); name_hbox.show_all (); - + auto_button.hide(); height_button.hide(); clear_button.hide(); hide_button.hide(); - break; + } } if (changed) { /* only emit the signal if the height really changed */ - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */ } } @@ -900,10 +865,10 @@ AutomationTimeAxisView::color_handler () } } -void +int AutomationTimeAxisView::set_state (const XMLNode& node) { - TimeAxisView::set_state (node); + return TimeAxisView::set_state (node); XMLNodeList kids; XMLNodeConstIterator iter; @@ -947,7 +912,9 @@ void AutomationTimeAxisView::update_extra_xml_shown (bool editor_shown) { XMLNode* xml_node = get_state_node(); - xml_node->add_property ("shown", editor_shown ? "yes" : "no"); +// if (xml_node) { + xml_node->add_property ("shown", editor_shown ? "yes" : "no"); +// } } guint32 diff --git a/gtk2_ardour/automation_time_axis.h b/gtk2_ardour/automation_time_axis.h index 8ddd007a3c..fb56c400c7 100644 --- a/gtk2_ardour/automation_time_axis.h +++ b/gtk2_ardour/automation_time_axis.h @@ -71,7 +71,8 @@ class AutomationTimeAxisView : public TimeAxisView { ~AutomationTimeAxisView(); - void set_height (TimeAxisView::TrackHeight); + + void set_height (uint32_t); void set_samples_per_unit (double); std::string name() const { return _name; } @@ -94,7 +95,7 @@ class AutomationTimeAxisView : public TimeAxisView { bool paste (nframes_t, float times, Selection&, size_t nth); void reset_objects (PointSelection&); - void set_state (const XMLNode&); + int set_state (const XMLNode&); guint32 show_at (double y, int& nth, Gtk::VBox *parent); void hide (); diff --git a/gtk2_ardour/axis_view.h b/gtk2_ardour/axis_view.h index e64ef99b16..3a15e05c99 100644 --- a/gtk2_ardour/axis_view.h +++ b/gtk2_ardour/axis_view.h @@ -52,11 +52,8 @@ class AxisView : public virtual Selectable virtual string name() const = 0; virtual bool marked_for_display() const { return _marked_for_display; } - virtual void set_marked_for_display (bool yn) { - if (yn != _marked_for_display) { - _marked_for_display = yn; - } + _marked_for_display = yn; } sigc::signal Hiding; diff --git a/gtk2_ardour/bundle_manager.cc b/gtk2_ardour/bundle_manager.cc index 4dacce782f..8486c5c30f 100644 --- a/gtk2_ardour/bundle_manager.cc +++ b/gtk2_ardour/bundle_manager.cc @@ -61,7 +61,7 @@ BundleEditorMatrix::get_state (int r, std::string const & p) const uint32_t BundleEditorMatrix::n_rows () const { - return _bundle->nchannels (); + return _bundle->nchannels ().n_total(); } uint32_t diff --git a/gtk2_ardour/canvas_vars.h b/gtk2_ardour/canvas_vars.h index 44a710703b..530d323961 100644 --- a/gtk2_ardour/canvas_vars.h +++ b/gtk2_ardour/canvas_vars.h @@ -24,7 +24,6 @@ CANVAS_VARIABLE(canvasvar_EnteredControlPointOutline, "entered control point out CANVAS_VARIABLE(canvasvar_EnteredControlPointSelected, "entered control point selected") CANVAS_VARIABLE(canvasvar_EnteredGainLine, "entered gain line") CANVAS_VARIABLE(canvasvar_EnteredMarker, "entered marker") -CANVAS_VARIABLE(canvasvar_FrameBase, "region base") CANVAS_VARIABLE(canvasvar_FrameHandle, "frame handle") CANVAS_VARIABLE(canvasvar_GainLine, "gain line") CANVAS_VARIABLE(canvasvar_GainLineInactive, "gain line inactive") @@ -82,6 +81,8 @@ CANVAS_VARIABLE(canvasvar_RangeDragBarRect, "range drag bar rect") CANVAS_VARIABLE(canvasvar_RangeDragRect, "range drag rect") CANVAS_VARIABLE(canvasvar_RangeMarkerBar, "range marker bar") CANVAS_VARIABLE(canvasvar_RecordingRect, "recording rect") +CANVAS_VARIABLE(canvasvar_RecWaveFormFill, "recorded waveform fill") +CANVAS_VARIABLE(canvasvar_RecWaveForm, "recorded waveform outline") CANVAS_VARIABLE(canvasvar_RubberBandRect, "rubber band rect") CANVAS_VARIABLE(canvasvar_SelectedCrossfadeEditorLine, "selected crossfade editor line") CANVAS_VARIABLE(canvasvar_SelectedCrossfadeEditorWave, "selected crossfade editor wave") @@ -103,8 +104,9 @@ CANVAS_VARIABLE(canvasvar_TrimHandleLocked, "trim handle locked") CANVAS_VARIABLE(canvasvar_TrimHandle, "trim handle") CANVAS_VARIABLE(canvasvar_VerboseCanvasCursor, "verbose canvas cursor") CANVAS_VARIABLE(canvasvar_VestigialFrame, "vestigial frame") +CANVAS_VARIABLE(canvasvar_FrameBase, "region base") +CANVAS_VARIABLE(canvasvar_WaveForm, "waveform outline") CANVAS_VARIABLE(canvasvar_WaveFormClip, "clipped waveform") CANVAS_VARIABLE(canvasvar_WaveFormFill, "waveform fill") -CANVAS_VARIABLE(canvasvar_WaveForm, "waveform outline") CANVAS_VARIABLE(canvasvar_ZeroLine, "zero line") CANVAS_VARIABLE(canvasvar_ZoomRect, "zoom rect") diff --git a/gtk2_ardour/crossfade_view.cc b/gtk2_ardour/crossfade_view.cc index 22119721ff..1b5f4d886a 100644 --- a/gtk2_ardour/crossfade_view.cc +++ b/gtk2_ardour/crossfade_view.cc @@ -52,7 +52,7 @@ CrossfadeView::CrossfadeView (ArdourCanvas::Group *parent, : TimeAxisViewItem ("xfade" /*xf.name()*/, *parent, tv, spu, basic_color, xf->position(), - xf->length(), TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowFrame)), + xf->length(), false, TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowFrame)), crossfade (xf), left_view (lview), right_view (rview) @@ -69,7 +69,7 @@ CrossfadeView::CrossfadeView (ArdourCanvas::Group *parent, fade_out->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CrossfadeLine.get(); fade_out->property_width_pixels() = 1; - set_y_position_and_height (0, get_time_axis_view().height); + set_y_position_and_height (0, get_time_axis_view().current_height()); /* no frame around the xfade or overlap rects */ @@ -109,15 +109,12 @@ CrossfadeView::reset_width_dependent_items (double pixel_width) void CrossfadeView::set_y_position_and_height (double y, double h) { - if (h == TimeAxisView::hSmaller || h == TimeAxisView::hSmall) { - TimeAxisViewItem::set_y_position_and_height (y, h - 3 ); + if (h <= TimeAxisView::hSmaller) { + TimeAxisViewItem::set_y_position_and_height (y, h - 3); } else { TimeAxisViewItem::set_y_position_and_height (y, h - NAME_HIGHLIGHT_SIZE - 3 ); } - _y_position = y; - _height = h; - redraw_curves (); } @@ -163,8 +160,10 @@ CrossfadeView::redraw_curves () At "height - 3.0" the bottom of the crossfade touches the name highlight or the bottom of the track (if the track is either Small or Smaller. */ - double const tav_height = get_time_axis_view().height; - if (tav_height == TimeAxisView::hSmaller || tav_height == TimeAxisView::hSmall) { + + double tav_height = get_time_axis_view().current_height(); + if (tav_height == TimeAxisView::hSmaller || + tav_height == TimeAxisView::hSmall) { h = tav_height - 3.0; } else { h = tav_height - NAME_HIGHLIGHT_SIZE - 3.0; diff --git a/gtk2_ardour/editing.cc b/gtk2_ardour/editing.cc index 2874e69308..1e58fcddbc 100644 --- a/gtk2_ardour/editing.cc +++ b/gtk2_ardour/editing.cc @@ -17,7 +17,7 @@ */ -#include +#include #include #include "editing.h" diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 3d14d96178..ab8940874c 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -84,6 +84,7 @@ #include "gui_thread.h" #include "simpleline.h" #include "rhythm_ferret.h" +#include "actions.h" #ifdef FFT_ANALYSIS #include "analysis_window.h" @@ -266,6 +267,7 @@ Editor::Editor () clicked_control_point = 0; last_update_frame = 0; drag_info.item = 0; + drag_info.copied_location = 0; current_mixer_strip = 0; current_bbt_points = 0; @@ -350,6 +352,13 @@ Editor::Editor () select_new_marker = false; zoomed_to_region = false; rhythm_ferret = 0; + allow_vertical_scroll = false; + no_save_visual = false; + need_resize_line = false; + resize_line_y = 0; + old_resize_line_y = -1; + no_region_list_redisplay = false; + resize_idle_id = -1; _scrubbing = false; scrubbing_direction = 0; @@ -370,8 +379,6 @@ Editor::Editor () set_midi_edit_mode (MidiEditPencil, true); set_mouse_mode (MouseObject, true); - last_visual_state.frames_per_unit = 0; - frames_per_unit = 2048; /* too early to use reset_zoom () */ reset_hscrollbar_stepping (); @@ -818,6 +825,7 @@ Editor::Editor () ControlProtocol::ZoomIn.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), false)); ControlProtocol::ZoomOut.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), true)); ControlProtocol::ScrollTimeline.connect (mem_fun (*this, &Editor::control_scroll)); + BasicUI::AccessAction.connect (mem_fun (*this, &Editor::access_action)); Config->ParameterChanged.connect (mem_fun (*this, &Editor::parameter_changed)); Route::SyncOrderKeys.connect (mem_fun (*this, &Editor::sync_order_keys)); @@ -850,6 +858,16 @@ Editor::~Editor() delete time_canvas; time_canvas = 0; } + + if (track_canvas) { + delete track_canvas; + track_canvas = 0; + } + + if (time_canvas) { + delete time_canvas; + time_canvas = 0; + } } void @@ -971,10 +989,10 @@ Editor::zoom_adjustment_changed () if (fpu < 1.0) { fpu = 1.0; - zoom_range_clock.set ((nframes_t) floor (fpu * canvas_width)); + zoom_range_clock.set ((nframes64_t) floor (fpu * canvas_width)); } else if (fpu > session->current_end_frame() / canvas_width) { fpu = session->current_end_frame() / canvas_width; - zoom_range_clock.set ((nframes_t) floor (fpu * canvas_width)); + zoom_range_clock.set ((nframes64_t) floor (fpu * canvas_width)); } temporal_zoom (fpu); @@ -994,7 +1012,7 @@ Editor::control_scroll (float fraction) /* _control_scroll_target is an optional - it acts like a pointer to an nframes_t, with + it acts like a pointer to an nframes64_t, with a operator conversion to boolean to check that it has a value could possibly use playhead_cursor->current_frame to store the @@ -1007,12 +1025,12 @@ Editor::control_scroll (float fraction) _dragging_playhead = true; } - if ((fraction < 0.0f) && (*_control_scroll_target < (nframes_t) fabs(step))) { + if ((fraction < 0.0f) && (*_control_scroll_target < (nframes64_t) fabs(step))) { *_control_scroll_target = 0; } else if ((fraction > 0.0f) && (max_frames - *_control_scroll_target < step)) { *_control_scroll_target = max_frames - (current_page_frames()*2); // allow room for slop in where the PH is on the screen } else { - *_control_scroll_target += (nframes_t) floor (step); + *_control_scroll_target += (nframes64_t) floor (step); } /* move visuals, we'll catch up with it later */ @@ -1043,7 +1061,7 @@ Editor::control_scroll (float fraction) } bool -Editor::deferred_control_scroll (nframes_t target) +Editor::deferred_control_scroll (nframes64_t target) { session->request_locate (*_control_scroll_target, session->transport_rolling()); // reset for next stream @@ -1052,6 +1070,27 @@ Editor::deferred_control_scroll (nframes_t target) return false; } +void +Editor::access_action (std::string action_group, std::string action_item) +{ + if (!session) { + return; + } + + ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::access_action), action_group, action_item)); + + cout<< "OSC: Recieved: "<< action_item << endl; + + RefPtr act; + act = ActionManager::get_action( action_group.c_str(), action_item.c_str() ); + + if (act) { + act->activate(); + } + + +} + void Editor::on_realize () { @@ -1073,7 +1112,7 @@ Editor::stop_scrolling () } void -Editor::map_position_change (nframes_t frame) +Editor::map_position_change (nframes64_t frame) { ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame)); @@ -1086,7 +1125,7 @@ Editor::map_position_change (nframes_t frame) } void -Editor::center_screen (nframes_t frame) +Editor::center_screen (nframes64_t frame) { double page = canvas_width * frames_per_unit; @@ -1099,12 +1138,12 @@ Editor::center_screen (nframes_t frame) } void -Editor::center_screen_internal (nframes_t frame, float page) +Editor::center_screen_internal (nframes64_t frame, float page) { page /= 2; if (frame > page) { - frame -= (nframes_t) page; + frame -= (nframes64_t) page; } else { frame = 0; } @@ -1117,7 +1156,7 @@ Editor::handle_new_duration () { ENSURE_GUI_THREAD (mem_fun (*this, &Editor::handle_new_duration)); - nframes_t new_end = session->get_maximum_extent() + (nframes_t) floorf (current_page_frames() * 0.10f); + nframes64_t new_end = session->get_maximum_extent() + (nframes64_t) floorf (current_page_frames() * 0.10f); if (new_end > last_canvas_frame) { last_canvas_frame = new_end; @@ -1126,6 +1165,7 @@ Editor::handle_new_duration () } horizontal_adjustment.set_value (leftmost_frame/frames_per_unit); + //cerr << "Editor::handle_new_duration () called ha v:l:u:ps:lcf = " << horizontal_adjustment.get_value() << ":" << horizontal_adjustment.get_lower() << ":" << horizontal_adjustment.get_upper() << ":" << horizontal_adjustment.get_page_size() << ":" << last_canvas_frame << endl;//DEBUG } void @@ -1217,6 +1257,7 @@ Editor::connect_to_session (Session *t) zoom_range_clock.set_session (session); _playlist_selector->set_session (session); nudge_clock.set_session (session); + nudge_clock.set (session->frame_rate() * 5); // default of 5 seconds if (rhythm_ferret) { rhythm_ferret->set_session (session); @@ -1471,10 +1512,10 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i } void -Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, nframes_t frame) +Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, nframes64_t frame) { using namespace Menu_Helpers; - Menu* (Editor::*build_menu_function)(nframes_t); + Menu* (Editor::*build_menu_function)(nframes64_t); Menu *menu; switch (item_type) { @@ -1590,7 +1631,7 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, } Menu* -Editor::build_track_context_menu (nframes_t ignored) +Editor::build_track_context_menu (nframes64_t ignored) { using namespace Menu_Helpers; @@ -1602,7 +1643,7 @@ Editor::build_track_context_menu (nframes_t ignored) } Menu* -Editor::build_track_bus_context_menu (nframes_t ignored) +Editor::build_track_bus_context_menu (nframes64_t ignored) { using namespace Menu_Helpers; @@ -1614,7 +1655,7 @@ Editor::build_track_bus_context_menu (nframes_t ignored) } Menu* -Editor::build_track_region_context_menu (nframes_t frame) +Editor::build_track_region_context_menu (nframes64_t frame) { using namespace Menu_Helpers; MenuList& edit_items = track_region_context_menu.items(); @@ -1627,10 +1668,20 @@ Editor::build_track_region_context_menu (nframes_t frame) boost::shared_ptr pl; if ((ds = rtv->get_diskstream()) && ((pl = ds->playlist()))) { - Playlist::RegionList* regions = pl->regions_at ((nframes_t) floor ( (double)frame * ds->speed())); - for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { - add_region_context_items (rtv->view(), (*i), edit_items); + Playlist::RegionList* regions = pl->regions_at ((nframes64_t) floor ( (double)frame * ds->speed())); + + if (selection->regions.size() > 1) { + // there's already a multiple selection: just add a + // single region context menu that will act on all + // selected regions + boost::shared_ptr dummy_region; // = NULL + add_region_context_items (rtv->view(), dummy_region, edit_items); + } else { + for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { + add_region_context_items (rtv->view(), (*i), edit_items); + } } + delete regions; } } @@ -1641,7 +1692,7 @@ Editor::build_track_region_context_menu (nframes_t frame) } Menu* -Editor::build_track_crossfade_context_menu (nframes_t frame) +Editor::build_track_crossfade_context_menu (nframes64_t frame) { using namespace Menu_Helpers; MenuList& edit_items = track_crossfade_context_menu.items(); @@ -1667,10 +1718,17 @@ Editor::build_track_crossfade_context_menu (nframes_t frame) add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many); } - for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { - add_region_context_items (atv->audio_view(), (*i), edit_items); + if (selection->regions.size() > 1) { + // there's already a multiple selection: just add a + // single region context menu that will act on all + // selected regions + boost::shared_ptr dummy_region; // = NULL + add_region_context_items (atv->audio_view(), dummy_region, edit_items); + } else { + for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { + add_region_context_items (atv->audio_view(), (*i), edit_items); + } } - delete regions; } } @@ -1719,7 +1777,7 @@ Editor::analyze_range_selection() #endif /* FFT_ANALYSIS */ Menu* -Editor::build_track_selection_context_menu (nframes_t ignored) +Editor::build_track_selection_context_menu (nframes64_t ignored) { using namespace Menu_Helpers; MenuList& edit_items = track_selection_context_menu.items(); @@ -1820,16 +1878,18 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi if (region) { ar = boost::dynamic_pointer_cast (region); mr = boost::dynamic_pointer_cast (region); + + /* when this particular menu pops up, make the relevant region + become selected. + */ + + region_menu->signal_map_event().connect ( + bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr(region))); + + items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region))); + items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region))); } - /* when this particular menu pops up, make the relevant region - become selected. - */ - - region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr(region))); - - items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region))); - items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region))); items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top))); items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom))); items.push_back (SeparatorElem()); @@ -1851,49 +1911,61 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi sigc::connection fooc; - items.push_back (CheckMenuElem (_("Lock"))); - CheckMenuItem* region_lock_item = static_cast(&items.back()); - if (region->locked()) { - region_lock_item->set_active(); - } - region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock)); + if (region) { + items.push_back (CheckMenuElem (_("Lock"))); + CheckMenuItem* region_lock_item = static_cast(&items.back()); + if (region->locked()) { + region_lock_item->set_active(); + } + 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(&items.back()); + items.push_back (CheckMenuElem (_("Glue to Bars&Beats"))); + CheckMenuItem* bbt_glue_item = static_cast(&items.back()); - switch (region->positional_lock_style()) { - case Region::MusicTime: - bbt_glue_item->set_active (true); - break; - default: - bbt_glue_item->set_active (false); - break; - } + switch (region->positional_lock_style()) { + case Region::MusicTime: + bbt_glue_item->set_active (true); + break; + default: + bbt_glue_item->set_active (false); + break; + } - bbt_glue_item->signal_activate().connect (bind (mem_fun (*this, &Editor::set_region_lock_style), Region::MusicTime)); + 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(&items.back()); - fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute)); - if (region->muted()) { - fooc.block (true); - region_mute_item->set_active(); - fooc.block (false); - } - - if (!Profile->get_sae()) { - items.push_back (CheckMenuElem (_("Opaque"))); - CheckMenuItem* region_opaque_item = static_cast(&items.back()); - fooc = region_opaque_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_opaque)); - if (region->opaque()) { + items.push_back (CheckMenuElem (_("Mute"))); + CheckMenuItem* region_mute_item = static_cast(&items.back()); + fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute)); + if (region->muted()) { fooc.block (true); - region_opaque_item->set_active(); + region_mute_item->set_active(); fooc.block (false); } + + if (!Profile->get_sae()) { + items.push_back (CheckMenuElem (_("Opaque"))); + CheckMenuItem* region_opaque_item = static_cast(&items.back()); + fooc = region_opaque_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_opaque)); + if (region->opaque()) { + fooc.block (true); + region_opaque_item->set_active(); + fooc.block (false); + } + } + } else { + // multiple regions selected + // how should these act? + // here they toggle the property of all selected regions + + items.push_back (MenuElem (_("Lock"), mem_fun(*this, &Editor::toggle_region_lock))); + items.push_back (MenuElem (_("Mute"), mem_fun(*this, &Editor::toggle_region_mute))); + if (!Profile->get_sae()) { + items.push_back (MenuElem (_("Opaque"), mem_fun(*this, &Editor::toggle_region_opaque))); + } } items.push_back (CheckMenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize))); - if (region->at_natural_position()) { + if (region && region->at_natural_position()) { items.back().set_sensitive (false); } @@ -1985,7 +2057,7 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi items.push_back (MenuElem (_("Multi-Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true)))); items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track)))); items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region))); + items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_selected_regions))); /* OK, stick the region submenu at the top of the list, and then add the standard items. @@ -1996,7 +2068,7 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi */ string::size_type pos = 0; - string menu_item_name = region->name(); + string menu_item_name = (region) ? region->name() : _("Selected regions"); while ((pos = menu_item_name.find ("_", pos)) != string::npos) { menu_item_name.replace (pos, 1, "__"); @@ -2049,7 +2121,8 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items) items.push_back (MenuElem (_("Duplicate range"), bind (mem_fun(*this, &Editor::duplicate_dialog), false))); items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::create_named_selection))); items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection))); + items.push_back (MenuElem (_("Consolidate range"), bind (mem_fun(*this, &Editor::bounce_range_selection), true))); + items.push_back (MenuElem (_("Bounce range to region list"), bind (mem_fun(*this, &Editor::bounce_range_selection), false))); items.push_back (MenuElem (_("Export range"), mem_fun(*this, &Editor::export_selection))); } @@ -2199,8 +2272,9 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items) void Editor::set_snap_to (SnapType st) -{ +{ unsigned int snap_ind = (unsigned int)st; + snap_type = st; if (snap_ind > snap_type_strings.size() - 1) { @@ -2355,7 +2429,7 @@ Editor::set_state (const XMLNode& node) move (x, y); if (session && (prop = node.property ("playhead"))) { - nframes_t pos = atol (prop->value().c_str()); + nframes64_t pos = atol (prop->value().c_str()); playhead_cursor->set_position (pos); } else { playhead_cursor->set_position (0); @@ -2546,7 +2620,7 @@ Editor::get_state () node->add_property ("edit-point", enum_2_string (_edit_point)); - snprintf (buf, sizeof (buf), "%" PRIu32, playhead_cursor->current_frame); + snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame); node->add_property ("playhead", buf); node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no"); @@ -2614,17 +2688,17 @@ Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark) switch (snap_type) { case SnapToCDFrame: if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) { - start = (nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75); + start = (nframes64_t) ceil ((double) start / (one_second / 75)) * (one_second / 75); } else { - start = (nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75); + start = (nframes64_t) floor ((double) start / (one_second / 75)) * (one_second / 75); } break; case SnapToSMPTEFrame: if (((direction == 0) && (fmod((double)start, (double)session->frames_per_smpte_frame()) > (session->frames_per_smpte_frame() / 2))) || (direction > 0)) { - start = (nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame()); + start = (nframes64_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame()); } else { - start = (nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame()); + start = (nframes64_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame()); } break; @@ -2636,9 +2710,9 @@ Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark) start -= session->smpte_offset (); } if (((direction == 0) && (start % one_smpte_second > one_smpte_second / 2)) || direction > 0) { - start = (nframes_t) ceil ((double) start / one_smpte_second) * one_smpte_second; + start = (nframes64_t) ceil ((double) start / one_smpte_second) * one_smpte_second; } else { - start = (nframes_t) floor ((double) start / one_smpte_second) * one_smpte_second; + start = (nframes64_t) floor ((double) start / one_smpte_second) * one_smpte_second; } if (session->smpte_offset_negative()) @@ -2657,9 +2731,9 @@ Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark) start -= session->smpte_offset (); } if (((direction == 0) && (start % one_smpte_minute > one_smpte_minute / 2)) || direction > 0) { - start = (nframes_t) ceil ((double) start / one_smpte_minute) * one_smpte_minute; + start = (nframes64_t) ceil ((double) start / one_smpte_minute) * one_smpte_minute; } else { - start = (nframes_t) floor ((double) start / one_smpte_minute) * one_smpte_minute; + start = (nframes64_t) floor ((double) start / one_smpte_minute) * one_smpte_minute; } if (session->smpte_offset_negative()) { @@ -2671,17 +2745,17 @@ Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark) case SnapToSeconds: if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) { - start = (nframes_t) ceil ((double) start / one_second) * one_second; + start = (nframes64_t) ceil ((double) start / one_second) * one_second; } else { - start = (nframes_t) floor ((double) start / one_second) * one_second; + start = (nframes64_t) floor ((double) start / one_second) * one_second; } break; case SnapToMinutes: if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) { - start = (nframes_t) ceil ((double) start / one_minute) * one_minute; + start = (nframes64_t) ceil ((double) start / one_minute) * one_minute; } else { - start = (nframes_t) floor ((double) start / one_minute) * one_minute; + start = (nframes64_t) floor ((double) start / one_minute) * one_minute; } break; @@ -2758,7 +2832,7 @@ Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark) case SnapToRegionSync: case SnapToRegionBoundary: if (!region_boundary_cache.empty()) { - vector::iterator i; + vector::iterator i; if (direction > 0) { i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start); @@ -2808,7 +2882,7 @@ Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark) } double -Editor::snap_length_beats (nframes_t start) +Editor::snap_length_beats (nframes64_t start) { if (!session) { return 1.0; @@ -3685,6 +3759,8 @@ Editor::zoom_focus_selection_done () focus_type = ZoomFocusEdit; } else if (choice == _("Active Mark")) { focus_type = ZoomFocusEdit; + } else if (choice == _("Active Mark")) { + focus_type = ZoomFocusEdit; } else { focus_type = ZoomFocusMouse; } @@ -3923,10 +3999,10 @@ Editor::playlist_selector () const return *_playlist_selector; } -nframes_t -Editor::get_nudge_distance (nframes_t pos, nframes_t& next) +nframes64_t +Editor::get_nudge_distance (nframes64_t pos, nframes64_t& next) { - nframes_t ret; + nframes64_t ret; ret = nudge_clock.current_duration (pos); next = ret + 1; /* XXXX fix me */ @@ -3978,7 +4054,7 @@ Editor::playlist_deletion_dialog (boost::shared_ptr pl) } bool -Editor::audio_region_selection_covers (nframes_t where) +Editor::audio_region_selection_covers (nframes64_t where) { for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) { if ((*a)->region()->covers (where)) { @@ -3997,6 +4073,15 @@ Editor::prepare_for_cleanup () selection->clear_regions (); selection->clear_playlists (); + + no_region_list_redisplay = true; +} + +void +Editor::finish_cleanup () +{ + no_region_list_redisplay = false; + redisplay_regions (); } Location* @@ -4212,8 +4297,8 @@ Editor::maximise_editing_space () post_maximal_pane_position = edit_pane.get_width(); } - fullscreen(); + if(post_maximal_editor_width) { edit_pane.set_position (post_maximal_pane_position - abs(post_maximal_editor_width - pre_maximal_editor_width)); @@ -4318,7 +4403,7 @@ Editor::on_key_release_event (GdkEventKey* ev) } void -Editor::reset_x_origin (nframes_t frame) +Editor::reset_x_origin (nframes64_t frame) { queue_visual_change (frame); } @@ -4330,28 +4415,97 @@ Editor::reset_zoom (double fpu) } void -Editor::reposition_and_zoom (nframes_t frame, double fpu) +Editor::reposition_and_zoom (nframes64_t frame, double fpu) { + //cerr << "Editor::reposition_and_zoom () called ha v:l:u:ps:fpu = " << horizontal_adjustment.get_value() << ":" << horizontal_adjustment.get_lower() << ":" << horizontal_adjustment.get_upper() << ":" << horizontal_adjustment.get_page_size() << ":" << frames_per_unit << endl;//DEBUG reset_x_origin (frame); reset_zoom (fpu); + + if (!no_save_visual) { + undo_visual_stack.push_back (current_visual_state(false)); + } +} + +Editor::VisualState* +Editor::current_visual_state (bool with_tracks) +{ + VisualState* vs = new VisualState; + vs->y_position = vertical_adjustment.get_value(); + vs->frames_per_unit = frames_per_unit; + vs->leftmost_frame = leftmost_frame; + vs->zoom_focus = zoom_focus; + vs->zoomed_to_region = zoomed_to_region; + + if (with_tracks) { + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + vs->track_states.push_back (TAVState ((*i), &(*i)->get_state())); + } + } + + return vs; +} + +void +Editor::undo_visual_state () +{ + if (undo_visual_stack.empty()) { + return; + } + + VisualState* vs = undo_visual_stack.back(); + undo_visual_stack.pop_back(); + use_visual_state (*vs); + redo_visual_stack.push_back (vs); +} + +void +Editor::redo_visual_state () +{ + if (redo_visual_stack.empty()) { + return; + } + + VisualState* vs = redo_visual_stack.back(); + redo_visual_stack.pop_back(); + use_visual_state (*vs); + undo_visual_stack.push_back (vs); } void Editor::swap_visual_state () { - if (last_visual_state.frames_per_unit == 0) { - // never set - return; + if (undo_visual_stack.empty()) { + redo_visual_state (); + } else { + undo_visual_state (); + } +} + +void +Editor::use_visual_state (VisualState& vs) +{ + no_save_visual = true; + + vertical_adjustment.set_value (vs.y_position); + + set_zoom_focus (vs.zoom_focus); + reposition_and_zoom (vs.leftmost_frame, vs.frames_per_unit); + + for (list::iterator i = vs.track_states.begin(); i != vs.track_states.end(); ++i) { + TrackViewList::iterator t; + + /* check if the track still exists - it could have been deleted */ + + if ((t = find (track_views.begin(), track_views.end(), i->first)) != track_views.end()) { + (*t)->set_state (*(i->second)); + } } - /* note: the correct functionality here is very dependent on the ordering of - setting zoom focus, horizontal position and finally zoom. this is because - it is set_frames_per_unit() that overwrites last_visual_state. - */ - - set_zoom_focus (last_visual_state.zoom_focus); - reposition_and_zoom (last_visual_state.leftmost_frame, last_visual_state.frames_per_unit); - zoomed_to_region = false; + if (!vs.track_states.empty()) { + update_route_visibility (); + } + + no_save_visual = false; } void @@ -4381,10 +4535,6 @@ Editor::set_frames_per_unit (double fpu) if (fpu == frames_per_unit) { return; } - - last_visual_state.frames_per_unit = frames_per_unit; - last_visual_state.leftmost_frame = leftmost_frame; - last_visual_state.zoom_focus = zoom_focus; frames_per_unit = fpu; post_zoom (); @@ -4395,7 +4545,7 @@ Editor::post_zoom () { // convert fpu to frame count - nframes_t frames = (nframes_t) floor (frames_per_unit * canvas_width); + nframes64_t frames = (nframes64_t) floor (frames_per_unit * canvas_width); if (frames_per_unit != zoom_range_clock.current_duration()) { zoom_range_clock.set (frames); @@ -4424,11 +4574,11 @@ Editor::post_zoom () } void -Editor::queue_visual_change (nframes_t where) +Editor::queue_visual_change (nframes64_t where) { pending_visual_change.pending = VisualChange::Type (pending_visual_change.pending | VisualChange::TimeOrigin); pending_visual_change.time_origin = where; - + if (pending_visual_change.idle_handler_id < 0) { pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this); } @@ -4456,6 +4606,12 @@ int Editor::idle_visual_changer () { VisualChange::Type p = pending_visual_change.pending; + nframes64_t csf, cef; + + if (session) { + csf = session->current_start_frame(); + cef = session->current_end_frame() + (current_page_frames() / 24);// Add a little extra so we can see the end marker + } pending_visual_change.pending = (VisualChange::Type) 0; @@ -4469,17 +4625,26 @@ Editor::idle_visual_changer () } if (p & VisualChange::TimeOrigin) { - nframes_t time_origin = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit); + nframes64_t time_origin = (nframes64_t) floor (horizontal_adjustment.get_value() * frames_per_unit); + + /* if we seek beyond the current end of the canvas, move the end */ if (time_origin != pending_visual_change.time_origin) { + + if (horizontal_adjustment.get_upper() < pending_visual_change.time_origin) { + last_canvas_frame = (cef > (pending_visual_change.time_origin + current_page_frames())) ? cef : pending_visual_change.time_origin + current_page_frames(); + horizontal_adjustment.set_upper ((cef - csf) / frames_per_unit); + reset_scrolling_region (); + } + horizontal_adjustment.set_value (pending_visual_change.time_origin/frames_per_unit); } else { update_fixed_rulers(); redisplay_tempo (true); } } - pending_visual_change.idle_handler_id = -1; + pending_visual_change.idle_handler_id = -1; return 0; /* this is always a one-shot call */ } @@ -4550,7 +4715,7 @@ Editor::get_preferred_edit_position (bool ignore_playhead) } void -Editor::set_loop_range (nframes_t start, nframes_t end, string cmd) +Editor::set_loop_range (nframes64_t start, nframes64_t end, string cmd) { if (!session) return; @@ -4577,7 +4742,7 @@ Editor::set_loop_range (nframes_t start, nframes_t end, string cmd) } void -Editor::set_punch_range (nframes_t start, nframes_t end, string cmd) +Editor::set_punch_range (nframes64_t start, nframes64_t end, string cmd) { if (!session) return; @@ -4625,14 +4790,14 @@ Editor::get_regions_at (RegionSelection& rs, nframes64_t where, const TrackSelec if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) { - Playlist::RegionList* regions = pl->regions_at ((nframes_t) floor ( (double)where * ds->speed())); + Playlist::RegionList* regions = pl->regions_at ((nframes64_t) floor ( (double)where * ds->speed())); for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { RegionView* rv = atv->audio_view()->find_view (*i); if (rv) { - rs.push_back (rv); + rs.add (rv); } } @@ -4663,7 +4828,7 @@ Editor::get_regions_after (RegionSelection& rs, nframes64_t where, const TrackSe if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) { - Playlist::RegionList* regions = pl->regions_touched ((nframes_t) floor ( (double)where * ds->speed()), max_frames); + Playlist::RegionList* regions = pl->regions_touched ((nframes64_t) floor ( (double)where * ds->speed()), max_frames); for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { @@ -4809,3 +4974,170 @@ Editor::first_idle () _have_idled = true; } + +void +Editor::start_resize_line_ops () +{ +#if 0 + old_resize_line_y = -1; + resize_line_y = -1; + need_resize_line = true; +#endif +} + +void +Editor::end_resize_line_ops () +{ +#if 0 + need_resize_line = false; + + if (old_resize_line_y >= 0) { + Gdk::Rectangle r (0, old_resize_line_y, (int) canvas_width, 3); + Glib::RefPtr win = get_window(); + cerr << "Final invalidation at " << old_resize_line_y << endl; + win->invalidate_rect (r, false); + } +#endif +} + +void +Editor::queue_draw_resize_line (int at) +{ +#if 0 + Glib::RefPtr win = get_window(); + + resize_line_y = at; + + if (win && canvas_width) { + + int controls_width = controls_layout.get_width(); + int xroot, discard; + + controls_layout.get_window()->get_origin (xroot, discard); + + if (old_resize_line_y >= 0) { + + /* redraw where it used to be */ + + + Gdk::Rectangle r (xroot, old_resize_line_y - 1, controls_width + (int) canvas_width, 3); + win->invalidate_rect (r, true); + cerr << "invalidate " << xroot << "," << old_resize_line_y - 1 << ' ' + << controls_width + canvas_width << " x 3\n"; + } + + /* draw where it is */ + + Gdk::Rectangle r (xroot, at - 1, controls_width + (int) canvas_width, 3); + win->invalidate_rect (r, true); + } +#endif +} + +bool +Editor::on_expose_event (GdkEventExpose* ev) +{ + /* cerr << "+++ editor expose " + << ev->area.x << ',' << ev->area.y + << ' ' + << ev->area.width << " x " << ev->area.height + << " need reize ? " << need_resize_line + << endl; + */ + bool ret = Window::on_expose_event (ev); + +#if 0 + if (need_resize_line) { + + int xroot, yroot, discard; + int controls_width; + + /* Our root coordinates for drawing the line will be the left edge + of the track controls, and the upper left edge of our own window. + */ + + get_window()->get_origin (discard, yroot); + controls_layout.get_window()->get_origin (xroot, discard); + controls_width = controls_layout.get_width(); + + GdkRectangle lr; + GdkRectangle intersection; + + lr.x = xroot; + lr.y = resize_line_y; + lr.width = controls_width + (int) canvas_width; + lr.height = 3; + + if (gdk_rectangle_intersect (&lr, &ev->area, &intersection)) { + + Glib::RefPtr style (get_style()); + Glib::RefPtr black_gc (style->get_black_gc ()); + Glib::RefPtr gc = wrap (black_gc->gobj_copy(), false); + + /* draw on root window */ + + GdkWindow* win = gdk_get_default_root_window(); + + gc->set_subwindow (Gdk::INCLUDE_INFERIORS); + gc->set_line_attributes (3, Gdk::LINE_SOLID, + Gdk::CAP_NOT_LAST, + Gdk::JOIN_MITER); + + gdk_draw_line (win, gc->gobj(), + xroot, + yroot + resize_line_y, + xroot + (int) canvas_width + controls_width, + yroot + resize_line_y); + cerr << "drew line @ " << xroot << ", " << yroot + resize_line_y + << " to " << xroot + (int) canvas_width + controls_width + << ", " << yroot + resize_line_y + << endl; + old_resize_line_y = yroot + resize_line_y; + cerr << "NEXT EXPOSE SHOULD BE AT " << old_resize_line_y << endl; + } else { + cerr << "no intersect with " + << lr.x << ',' << lr.y + << ' ' + << lr.width << " x " << lr.height + << endl; + } + } + + //cerr << "--- editor expose\n"; +#endif + + return ret; +} + +static gboolean +_idle_resizer (gpointer arg) +{ + return ((Editor*)arg)->idle_resize (); +} + +void +Editor::add_to_idle_resize (TimeAxisView* view, uint32_t h) +{ + if (resize_idle_id < 0) { + resize_idle_id = g_idle_add (_idle_resizer, this); + } + + resize_idle_target = h; + + pending_resizes.push_back (view); + + if (selection->selected (view) && !selection->tracks.empty()) { + pending_resizes.insert (pending_resizes.end(), selection->tracks.begin(), selection->tracks.end()); + } +} + +bool +Editor::idle_resize () +{ + for (vector::iterator i = pending_resizes.begin(); i != pending_resizes.end(); ++i) { + (*i)->idle_resize (resize_idle_target); + } + pending_resizes.clear(); + resize_idle_id = -1; + return false; +} diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 2c7e32d19e..e8af889ad1 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -136,9 +136,9 @@ class Editor : public PublicEditor void first_idle (); virtual bool have_idled() const { return _have_idled; } - nframes_t leftmost_position() const { return leftmost_frame; } - nframes_t current_page_frames() const { - return (nframes_t) floor (canvas_width * frames_per_unit); + nframes64_t leftmost_position() const { return leftmost_frame; } + nframes64_t current_page_frames() const { + return (nframes64_t) floor (canvas_width * frames_per_unit); } void cycle_snap_mode (); @@ -170,6 +170,7 @@ class Editor : public PublicEditor TimeAxisView* get_named_time_axis(const std::string & name) ; void foreach_time_axis_view (sigc::slot); + void add_to_idle_resize (TimeAxisView*, uint32_t); RouteTimeAxisView* get_route_view_by_id (PBD::ID& id); @@ -204,11 +205,11 @@ class Editor : public PublicEditor /* undo related */ - nframes_t unit_to_frame (double unit) const { - return (nframes_t) rint (unit * frames_per_unit); + nframes64_t unit_to_frame (double unit) const { + return (nframes64_t) rint (unit * frames_per_unit); } - double frame_to_unit (nframes_t frame) const { + double frame_to_unit (nframes64_t frame) const { return rint ((double) frame / (double) frames_per_unit); } @@ -232,7 +233,7 @@ class Editor : public PublicEditor */ if (pixel >= 0) { - return (nframes_t) rint (pixel * frames_per_unit * GNOME_CANVAS(track_canvas->gobj())->pixels_per_unit); + return (nframes64_t) rint (pixel * frames_per_unit * GNOME_CANVAS(track_canvas->gobj())->pixels_per_unit); } else { return 0; } @@ -304,7 +305,7 @@ class Editor : public PublicEditor void show_editor_mixer (bool yn); void show_editor_list (bool yn); void set_selected_mixer_strip (TimeAxisView&); - void hide_track_in_display (TimeAxisView& tv); + void hide_track_in_display (TimeAxisView& tv, bool temporary = false); void show_track_in_display (TimeAxisView& tv); /* nudge is initiated by transport controls owned by ARDOUR_UI */ @@ -370,13 +371,14 @@ class Editor : public PublicEditor bool new_regionviews_display_gain () { return _new_regionviews_show_envelope; } void prepare_for_cleanup (); + void finish_cleanup (); void maximise_editing_space(); void restore_editing_space(); - void reset_x_origin (nframes_t); + void reset_x_origin (nframes64_t); void reset_zoom (double); - void reposition_and_zoom (nframes_t, double); + void reposition_and_zoom (nframes64_t, double); nframes64_t get_preferred_edit_position (bool ignore_playhead = false); @@ -387,11 +389,19 @@ class Editor : public PublicEditor void show_rhythm_ferret(); + void goto_visual_state (uint32_t); + void save_visual_state (uint32_t); + + void queue_draw_resize_line (int at); + void start_resize_line_ops (); + void end_resize_line_ops (); + protected: void map_transport_state (); - void map_position_change (nframes_t); + void map_position_change (nframes64_t); void on_realize(); + bool on_expose_event (GdkEventExpose*); private: @@ -401,25 +411,41 @@ class Editor : public PublicEditor bool constructed; // to keep track of the playhead position for control_scroll - boost::optional _control_scroll_target; + boost::optional _control_scroll_target; PlaylistSelector* _playlist_selector; + typedef std::pair TAVState; + struct VisualState { - double frames_per_unit; - nframes_t leftmost_frame; - Editing::ZoomFocus zoom_focus; + double y_position; + double frames_per_unit; + nframes64_t leftmost_frame; + Editing::ZoomFocus zoom_focus; + bool zoomed_to_region; + std::list track_states; }; - VisualState last_visual_state; + std::list undo_visual_stack; + std::list redo_visual_stack; + VisualState* current_visual_state (bool with_tracks = true); + void undo_visual_state (); + void redo_visual_state (); + void use_visual_state (VisualState&); + bool no_save_visual; + void swap_visual_state (); + + std::vector visual_states; + sigc::connection visual_state_op_connection; + void start_visual_state_op (uint32_t n); + void cancel_visual_state_op (uint32_t n); + bool end_visual_state_op (uint32_t n); - nframes_t leftmost_frame; + nframes64_t leftmost_frame; double frames_per_unit; Editing::ZoomFocus zoom_focus; - void use_visual_state (const VisualState&); void set_frames_per_unit (double); - void swap_visual_state (); void post_zoom (); Editing::MouseMode mouse_mode; @@ -469,7 +495,7 @@ class Editor : public PublicEditor void hide(); void show (); void set_name (const string&); - void set_position (nframes_t start, nframes_t end = 0); + void set_position (nframes64_t start, nframes64_t end = 0); void set_color_rgba (uint32_t); }; @@ -482,7 +508,8 @@ class Editor : public PublicEditor void hide_marker (ArdourCanvas::Item*, GdkEvent*); void clear_marker_display (); - void mouse_add_new_marker (nframes_t where, bool is_cd=false, bool is_xrun=false); + void mouse_add_new_marker (nframes64_t where, bool is_cd=false, bool is_xrun=false); + bool choose_new_marker_name(string &name); void update_cd_marker_display (); void ensure_cd_marker_updated (LocationMarkers * lam, ARDOUR::Location * location); @@ -542,12 +569,12 @@ class Editor : public PublicEditor Gtk::Menu * track_edit_playlist_submenu; Gtk::Menu * track_selection_edit_playlist_submenu; - void popup_track_context_menu (int, int, ItemType, bool, nframes_t); - Gtk::Menu* build_track_context_menu (nframes_t); - Gtk::Menu* build_track_bus_context_menu (nframes_t); - Gtk::Menu* build_track_region_context_menu (nframes_t frame); - Gtk::Menu* build_track_crossfade_context_menu (nframes_t); - Gtk::Menu* build_track_selection_context_menu (nframes_t); + void popup_track_context_menu (int, int, ItemType, bool, nframes64_t); + Gtk::Menu* build_track_context_menu (nframes64_t); + Gtk::Menu* build_track_bus_context_menu (nframes64_t); + Gtk::Menu* build_track_region_context_menu (nframes64_t frame); + Gtk::Menu* build_track_crossfade_context_menu (nframes64_t); + Gtk::Menu* build_track_selection_context_menu (nframes64_t); void add_dstream_context_items (Gtk::Menu_Helpers::MenuList&); void add_bus_context_items (Gtk::Menu_Helpers::MenuList&); void add_region_context_items (StreamView*, boost::shared_ptr, Gtk::Menu_Helpers::MenuList&); @@ -564,6 +591,10 @@ class Editor : public PublicEditor Gtk::VBox global_vpacker; Gtk::VBox vpacker; + bool need_resize_line; + int resize_line_y; + int old_resize_line_y; + Gdk::Cursor* current_canvas_cursor; void set_canvas_cursor (); Gdk::Cursor* which_grabber_cursor (); @@ -643,7 +674,7 @@ class Editor : public PublicEditor void compute_fixed_ruler_scale (); //calculates the RulerScale of the fixed rulers void update_fixed_rulers (); void update_tempo_based_rulers (); - void popup_ruler_menu (nframes_t where = 0, ItemType type = RegionItem); + void popup_ruler_menu (nframes64_t where = 0, ItemType type = RegionItem); void update_ruler_visibility (); void set_ruler_visible (RulerType, bool); void toggle_ruler_visibility (RulerType rt); @@ -704,7 +735,7 @@ class Editor : public PublicEditor gint bbt_nmarks; uint32_t bbt_bar_helper_on; uint32_t bbt_accent_modulo; - void compute_bbt_ruler_scale (nframes_t lower, nframes_t upper); + void compute_bbt_ruler_scale (nframes64_t lower, nframes64_t upper); gint metric_get_smpte (GtkCustomRulerMark **, gdouble, gdouble, gint); gint metric_get_bbt (GtkCustomRulerMark **, gdouble, gdouble, gint); @@ -752,13 +783,13 @@ class Editor : public PublicEditor Editor& editor; ArdourCanvas::Points points; ArdourCanvas::Line canvas_item; - nframes_t current_frame; + nframes64_t current_frame; double length; Cursor (Editor&, bool (Editor::*)(GdkEvent*,ArdourCanvas::Item*)); ~Cursor (); - void set_position (nframes_t); + void set_position (nframes64_t); void set_length (double units); void set_y_axis (double position); }; @@ -793,14 +824,12 @@ class Editor : public PublicEditor void select_all_selectables_between (bool within); void select_range_between (); - boost::shared_ptr find_next_region (nframes_t, ARDOUR::RegionPoint, int32_t dir, TrackViewList&, TimeAxisView ** = 0); + boost::shared_ptr find_next_region (nframes64_t, ARDOUR::RegionPoint, int32_t dir, TrackViewList&, TimeAxisView ** = 0); nframes64_t find_next_region_boundary (nframes64_t, int32_t dir, const TrackViewList&); - vector region_boundary_cache; + vector region_boundary_cache; void build_region_boundary_cache (); - Gtk::VBox trackview_vpacker; - Gtk::HBox top_hbox; Gtk::HBox bottom_hbox; @@ -826,7 +855,7 @@ class Editor : public PublicEditor double canvas_width; double canvas_height; double full_canvas_height; - nframes_t last_canvas_frame; + nframes64_t last_canvas_frame; bool track_canvas_map_handler (GdkEventAny*); bool time_canvas_map_handler (GdkEventAny*); @@ -841,7 +870,8 @@ class Editor : public PublicEditor Gtk::HBox edit_controls_hbox; void control_scroll (float); - bool deferred_control_scroll (nframes_t); + void access_action (std::string,std::string); + bool deferred_control_scroll (nframes64_t); sigc::connection control_scroll_connection; void tie_vertical_scrolling (); @@ -855,7 +885,7 @@ class Editor : public PublicEditor }; Type pending; - nframes_t time_origin; + nframes64_t time_origin; double frames_per_unit; int idle_handler_id; @@ -869,7 +899,7 @@ class Editor : public PublicEditor static int _idle_visual_changer (void *arg); int idle_visual_changer (); - void queue_visual_change (nframes_t); + void queue_visual_change (nframes64_t); void queue_visual_change (double); void end_location_changed (ARDOUR::Location*); @@ -999,16 +1029,16 @@ class Editor : public PublicEditor static void build_cursors (); sigc::connection scroll_connection; - nframes_t last_update_frame; - void center_screen (nframes_t); - void center_screen_internal (nframes_t, float); + nframes64_t last_update_frame; + void center_screen (nframes64_t); + void center_screen_internal (nframes64_t, float); void update_current_screen (); void session_going_away (); - nframes_t cut_buffer_start; - nframes_t cut_buffer_length; + nframes64_t cut_buffer_start; + nframes64_t cut_buffer_length; bool typed_event (ArdourCanvas::Item*, GdkEvent*, ItemType); bool button_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType); @@ -1021,7 +1051,7 @@ class Editor : public PublicEditor void register_actions (); - int ensure_cursor (nframes_t* pos); + int ensure_cursor (nframes64_t* pos); void handle_new_region (boost::weak_ptr); void handle_new_regions (vector >& ); @@ -1030,6 +1060,7 @@ class Editor : public PublicEditor void add_regions_to_region_display (std::vector > & ); void region_hidden (boost::shared_ptr); void redisplay_regions (); + bool no_region_list_redisplay; void insert_into_tmp_regionlist(boost::shared_ptr); list > tmp_region_list; @@ -1041,7 +1072,7 @@ class Editor : public PublicEditor void cut_copy_ranges (Editing::CutCopyOp); void mouse_paste (); - void paste_internal (nframes_t position, float times); + void paste_internal (nframes64_t position, float times); /* EDITING OPERATIONS */ @@ -1055,19 +1086,19 @@ class Editor : public PublicEditor void lower_region (); void lower_region_to_bottom (); void split_region (); - void split_region_at (nframes_t); - void split_regions_at (nframes_t, RegionSelection&); + void split_region_at (nframes64_t); + void split_regions_at (nframes64_t, RegionSelection&); void split_region_at_transients (); void split_region_at_points (boost::shared_ptr, ARDOUR::AnalysisFeatureList&, bool can_ferret); void crop_region_to_selection (); - void crop_region_to (nframes_t start, nframes_t end); + void crop_region_to (nframes64_t start, nframes64_t end); void set_sync_point (nframes64_t, const RegionSelection&); void set_region_sync_from_edit_point (); void remove_region_sync(); - void align_selection (ARDOUR::RegionPoint, nframes_t position, const RegionSelection&); - void align_selection_relative (ARDOUR::RegionPoint point, nframes_t position, const RegionSelection&); - void align_region (boost::shared_ptr, ARDOUR::RegionPoint point, nframes_t position); - void align_region_internal (boost::shared_ptr, ARDOUR::RegionPoint point, nframes_t position); + void align_selection (ARDOUR::RegionPoint, nframes64_t position, const RegionSelection&); + void align_selection_relative (ARDOUR::RegionPoint point, nframes64_t position, const RegionSelection&); + void align_region (boost::shared_ptr, ARDOUR::RegionPoint point, nframes64_t position); + void align_region_internal (boost::shared_ptr, ARDOUR::RegionPoint point, nframes64_t position); void remove_selected_regions (); void remove_clicked_region (); void edit_region (); @@ -1087,7 +1118,7 @@ class Editor : public PublicEditor void quantize_region (); void do_insert_time (); - void insert_time (nframes64_t pos, nframes64_t distance, Editing::InsertTimeOption opt, bool ignore_music_glue); + void insert_time (nframes64_t pos, nframes64_t distance, Editing::InsertTimeOption opt, bool ignore_music_glue, bool markers_too); void tab_to_transient (bool forward); @@ -1130,13 +1161,13 @@ class Editor : public PublicEditor void loop_location (ARDOUR::Location&); void temporal_zoom_selection (); - void temporal_zoom_region (); - void toggle_zoom_region (); + void temporal_zoom_region (bool both_axes); + void toggle_zoom_region (bool both_axes); bool zoomed_to_region; void temporal_zoom_session (); void temporal_zoom (gdouble scale); - void temporal_zoom_by_frame (nframes_t start, nframes_t end, const string & op); - void temporal_zoom_to_frame (bool coarser, nframes_t frame); + void temporal_zoom_by_frame (nframes64_t start, nframes64_t end, const string & op); + void temporal_zoom_to_frame (bool coarser, nframes64_t frame); void amplitude_zoom (gdouble scale); void amplitude_zoom_step (bool in); @@ -1259,8 +1290,8 @@ class Editor : public PublicEditor void set_loop_from_region (bool play); void set_punch_from_edit_range (); - void set_loop_range (nframes_t start, nframes_t end, std::string cmd); - void set_punch_range (nframes_t start, nframes_t end, std::string cmd); + void set_loop_range (nframes64_t start, nframes64_t end, std::string cmd); + void set_punch_range (nframes64_t start, nframes64_t end, std::string cmd); void add_location_from_playhead_cursor (); bool select_new_marker; @@ -1281,7 +1312,7 @@ class Editor : public PublicEditor void keyboard_selection_begin (); void keyboard_selection_finish (bool add); bool have_pending_keyboard_selection; - nframes_t pending_keyboard_selection_start; + nframes64_t pending_keyboard_selection_start; boost::shared_ptr select_region_for_operation (int dir, TimeAxisView **tv); void extend_selection_to_end_of_region (bool next); @@ -1375,11 +1406,11 @@ class Editor : public PublicEditor void remove_gain_control_point (ArdourCanvas::Item*, GdkEvent*); void remove_control_point (ArdourCanvas::Item*, GdkEvent*); - void mouse_brush_insert_region (RegionView*, nframes_t pos); - void brush (nframes_t); + void mouse_brush_insert_region (RegionView*, nframes64_t pos); + void brush (nframes64_t); - 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); + void show_verbose_time_cursor (nframes64_t frame, double offset = 0, double xpos=-1, double ypos=-1); + void show_verbose_duration_cursor (nframes64_t start, nframes64_t end, double offset = 0, double xpos=-1, double ypos=-1); double clamp_verbose_cursor_x (double); double clamp_verbose_cursor_y (double); @@ -1486,8 +1517,8 @@ public: void new_tempo_section (); - void mouse_add_new_tempo_event (nframes_t where); - void mouse_add_new_meter_event (nframes_t where); + void mouse_add_new_tempo_event (nframes64_t where); + void mouse_add_new_meter_event (nframes64_t where); void remove_tempo_marker (ArdourCanvas::Item*); void remove_meter_marker (ArdourCanvas::Item*); @@ -1513,6 +1544,8 @@ public: void marker_menu_set_playhead (); void marker_menu_set_from_playhead (); void marker_menu_set_from_selection (); + void marker_menu_range_to_next (); + void marker_menu_export_range (); void new_transport_marker_menu_set_loop (); void new_transport_marker_menu_set_punch (); void update_loop_range_view (bool visibility=false); @@ -1548,14 +1581,8 @@ public: void redisplay_tempo (bool immediate_redraw); void snap_to (nframes64_t& first, int32_t direction = 0, bool for_mark = false); - void snap_to (nframes_t& first, int32_t direction = 0, bool for_mark = false) { - /* XXX remove this function when everything moves to 64 bit frame counts */ - nframes64_t first64 = first; - snap_to (first64, direction, for_mark); - first = (nframes_t) first64; - } - double snap_length_beats (nframes_t start); + double snap_length_beats (nframes64_t start); uint32_t bbt_beat_subdivision; @@ -1690,7 +1717,7 @@ public: void region_selection_op (void (ARDOUR::Region::*pmf)(void*), void*); void region_selection_op (void (ARDOUR::Region::*pmf)(bool), bool); - bool audio_region_selection_covers (nframes_t where); + bool audio_region_selection_covers (nframes64_t where); /* transport range select process */ enum RangeMarkerOp { @@ -1733,7 +1760,7 @@ public: void drag_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event); void end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event); - bool select_all_within (nframes_t start, nframes_t end, gdouble topy, gdouble boty, const TrackViewList&, Selection::Operation op); + bool select_all_within (nframes64_t start, nframes64_t end, gdouble topy, gdouble boty, const TrackViewList&, Selection::Operation op); ArdourCanvas::SimpleRect *rubberband_rect; @@ -1744,7 +1771,7 @@ public: void end_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event); ArdourCanvas::SimpleRect *zoom_rect; - void reposition_zoom_rect (nframes_t start, nframes_t end); + void reposition_zoom_rect (nframes64_t start, nframes64_t end); /* diskstream/route display management */ @@ -1752,11 +1779,13 @@ public: RouteDisplayModelColumns() { add (text); add (visible); + add (temporary_visible); add (tv); add (route); } Gtk::TreeModelColumn text; Gtk::TreeModelColumn visible; + Gtk::TreeModelColumn temporary_visible; Gtk::TreeModelColumn tv; Gtk::TreeModelColumn > route; }; @@ -1769,6 +1798,8 @@ public: Gtk::ScrolledWindow route_list_scroller; Gtk::Menu* route_list_menu; + void update_route_visibility (); + void sync_order_keys (); bool ignore_route_order_sync; @@ -1854,7 +1885,7 @@ public: int last_autoscroll_x; int last_autoscroll_y; uint32_t autoscroll_cnt; - nframes_t autoscroll_x_distance; + nframes64_t autoscroll_x_distance; double autoscroll_y_distance; static gint _autoscroll_canvas (void *); @@ -1862,6 +1893,7 @@ public: void start_canvas_autoscroll (int x, int y); void stop_canvas_autoscroll (); void maybe_autoscroll (GdkEventMotion*); + bool allow_vertical_scroll; /* trimming */ enum TrimOp { @@ -1873,9 +1905,9 @@ public: void start_trim (ArdourCanvas::Item*, GdkEvent*); void point_trim (GdkEvent*); void trim_motion_callback (ArdourCanvas::Item*, GdkEvent*); - void single_contents_trim (RegionView&, nframes_t, bool, bool, bool); - void single_start_trim (RegionView&, nframes_t, bool, bool); - void single_end_trim (RegionView&, nframes_t, bool, bool); + void single_contents_trim (RegionView&, nframes64_t, bool, bool, bool); + void single_start_trim (RegionView&, nframes64_t, bool, bool); + void single_end_trim (RegionView&, nframes64_t, bool, bool); void trim_finished_callback (ArdourCanvas::Item*, GdkEvent*); void thaw_region_after_trim (RegionView& rv); @@ -1943,14 +1975,14 @@ public: ExportDialog *export_dialog; ExportDialog *export_range_markers_dialog; - void export_range (nframes_t start, nframes_t end); + void export_range (nframes64_t start, nframes64_t end); void export_range_markers (); int write_region_selection(RegionSelection&); bool write_region (string path, boost::shared_ptr); void export_region (); void bounce_region_selection (); - void bounce_range_selection (); + void bounce_range_selection (bool replace); void external_edit_region (); int write_audio_selection (TimeSelection&); @@ -1967,12 +1999,6 @@ public: void begin_reversible_command (string cmd_name); void commit_reversible_command (); - /* visual history */ - - UndoHistory visual_history; - UndoTransaction current_visual_command; - - void update_title (); void update_title_s (const string & snapshot_name); @@ -2151,7 +2177,7 @@ public: Gtk::VBox nudge_vbox; AudioClock nudge_clock; - nframes_t get_nudge_distance (nframes_t pos, nframes_t& next); + nframes64_t get_nudge_distance (nframes64_t pos, nframes64_t& next); bool nudge_forward_release (GdkEventButton*); bool nudge_backward_release (GdkEventButton*); @@ -2169,7 +2195,7 @@ public: /* tracking step changes of track height */ TimeAxisView* current_stepping_trackview; - struct timeval last_track_height_step_timestamp; + ARDOUR::microseconds_t last_track_height_step_timestamp; gint track_height_step_timeout(); sigc::connection step_timeout; @@ -2240,7 +2266,8 @@ public: RhythmFerret* rhythm_ferret; - void set_track_height (TimeAxisView::TrackHeight h); + void fit_tracks (); + void set_track_height (uint32_t h); void set_track_height_largest (); void set_track_height_large (); void set_track_height_larger (); @@ -2253,6 +2280,11 @@ public: void waveform_scale_chosen (Editing::WaveformScale); bool _have_idled; + int resize_idle_id; + int32_t resize_idle_target; + bool idle_resize(); + friend gboolean _idle_resize (gpointer); + std::vector pending_resizes; }; #endif /* __ardour_editor_h__ */ diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 0d859985a2..a1a7092eb0 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -73,6 +73,7 @@ Editor::register_actions () ActionManager::register_action (editor_actions, X_("RegionEditOps"), _("Region operations")); ActionManager::register_action (editor_actions, X_("RegionGainMenu"), _("Gain")); ActionManager::register_action (editor_actions, X_("RulerMenu"), _("Rulers")); + ActionManager::register_action (editor_actions, X_("SavedViewMenu"), _("Views")); ActionManager::register_action (editor_actions, X_("ScrollMenu"), _("Scroll")); ActionManager::register_action (editor_actions, X_("SecondaryClockMenu"), _("Secondary Clock")); ActionManager::register_action (editor_actions, X_("Select"), _("Select")); @@ -91,10 +92,8 @@ Editor::register_actions () ActionManager::register_action (editor_actions, X_("TrimMenu"), _("Trim")); ActionManager::register_action (editor_actions, X_("View"), _("View")); ActionManager::register_action (editor_actions, X_("WaveformMenu"), _("Waveforms")); - ActionManager::register_action (editor_actions, X_("ZoomFocus"), _("Zoom")); + ActionManager::register_action (editor_actions, X_("ZoomFocus"), _("Zoom Focus")); ActionManager::register_action (editor_actions, X_("ZoomMenu"), _("Zoom")); - ActionManager::register_action (editor_actions, X_("ZoomFocusMenu"), _("Zoom Focus")); - /* add named actions for the editor */ @@ -198,6 +197,56 @@ Editor::register_actions () ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "save-visual-state-1", _("Save View 1"), bind (mem_fun (*this, &Editor::start_visual_state_op), 0)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-visual-state-1", _("Goto View 1"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 0)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "save-visual-state-2", _("Save View 2"), bind (mem_fun (*this, &Editor::start_visual_state_op), 1)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-visual-state-2", _("Goto View 2"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 1)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "save-visual-state-3", _("Save View 3"), bind (mem_fun (*this, &Editor::start_visual_state_op), 2)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-visual-state-3", _("Goto View 3"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 2)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "save-visual-state-4", _("Save View 4"), bind (mem_fun (*this, &Editor::start_visual_state_op), 3)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-visual-state-4", _("Goto View 4"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 3)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "save-visual-state-5", _("Save View 5"), bind (mem_fun (*this, &Editor::start_visual_state_op), 4)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-visual-state-5", _("Goto View 5"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 4)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "save-visual-state-6", _("Save View 6"), bind (mem_fun (*this, &Editor::start_visual_state_op), 5)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-visual-state-6", _("Goto View 6"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 5)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "save-visual-state-7", _("Save View 7"), bind (mem_fun (*this, &Editor::start_visual_state_op), 6)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-visual-state-7", _("Goto View 7"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 6)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "save-visual-state-8", _("Save View 8"), bind (mem_fun (*this, &Editor::start_visual_state_op), 7)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-visual-state-8", _("Goto View 8"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 7)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "save-visual-state-9", _("Save View 9"), bind (mem_fun (*this, &Editor::start_visual_state_op), 8)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-visual-state-9", _("Goto View 9"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 8)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "save-visual-state-10", _("Save View 10"), bind (mem_fun (*this, &Editor::start_visual_state_op), 9)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-visual-state-10", _("Goto View 10"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 9)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "save-visual-state-11", _("Save View 11"), bind (mem_fun (*this, &Editor::start_visual_state_op), 10)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-visual-state-11", _("Goto View 11"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 10)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "save-visual-state-12", _("Save View 12"), bind (mem_fun (*this, &Editor::start_visual_state_op), 11)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "goto-visual-state-12", _("Goto View 12"), bind (mem_fun (*this, &Editor::cancel_visual_state_op), 11)); + ActionManager::session_sensitive_actions.push_back (act); + + act = ActionManager::register_action (editor_actions, "goto-mark-1", _("Locate to Mark 1"), bind (mem_fun (*this, &Editor::goto_nth_marker), 0)); ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (editor_actions, "goto-mark-2", _("Locate to Mark 2"), bind (mem_fun (*this, &Editor::goto_nth_marker), 1)); @@ -249,7 +298,9 @@ Editor::register_actions () ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (editor_actions, "zoom-to-session", _("Zoom to Session"), mem_fun(*this, &Editor::temporal_zoom_session)); ActionManager::session_sensitive_actions.push_back (act); - act = ActionManager::register_action (editor_actions, "zoom-to-region", _("Zoom to Region"), mem_fun(*this, &Editor::toggle_zoom_region)); + act = ActionManager::register_action (editor_actions, "zoom-to-region", _("Zoom to Region"), bind (mem_fun(*this, &Editor::toggle_zoom_region), false)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "zoom-to-region-both-axes", _("Zoom to Region (W&H)"), bind (mem_fun(*this, &Editor::toggle_zoom_region), true)); ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (editor_actions, "toggle-zoom", _("Toggle Zoom State"), mem_fun(*this, &Editor::swap_visual_state)); ActionManager::session_sensitive_actions.push_back (act); @@ -319,6 +370,9 @@ Editor::register_actions () act = ActionManager::register_action (editor_actions, "pitch-shift-region", _("Transpose"), mem_fun(*this, &Editor::pitch_shift_regions)); ActionManager::session_sensitive_actions.push_back (act); ActionManager::region_selection_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "toggle-opaque-region", _("Toggle Opaque"), mem_fun(*this, &Editor::toggle_region_opaque)); + ActionManager::session_sensitive_actions.push_back (act); + ActionManager::region_selection_sensitive_actions.push_back (act); act = ActionManager::register_action (editor_actions, "set-fade-in-length", _("Set Fade In Length"), bind (mem_fun(*this, &Editor::set_fade_length), true)); ActionManager::session_sensitive_actions.push_back (act); @@ -467,7 +521,8 @@ Editor::register_actions () act = ActionManager::register_action (editor_actions, "quantize-region", _("Quantize Region"), mem_fun(*this, &Editor::quantize_region)); ActionManager::session_sensitive_actions.push_back (act); - + ActionManager::region_selection_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "set-tempo-from-region", _("Set Tempo from Region=Bar"), mem_fun(*this, &Editor::use_region_as_bar)); ActionManager::session_sensitive_actions.push_back (act); ActionManager::region_selection_sensitive_actions.push_back (act); @@ -521,6 +576,8 @@ Editor::register_actions () ActionManager::session_sensitive_actions.push_back (act); ActionManager::track_selection_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "fit-tracks", _("Fit Selected Tracks"), (mem_fun(*this, &Editor::fit_tracks))); + ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (editor_actions, "track-height-largest", _("Largest"), (mem_fun(*this, &Editor::set_track_height_largest))); ActionManager::session_sensitive_actions.push_back (act); ActionManager::track_selection_sensitive_actions.push_back (act); @@ -693,9 +750,10 @@ Editor::register_actions () /* the next two are duplicate items with different names for use in two different contexts */ - act = ActionManager::register_action (editor_actions, X_("addExistingAudioFiles"), _("Import"), mem_fun (*this, &Editor::external_audio_dialog)); ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, X_("addExternalAudioToRegionList"), _("Import to Region List"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion)); + ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_toggle_action (editor_actions, X_("toggle-waveform-visible"), _("Show Waveforms"), mem_fun (*this, &Editor::toggle_waveform_visibility)); ActionManager::track_selection_sensitive_actions.push_back (act); diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc index 61d0a22882..b3b710f990 100644 --- a/gtk2_ardour/editor_audio_import.cc +++ b/gtk2_ardour/editor_audio_import.cc @@ -74,7 +74,7 @@ void Editor::add_external_audio_action (ImportMode mode_hint) { if (session == 0) { - MessageDialog msg (0, _("You can't import or embed a file until you have a session loaded.")); + MessageDialog msg (_("You can't import or embed an audiofile until you have a session loaded.")); msg.run (); return; } @@ -95,7 +95,7 @@ Editor::external_audio_dialog () uint32_t track_cnt; if (session == 0) { - MessageDialog msg (0, _("You can't import or embed a file until you have a session loaded.")); + MessageDialog msg (_("You can't import or embed an audiofile until you have a session loaded.")); msg.run (); return; } diff --git a/gtk2_ardour/editor_audiotrack.cc b/gtk2_ardour/editor_audiotrack.cc index cfb8f0a557..7e821f0e5e 100644 --- a/gtk2_ardour/editor_audiotrack.cc +++ b/gtk2_ardour/editor_audiotrack.cc @@ -111,6 +111,7 @@ Editor::toggle_meter_updating() } else { stop_updating (); } + track_canvas_allocate(track_canvas->get_allocation()); } void diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index 516443e012..0be64cc80f 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -55,7 +55,7 @@ using namespace Glib; using namespace Gtkmm2ext; using namespace Editing; -/* XXX this is a hack. it ought to be the maximum value of an nframes_t */ +/* XXX this is a hack. it ought to be the maximum value of an nframes64_t */ const double max_canvas_coordinate = (double) JACK_MAX_FRAMES; @@ -181,7 +181,6 @@ Editor::initialize_canvas () marker_time_line_group = new ArdourCanvas::Group (*time_canvas->root(), 0.0, 0.0); marker_tempo_lines = new TempoLines(*time_canvas, marker_time_line_group); - meter_group = new ArdourCanvas::Group (*time_canvas->root(), 0.0, 0.0); tempo_group = new ArdourCanvas::Group (*time_canvas->root(), 0.0, timebar_height); range_marker_group = new ArdourCanvas::Group (*time_canvas->root(), 0.0, timebar_height * 2.0); @@ -190,23 +189,27 @@ Editor::initialize_canvas () cd_marker_group = new ArdourCanvas::Group (*time_canvas->root(), 0.0, timebar_height * 5.0); tempo_bar = new ArdourCanvas::SimpleRect (*tempo_group, 0.0, 0.0, max_canvas_coordinate, timebar_height-1.0); + tempo_bar->property_outline_what() = (0x1 | 0x8); tempo_bar->property_outline_pixels() = 1; - meter_bar = new ArdourCanvas::SimpleRect (*meter_group, 0.0, 0.0, max_canvas_coordinate, timebar_height-1.0); + meter_bar->property_outline_what() = (0x1 | 0x8); meter_bar->property_outline_pixels() = 1; marker_bar = new ArdourCanvas::SimpleRect (*marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height-1.0); + marker_bar->property_outline_what() = (0x1 | 0x8); marker_bar->property_outline_pixels() = 1; cd_marker_bar = new ArdourCanvas::SimpleRect (*cd_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height-1.0); + cd_marker_bar->property_outline_what() = (0x1 | 0x8); cd_marker_bar->property_outline_pixels() = 1; range_marker_bar = new ArdourCanvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height-1.0); + range_marker_bar->property_outline_what() = (0x1 | 0x8); range_marker_bar->property_outline_pixels() = 1; @@ -220,7 +223,7 @@ Editor::initialize_canvas () range_bar_drag_rect = new ArdourCanvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height-1.0); range_bar_drag_rect->property_outline_pixels() = 0; - + transport_bar_drag_rect = new ArdourCanvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height-1.0); transport_bar_drag_rect->property_outline_pixels() = 0; transport_bar_drag_rect->hide (); @@ -343,7 +346,7 @@ Editor::track_canvas_size_allocated () full_canvas_height = height; } - zoom_range_clock.set ((nframes_t) floor ((canvas_width * frames_per_unit))); + zoom_range_clock.set ((nframes64_t) floor ((canvas_width * frames_per_unit))); playhead_cursor->set_position (playhead_cursor->current_frame); reset_hscrollbar_stepping (); @@ -391,7 +394,7 @@ Editor::reset_scrolling_region (Gtk::Allocation* alloc) } double last_canvas_unit = max ((last_canvas_frame / frames_per_unit), canvas_width); - + //cerr << "Editor::reset_scrolling_region () lcf:fpu:cw:lcu " << last_canvas_frame << ":" << frames_per_unit << ":" << canvas_width << ":" << last_canvas_unit << endl;//DEBUG track_canvas->set_scroll_region (0.0, 0.0, last_canvas_unit, pos); // XXX what is the correct height value for the time canvas ? this overstates it @@ -521,6 +524,8 @@ Editor::drop_paths (const RefPtr& context, /* drop onto canvas background: create new tracks */ + frame = 0; + if (Profile->get_sae() || Config->get_only_copy_imported_files()) { do_import (paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, SrcBest, frame); } else { @@ -587,8 +592,8 @@ Editor::drop_routes (const Glib::RefPtr& context, void Editor::maybe_autoscroll (GdkEventMotion* event) { - nframes_t rightmost_frame = leftmost_frame + current_page_frames(); - nframes_t frame = drag_info.current_pointer_frame; + nframes64_t rightmost_frame = leftmost_frame + current_page_frames(); + nframes64_t frame = drag_info.current_pointer_frame; bool startit = false; double vertical_pos = vertical_adjustment.get_value(); @@ -621,6 +626,10 @@ Editor::maybe_autoscroll (GdkEventMotion* event) } + if (!allow_vertical_scroll) { + autoscroll_y = 0; + } + if ((autoscroll_x != last_autoscroll_x) || (autoscroll_y != last_autoscroll_y) || (autoscroll_x == 0 && autoscroll_y == 0)) { stop_canvas_autoscroll (); } @@ -642,10 +651,10 @@ Editor::_autoscroll_canvas (void *arg) bool Editor::autoscroll_canvas () { - nframes_t new_frame; - nframes_t limit = max_frames - current_page_frames(); + nframes64_t new_frame; + nframes64_t limit = max_frames - current_page_frames(); GdkEventMotion ev; - nframes_t target_frame; + nframes64_t target_frame; double new_pixel; double target_pixel; @@ -742,17 +751,17 @@ Editor::autoscroll_canvas () /* after about a while, speed up a bit by changing the timeout interval */ - autoscroll_x_distance = (nframes_t) floor (current_page_frames()/30.0f); + autoscroll_x_distance = (nframes64_t) floor (current_page_frames()/30.0f); } else if (autoscroll_cnt == 150) { /* 1.0 seconds */ - autoscroll_x_distance = (nframes_t) floor (current_page_frames()/20.0f); + autoscroll_x_distance = (nframes64_t) floor (current_page_frames()/20.0f); } else if (autoscroll_cnt == 300) { /* 1.5 seconds */ /* after about another while, speed up by increasing the shift per callback */ - autoscroll_x_distance = (nframes_t) floor (current_page_frames()/10.0f); + autoscroll_x_distance = (nframes64_t) floor (current_page_frames()/10.0f); } } @@ -792,7 +801,7 @@ Editor::start_canvas_autoscroll (int dx, int dy) autoscroll_active = true; autoscroll_x = dx; autoscroll_y = dy; - autoscroll_x_distance = (nframes_t) floor (current_page_frames()/50.0); + autoscroll_x_distance = (nframes64_t) floor (current_page_frames()/50.0); autoscroll_y_distance = fabs (dy * 5); /* pixels */ autoscroll_cnt = 0; @@ -864,7 +873,7 @@ Editor::tie_vertical_scrolling () void Editor::canvas_horizontally_scrolled () { - nframes64_t time_origin = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit); + nframes64_t time_origin = (nframes64_t) floor (horizontal_adjustment.get_value() * frames_per_unit); if (time_origin != leftmost_frame) { canvas_scroll_to (time_origin); @@ -874,8 +883,9 @@ Editor::canvas_horizontally_scrolled () void Editor::canvas_scroll_to (nframes64_t time_origin) { - leftmost_frame = time_origin; - nframes_t rightmost_frame = leftmost_frame + current_page_frames (); + leftmost_frame = time_origin; + + nframes64_t rightmost_frame = leftmost_frame + current_page_frames (); if (rightmost_frame > last_canvas_frame) { last_canvas_frame = rightmost_frame; diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index 0da0bfc487..dd107d8d02 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -56,7 +56,7 @@ Editor::track_canvas_scroll (GdkEventScroll* ev) { int x, y; double wx, wy; - nframes_t xdelta; + nframes64_t xdelta; int direction = ev->direction; CanvasNoteEvent *midi_event = dynamic_cast(track_canvas->get_item_at(ev->x, ev->y)); @@ -80,7 +80,7 @@ Editor::track_canvas_scroll (GdkEventScroll* ev) event.button.x = wx; event.button.y = wy; - nframes_t where = event_frame (&event, 0, 0); + nframes64_t where = event_frame (&event, 0, 0); temporal_zoom_to_frame (false, where); return true; } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) { @@ -93,7 +93,7 @@ Editor::track_canvas_scroll (GdkEventScroll* ev) return false; } } - gettimeofday (&last_track_height_step_timestamp, 0); + last_track_height_step_timestamp = get_microseconds(); current_stepping_trackview->step_height (true); return true; } else { @@ -118,7 +118,7 @@ Editor::track_canvas_scroll (GdkEventScroll* ev) event.button.x = wx; event.button.y = wy; - nframes_t where = event_frame (&event, 0, 0); + nframes64_t where = event_frame (&event, 0, 0); temporal_zoom_to_frame (true, where); return true; } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) { @@ -131,7 +131,7 @@ Editor::track_canvas_scroll (GdkEventScroll* ev) return false; } } - gettimeofday (&last_track_height_step_timestamp, 0); + last_track_height_step_timestamp = get_microseconds(); current_stepping_trackview->step_height (false); return true; } else { @@ -180,7 +180,7 @@ Editor::track_canvas_scroll_event (GdkEventScroll *event) bool Editor::time_canvas_scroll (GdkEventScroll* ev) { - nframes_t xdelta; + nframes64_t xdelta; int direction = ev->direction; switch (direction) { diff --git a/gtk2_ardour/editor_cursors.cc b/gtk2_ardour/editor_cursors.cc index 239d27d4f9..54786bcebf 100644 --- a/gtk2_ardour/editor_cursors.cc +++ b/gtk2_ardour/editor_cursors.cc @@ -61,7 +61,7 @@ Editor::Cursor::~Cursor () } void -Editor::Cursor::set_position (nframes_t frame) +Editor::Cursor::set_position (nframes64_t frame) { double new_pos = editor.frame_to_unit (frame); diff --git a/gtk2_ardour/editor_export_audio.cc b/gtk2_ardour/editor_export_audio.cc index 157494b846..c1d0c56833 100644 --- a/gtk2_ardour/editor_export_audio.cc +++ b/gtk2_ardour/editor_export_audio.cc @@ -77,7 +77,7 @@ Editor::export_selection () } void -Editor::export_range (nframes_t start, nframes_t end) +Editor::export_range (nframes64_t start, nframes64_t end) { if (session) { if (export_dialog == 0) { @@ -157,7 +157,12 @@ Editor::bounce_region_selection () itt.cancel = false; itt.progress = 0.0f; - track->bounce_range (region->position(), region->position() + region->length(), itt); + boost::shared_ptr r = track->bounce_range (region->position(), region->position() + region->length(), itt); + cerr << "Result of bounce of " + << region->name() << " len = " << region->length() + << " was " + << r->name() << " len = " << r->length() + << endl; } } @@ -165,11 +170,11 @@ bool Editor::write_region (string path, boost::shared_ptr region) { boost::shared_ptr fs; - const nframes_t chunk_size = 4096; - nframes_t to_read; + const nframes64_t chunk_size = 4096; + nframes64_t to_read; Sample buf[chunk_size]; gain_t gain_buffer[chunk_size]; - nframes_t pos; + nframes64_t pos; char s[PATH_MAX+1]; uint32_t cnt; vector > sources; @@ -234,7 +239,7 @@ Editor::write_region (string path, boost::shared_ptr region) pos = region->position(); while (to_read) { - nframes_t this_time; + nframes64_t this_time; this_time = min (to_read, chunk_size); @@ -312,11 +317,11 @@ bool Editor::write_audio_range (AudioPlaylist& playlist, const ChanCount& count, list& range) { boost::shared_ptr fs; - const nframes_t chunk_size = 4096; - nframes_t nframes; + const nframes64_t chunk_size = 4096; + nframes64_t nframes; Sample buf[chunk_size]; gain_t gain_buffer[chunk_size]; - nframes_t pos; + nframes64_t pos; char s[PATH_MAX+1]; uint32_t cnt; string path; @@ -369,7 +374,7 @@ Editor::write_audio_range (AudioPlaylist& playlist, const ChanCount& count, list pos = (*i).start; while (nframes) { - nframes_t this_time; + nframes64_t this_time; this_time = min (nframes, chunk_size); @@ -401,7 +406,7 @@ Editor::write_audio_range (AudioPlaylist& playlist, const ChanCount& count, list while (nframes) { - nframes_t this_time = min (nframes, chunk_size); + nframes64_t this_time = min (nframes, chunk_size); memset (buf, 0, sizeof (Sample) * this_time); for (uint32_t n=0; n < channels; ++n) { diff --git a/gtk2_ardour/editor_imageframe.cc b/gtk2_ardour/editor_imageframe.cc index daba2496a0..d4bf497591 100644 --- a/gtk2_ardour/editor_imageframe.cc +++ b/gtk2_ardour/editor_imageframe.cc @@ -95,10 +95,10 @@ void Editor::scroll_timeaxis_to_imageframe_item(const TimeAxisViewItem* item) { // GTK2FIX - //nframes_t offset = static_cast(frames_per_unit * (edit_hscroll_slider_width/2)) ; - nframes_t offset = 0; + //nframes64_t offset = static_cast(frames_per_unit * (edit_hscroll_slider_width/2)) ; + nframes64_t offset = 0; - nframes_t x_pos = 0 ; + nframes64_t x_pos = 0 ; if (item->get_position() < offset) { x_pos = 0 ; @@ -493,14 +493,14 @@ Editor::markerview_drag_motion_callback(ArdourCanvas::Item*, GdkEvent* event) double cx, cy ; MarkerView* mv = reinterpret_cast(drag_info.data) ; - nframes_t pending_region_position ; - nframes_t pointer_frame ; + nframes64_t pending_region_position ; + nframes64_t pointer_frame ; pointer_frame = event_frame(event, &cx, &cy) ; snap_to(pointer_frame) ; - if (pointer_frame > (nframes_t) drag_info.pointer_frame_offset) + if (pointer_frame > (nframes64_t) drag_info.pointer_frame_offset) { pending_region_position = pointer_frame - drag_info.pointer_frame_offset ; snap_to(pending_region_position) ; @@ -541,14 +541,14 @@ Editor::imageframe_drag_motion_callback(ArdourCanvas::Item*, GdkEvent* event) ImageFrameView* ifv = reinterpret_cast(drag_info.data) ; - nframes_t pending_region_position; - nframes_t pointer_frame; + nframes64_t pending_region_position; + nframes64_t pointer_frame; pointer_frame = event_frame(event, &cx, &cy) ; snap_to(pointer_frame) ; - if (pointer_frame > (nframes_t) drag_info.pointer_frame_offset) + if (pointer_frame > (nframes64_t) drag_info.pointer_frame_offset) { pending_region_position = pointer_frame - drag_info.pointer_frame_offset ; snap_to(pending_region_position) ; @@ -576,7 +576,7 @@ Editor::imageframe_drag_motion_callback(ArdourCanvas::Item*, GdkEvent* event) void Editor::timeaxis_item_drag_finished_callback(ArdourCanvas::Item*, GdkEvent* event) { - nframes_t where ; + nframes64_t where ; TimeAxisViewItem* tavi = reinterpret_cast(drag_info.data) ; bool item_x_movement = (drag_info.last_frame_position != tavi->get_position()) ; @@ -674,9 +674,9 @@ Editor::imageframe_start_handle_trim_motion(ArdourCanvas::Item* item, GdkEvent* { ImageFrameView* ifv = reinterpret_cast (drag_info.data) ; - nframes_t start = 0 ; - nframes_t end = 0 ; - nframes_t pointer_frame = event_frame(event) ; + nframes64_t start = 0 ; + nframes64_t end = 0 ; + nframes64_t pointer_frame = event_frame(event) ; // chekc th eposition of the item is not locked if(!ifv->get_position_locked()) { @@ -693,7 +693,7 @@ Editor::imageframe_start_handle_trim_motion(ArdourCanvas::Item* item, GdkEvent* } // are we getting bigger or smaller? - nframes_t new_dur_val = end - start ; + nframes64_t new_dur_val = end - start ; // start handle, so a smaller pointer frame increases our component size if(pointer_frame <= drag_info.grab_frame) @@ -751,10 +751,10 @@ Editor::imageframe_start_handle_end_trim(ArdourCanvas::Item* item, GdkEvent* eve } else { - nframes_t temp = ifv->get_position() + ifv->get_duration() ; + nframes64_t temp = ifv->get_position() + ifv->get_duration() ; - ifv->set_position((nframes_t) (temp - drag_info.cumulative_x_drag), this) ; - ifv->set_duration((nframes_t) drag_info.cumulative_x_drag, this) ; + ifv->set_position((nframes64_t) (temp - drag_info.cumulative_x_drag), this) ; + ifv->set_duration((nframes64_t) drag_info.cumulative_x_drag, this) ; } } @@ -763,10 +763,10 @@ Editor::imageframe_end_handle_trim_motion(ArdourCanvas::Item* item, GdkEvent* ev { ImageFrameView* ifv = reinterpret_cast (drag_info.data) ; - nframes_t start = 0 ; - nframes_t end = 0 ; - nframes_t pointer_frame = event_frame(event) ; - nframes_t new_dur_val = 0 ; + nframes64_t start = 0 ; + nframes64_t end = 0 ; + nframes64_t pointer_frame = event_frame(event) ; + nframes64_t new_dur_val = 0 ; snap_to(pointer_frame) ; @@ -828,7 +828,7 @@ Editor::imageframe_end_handle_end_trim (ArdourCanvas::Item* item, GdkEvent* even } else { - nframes_t new_duration = (nframes_t)drag_info.cumulative_x_drag ; + nframes64_t new_duration = (nframes64_t)drag_info.cumulative_x_drag ; if((new_duration <= ifv->get_max_duration()) && (new_duration >= ifv->get_min_duration())) { ifv->set_duration(new_duration, this) ; @@ -888,9 +888,9 @@ Editor::markerview_start_handle_trim_motion(ArdourCanvas::Item* item, GdkEvent* { MarkerView* mv = reinterpret_cast (drag_info.data) ; - nframes_t start = 0 ; - nframes_t end = 0 ; - nframes_t pointer_frame = event_frame(event) ; + nframes64_t start = 0 ; + nframes64_t end = 0 ; + nframes64_t pointer_frame = event_frame(event) ; // chekc th eposition of the item is not locked if(!mv->get_position_locked()) @@ -911,7 +911,7 @@ Editor::markerview_start_handle_trim_motion(ArdourCanvas::Item* item, GdkEvent* } // are we getting bigger or smaller? - nframes_t new_dur_val = end - start ; + nframes64_t new_dur_val = end - start ; if(pointer_frame <= drag_info.grab_frame) { @@ -968,10 +968,10 @@ Editor::markerview_start_handle_end_trim(ArdourCanvas::Item* item, GdkEvent* eve } else { - nframes_t temp = mv->get_position() + mv->get_duration() ; + nframes64_t temp = mv->get_position() + mv->get_duration() ; - mv->set_position((nframes_t) (temp - drag_info.cumulative_x_drag), this) ; - mv->set_duration((nframes_t) drag_info.cumulative_x_drag, this) ; + mv->set_position((nframes64_t) (temp - drag_info.cumulative_x_drag), this) ; + mv->set_duration((nframes64_t) drag_info.cumulative_x_drag, this) ; } } @@ -980,10 +980,10 @@ Editor::markerview_end_handle_trim_motion(ArdourCanvas::Item* item, GdkEvent* ev { MarkerView* mv = reinterpret_cast (drag_info.data) ; - nframes_t start = 0 ; - nframes_t end = 0 ; - nframes_t pointer_frame = event_frame(event) ; - nframes_t new_dur_val = 0 ; + nframes64_t start = 0 ; + nframes64_t end = 0 ; + nframes64_t pointer_frame = event_frame(event) ; + nframes64_t new_dur_val = 0 ; snap_to(pointer_frame) ; @@ -1008,7 +1008,7 @@ Editor::markerview_end_handle_trim_motion(ArdourCanvas::Item* item, GdkEvent* ev { // we cant extend beyond the item we are marking ImageFrameView* marked_item = mv->get_marked_item() ; - nframes_t marked_end = marked_item->get_position() + marked_item->get_duration() ; + nframes64_t marked_end = marked_item->get_position() + marked_item->get_duration() ; if(mv->get_max_duration_active() && (new_dur_val > mv->get_max_duration())) { @@ -1062,7 +1062,7 @@ Editor::markerview_end_handle_end_trim (ArdourCanvas::Item* item, GdkEvent* even } else { - nframes_t new_duration = (nframes_t)drag_info.cumulative_x_drag ; + nframes64_t new_duration = (nframes64_t)drag_info.cumulative_x_drag ; mv->set_duration(new_duration, this) ; } } diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc index 60f838f06a..059855ccf5 100644 --- a/gtk2_ardour/editor_markers.cc +++ b/gtk2_ardour/editor_markers.cc @@ -375,8 +375,8 @@ Editor::LocationMarkers::set_name (const string& str) } void -Editor::LocationMarkers::set_position (nframes_t startf, - nframes_t endf) +Editor::LocationMarkers::set_position (nframes64_t startf, + nframes64_t endf) { start->set_position (startf); if (end) { end->set_position (endf); } @@ -390,7 +390,7 @@ Editor::LocationMarkers::set_color_rgba (uint32_t rgba) } void -Editor::mouse_add_new_marker (nframes_t where, bool is_cd, bool is_xrun) +Editor::mouse_add_new_marker (nframes64_t where, bool is_cd, bool is_xrun) { string markername, markerprefix; int flags = (is_cd ? Location::IsCDMarker|Location::IsMark : Location::IsMark); @@ -404,6 +404,9 @@ Editor::mouse_add_new_marker (nframes_t where, bool is_cd, bool is_xrun) if (session) { session->locations()->next_available_name(markername, markerprefix); + if (!is_xrun && !choose_new_marker_name(markername)) { + return; + } Location *location = new Location (where, where, markername, (Location::Flags) flags); session->begin_reversible_command (_("add marker")); XMLNode &before = session->locations()->get_state(); @@ -594,6 +597,8 @@ Editor::build_marker_menu (bool start_or_end) items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Create range to next marker"), mem_fun(*this, &Editor::marker_menu_range_to_next))); + items.push_back (MenuElem (_("Hide"), mem_fun(*this, &Editor::marker_menu_hide))); if (start_or_end) return; items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::marker_menu_rename))); @@ -630,9 +635,11 @@ Editor::build_range_marker_menu (bool loop_or_punch) items.push_back (MenuElem (_("Set Range from Range Selection"), mem_fun(*this, &Editor::marker_menu_set_from_selection))); } + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Export Range"), mem_fun(*this, &Editor::marker_menu_export_range))); items.push_back (SeparatorElem()); - if (! loop_or_punch) { + if (!loop_or_punch) { items.push_back (MenuElem (_("Hide Range"), mem_fun(*this, &Editor::marker_menu_hide))); items.push_back (MenuElem (_("Rename Range"), mem_fun(*this, &Editor::marker_menu_rename))); items.push_back (MenuElem (_("Remove Range"), mem_fun(*this, &Editor::marker_menu_remove))); @@ -807,6 +814,57 @@ Editor::marker_menu_set_playhead () } } +void +Editor::marker_menu_export_range () +{ + Marker* marker; + + if ((marker = reinterpret_cast (marker_menu_item->get_data ("marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + Location* l; + bool is_start; + + if ((l = find_location_from_marker (marker, is_start)) != 0) { + if (l->is_range_marker()) { + export_range (l->start(), l->end()); + } + } +} + +void +Editor::marker_menu_range_to_next () +{ + Marker* marker; + if (!session) { + return; + } + + if ((marker = reinterpret_cast (marker_menu_item->get_data ("marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + Location* l; + bool is_start; + + if ((l = find_location_from_marker (marker, is_start)) == 0) { + return; + } + + nframes_t end = session->locations()->first_mark_after (marker->position()); + + if (end != max_frames) { + string range_name = l->name(); + range_name += "-range"; + + Location* newrange = new Location (marker->position(), end, range_name, Location::IsRangeMarker); + session->locations()->add (newrange); + } +} + void Editor::marker_menu_set_from_playhead () { diff --git a/gtk2_ardour/editor_mixer.cc b/gtk2_ardour/editor_mixer.cc index b732487740..5c9208fcfb 100644 --- a/gtk2_ardour/editor_mixer.cc +++ b/gtk2_ardour/editor_mixer.cc @@ -191,7 +191,7 @@ Editor::update_current_screen () { if (session && session->engine().running()) { - nframes_t frame; + nframes64_t frame; frame = session->audible_frame(); @@ -253,11 +253,7 @@ Editor::update_current_screen () } else { if (frame != last_update_frame) { - if (frame < leftmost_frame || frame > leftmost_frame + current_page_frames()) { - playhead_cursor->canvas_item.hide(); - } else { - playhead_cursor->set_position (frame); - } + playhead_cursor->set_position (frame); } } diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index e1d320e386..384f40fdf6 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -598,6 +598,25 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it bool Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { + Glib::RefPtr canvas_window = const_cast(this)->track_canvas->get_window(); + + if (canvas_window) { + Glib::RefPtr pointer_window; + int x, y; + double wx, wy; + Gdk::ModifierType mask; + + pointer_window = canvas_window->get_pointer (x, y, mask); + + if (pointer_window == track_canvas->get_bin_window()) { + + track_canvas->window_to_world (x, y, wx, wy); + allow_vertical_scroll = true; + } else { + allow_vertical_scroll = false; + } + } + track_canvas->grab_focus(); if (session && session->actively_recording()) { @@ -959,7 +978,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp bool Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type) { - nframes_t where = event_frame (event, 0, 0); + nframes64_t where = event_frame (event, 0, 0); AutomationTimeAxisView* atv = 0; /* no action if we're recording */ @@ -1705,7 +1724,7 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item track_canvas->get_pointer (x, y); } - + if (current_stepping_trackview) { /* don't keep the persistent stepped trackview if the mouse moves */ current_stepping_trackview = 0; @@ -1993,15 +2012,16 @@ Editor::start_fade_in_grab (ArdourCanvas::Item* item, GdkEvent* event) AudioRegionView* arv = static_cast(drag_info.data); - drag_info.pointer_frame_offset = drag_info.grab_frame - ((nframes_t) arv->audio_region()->fade_in()->back()->when + arv->region()->position()); + + drag_info.pointer_frame_offset = drag_info.grab_frame - ((nframes64_t) arv->audio_region()->fade_in()->back()->when + arv->region()->position()); } void Editor::fade_in_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { AudioRegionView* arv = static_cast(drag_info.data); - nframes_t pos; - nframes_t fade_length; + nframes64_t pos; + nframes64_t fade_length; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2043,8 +2063,8 @@ void Editor::fade_in_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) { AudioRegionView* arv = static_cast(drag_info.data); - nframes_t pos; - nframes_t fade_length; + nframes64_t pos; + nframes64_t fade_length; if (drag_info.first_move) return; @@ -2101,15 +2121,15 @@ Editor::start_fade_out_grab (ArdourCanvas::Item* item, GdkEvent* event) AudioRegionView* arv = static_cast(drag_info.data); - drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region()->length() - (nframes_t) arv->audio_region()->fade_out()->back()->when + arv->region()->position()); + drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region()->length() - (nframes64_t) arv->audio_region()->fade_out()->back()->when + arv->region()->position()); } void Editor::fade_out_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { AudioRegionView* arv = static_cast(drag_info.data); - nframes_t pos; - nframes_t fade_length; + nframes64_t pos; + nframes64_t fade_length; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2155,8 +2175,8 @@ Editor::fade_out_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* eve if (drag_info.first_move) return; AudioRegionView* arv = static_cast(drag_info.data); - nframes_t pos; - nframes_t fade_length; + nframes64_t pos; + nframes64_t fade_length; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2239,7 +2259,7 @@ void Editor::cursor_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { Cursor* cursor = (Cursor *) drag_info.data; - nframes_t adjusted_frame; + nframes64_t adjusted_frame; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2362,21 +2382,21 @@ Editor::start_marker_grab (ArdourCanvas::Item* item, GdkEvent* event) void Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { - nframes_t f_delta; + nframes64_t f_delta; Marker* marker = (Marker *) drag_info.data; Location *real_location; Location *copy_location; bool is_start; bool move_both = false; - nframes_t newframe; + nframes64_t newframe; if (drag_info.pointer_frame_offset <= drag_info.current_pointer_frame) { newframe = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; } else { newframe = 0; } - nframes_t next = newframe; + nframes64_t next = newframe; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (newframe, 0, true); @@ -2562,7 +2582,7 @@ void Editor::meter_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { MeterMarker* marker = (MeterMarker *) drag_info.data; - nframes_t adjusted_frame; + nframes64_t adjusted_frame; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2694,7 +2714,7 @@ void Editor::tempo_marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { TempoMarker* marker = (TempoMarker *) drag_info.data; - nframes_t adjusted_frame; + nframes64_t adjusted_frame; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -2866,7 +2886,7 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* cy = min ((double) (cp->line().y_position() + cp->line().height()), cy); //translate cx to frames - nframes_t cx_frames = unit_to_frame (cx); + nframes64_t cx_frames = unit_to_frame (cx); if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()) && !drag_info.x_constrained) { snap_to (cx_frames); @@ -2939,7 +2959,7 @@ Editor::start_line_grab (AutomationLine* line, GdkEvent* event) { double cx; double cy; - nframes_t frame_within_region; + nframes64_t frame_within_region; /* need to get x coordinate in terms of parent (TimeAxisItemView) origin. @@ -2948,7 +2968,7 @@ Editor::start_line_grab (AutomationLine* line, GdkEvent* event) cx = event->button.x; cy = event->button.y; line->parent_group().w2i (cx, cy); - frame_within_region = (nframes_t) floor (cx * frames_per_unit); + frame_within_region = (nframes64_t) floor (cx * frames_per_unit); if (!line->control_points_adjacent (frame_within_region, current_line_drag_info.before, current_line_drag_info.after)) { @@ -3057,7 +3077,7 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event) speed = tv->get_diskstream()->speed(); } - drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed); + drag_info.last_frame_position = (nframes64_t) (clicked_regionview->region()->position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; drag_info.source_trackview = &clicked_regionview->get_time_axis_view(); drag_info.dest_trackview = drag_info.source_trackview; @@ -3106,7 +3126,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.source_trackview = &clicked_regionview->get_time_axis_view(); drag_info.dest_trackview = drag_info.source_trackview; - drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed); + drag_info.last_frame_position = (nframes64_t) (clicked_regionview->region()->position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; // we want a move threshold drag_info.want_move_threshold = true; @@ -3138,7 +3158,7 @@ Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event) speed = tv->get_diskstream()->speed(); } - drag_info.last_frame_position = (nframes_t) (clicked_regionview->region()->position() / speed); + drag_info.last_frame_position = (nframes64_t) (clicked_regionview->region()->position() / speed); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; drag_info.source_trackview = &clicked_regionview->get_time_axis_view(); drag_info.dest_trackview = drag_info.source_trackview; @@ -3164,7 +3184,7 @@ Editor::possibly_copy_regions_during_grab (GdkEvent* event) RegionView* rv; RegionView* nrv; - + rv = (*i); AudioRegionView* arv = dynamic_cast(rv); @@ -3309,7 +3329,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) double x_delta; double y_delta = 0; RegionView* rv = reinterpret_cast (drag_info.data); - nframes_t pending_region_position = 0; + nframes64_t pending_region_position = 0; int32_t pointer_y_span = 0, canvas_pointer_y_span = 0, original_pointer_order; int32_t visible_y_high = 0, visible_y_low = 512; //high meaning higher numbered.. not the height on the screen bool clamp_y_axis = false; @@ -3363,12 +3383,13 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) tracks = tracks |= (0x01 << rtv2->order); } - height_list[rtv2->order] = (*i)->height; + height_list[rtv2->order] = (*i)->current_height(); children = 1; + if ((children_list = rtv2->get_child_list()).size() > 0) { for (TimeAxisView::Children::iterator j = children_list.begin(); j != children_list.end(); ++j) { tracks = tracks |= (0x01 << (rtv2->order + children)); - height_list[rtv2->order + children] = (*j)->height; + height_list[rtv2->order + children] = (*j)->current_height(); numtracks++; children++; } @@ -3496,8 +3517,8 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { - nframes_t sync_frame; - nframes_t sync_offset; + nframes64_t sync_frame; + nframes64_t sync_offset; int32_t sync_dir; pending_region_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -3685,7 +3706,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) tvp2 = trackview_by_y_position (iy1 + y_delta); temp_rtv = dynamic_cast(tvp2); - rv->set_y_position_and_height (0, temp_rtv->height); + rv->set_y_position_and_height (0, temp_rtv->current_height()); /* if you un-comment the following, the region colours will follow the track colours whilst dragging, personally, i think this can confuse things, but never mind. @@ -3837,7 +3858,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event double speed; bool changed_tracks; bool changed_position; - nframes_t where; + nframes64_t where; if (rv->region()->locked()) { ++i; @@ -3852,11 +3873,11 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event speed = dest_rtv->get_diskstream()->speed(); } - changed_position = (drag_info.last_frame_position != (nframes_t) (rv->region()->position()/speed)); + changed_position = (drag_info.last_frame_position != (nframes64_t) (rv->region()->position()/speed)); changed_tracks = (dest_tv != &rv->get_time_axis_view()); if (changed_position && !drag_info.x_constrained) { - where = (nframes_t) (unit_to_frame (ix1) * speed); + where = (nframes64_t) (unit_to_frame (ix1) * speed); } else { where = rv->region()->position(); } @@ -3869,6 +3890,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event boost::shared_ptr new_region; + if (drag_info.copy) { /* we already made a copy */ new_region = rv->region(); @@ -3918,7 +3940,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event /* get the playlist where this drag started. we can't use rv->region()->playlist() because we may have copied the region and it has not been attached to a playlist. */ - + assert ((source_tv = dynamic_cast (&rv->get_time_axis_view()))); assert ((ds = source_tv->get_diskstream())); assert ((from_playlist = ds->playlist())); @@ -4036,7 +4058,7 @@ Editor::create_region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent begin_reversible_command (_("create region")); XMLNode &before = mtv->playlist()->get_state(); - nframes_t start = drag_info.grab_frame; + nframes64_t start = drag_info.grab_frame; snap_to (start, -1); const Meter& m = session->tempo_map().meter_at(start); const Tempo& t = session->tempo_map().tempo_at(start); @@ -4078,28 +4100,28 @@ Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event) if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) { - align_region (rv.region(), SyncPoint, (nframes_t) (where * speed)); + align_region (rv.region(), SyncPoint, (nframes64_t) (where * speed)); } else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) { - align_region (rv.region(), End, (nframes_t) (where * speed)); + align_region (rv.region(), End, (nframes64_t) (where * speed)); } else { - align_region (rv.region(), Start, (nframes_t) (where * speed)); + align_region (rv.region(), Start, (nframes64_t) (where * speed)); } } } } void -Editor::show_verbose_time_cursor (nframes_t frame, double offset, double xpos, double ypos) +Editor::show_verbose_time_cursor (nframes64_t frame, double offset, double xpos, double ypos) { char buf[128]; SMPTE::Time smpte; BBT_Time bbt; int hours, mins; - nframes_t frame_rate; + nframes64_t frame_rate; float secs; if (session == 0) { @@ -4137,7 +4159,7 @@ Editor::show_verbose_time_cursor (nframes_t frame, double offset, double xpos, d break; default: - snprintf (buf, sizeof(buf), "%u", frame); + snprintf (buf, sizeof(buf), "%" PRIi64, frame); break; } @@ -4151,14 +4173,14 @@ Editor::show_verbose_time_cursor (nframes_t frame, double offset, double xpos, d } void -Editor::show_verbose_duration_cursor (nframes_t start, nframes_t end, double offset, double xpos, double ypos) +Editor::show_verbose_duration_cursor (nframes64_t start, nframes64_t end, double offset, double xpos, double ypos) { char buf[128]; SMPTE::Time smpte; BBT_Time sbbt; BBT_Time ebbt; int hours, mins; - nframes_t distance, frame_rate; + nframes64_t distance, frame_rate; float secs; Meter meter_at_start(session->tempo_map().meter_at(start)); @@ -4219,7 +4241,7 @@ Editor::show_verbose_duration_cursor (nframes_t start, nframes_t end, double off break; default: - snprintf (buf, sizeof(buf), "%u", end - start); + snprintf (buf, sizeof(buf), "%" PRIi64, end - start); break; } @@ -4331,8 +4353,8 @@ Editor::cancel_selection () void Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, SelectionOp op) { - nframes_t start = 0; - nframes_t end = 0; + nframes64_t start = 0; + nframes64_t end = 0; if (session == 0) { return; @@ -4389,10 +4411,10 @@ Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, Selection void Editor::drag_selection (ArdourCanvas::Item* item, GdkEvent* event) { - nframes_t start = 0; - nframes_t end = 0; - nframes_t length; - nframes_t pending_position; + nframes64_t start = 0; + nframes64_t end = 0; + nframes64_t length; + nframes64_t pending_position; if (drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { pending_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; @@ -4550,9 +4572,9 @@ Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event) speed = tv->get_diskstream()->speed(); } - nframes_t region_start = (nframes_t) (clicked_regionview->region()->position() / speed); - nframes_t region_end = (nframes_t) (clicked_regionview->region()->last_frame() / speed); - nframes_t region_length = (nframes_t) (clicked_regionview->region()->length() / speed); + nframes64_t region_start = (nframes64_t) (clicked_regionview->region()->position() / speed); + nframes64_t region_end = (nframes64_t) (clicked_regionview->region()->last_frame() / speed); + nframes64_t region_length = (nframes64_t) (clicked_regionview->region()->length() / speed); //drag_info.item = clicked_regionview->get_name_highlight(); drag_info.item = item; @@ -4591,7 +4613,7 @@ void Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) { RegionView* rv = clicked_regionview; - nframes_t frame_delta = 0; + nframes64_t frame_delta = 0; bool left_direction; bool obey_snap = !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()); @@ -4676,7 +4698,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) } case EndTrim: - if ((left_direction == true) && (drag_info.current_pointer_frame > (nframes_t) (rv->region()->last_frame()/speed))) { + if ((left_direction == true) && (drag_info.current_pointer_frame > (nframes64_t) (rv->region()->last_frame()/speed))) { break; } else { for (list::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) { @@ -4704,10 +4726,10 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) switch (trim_op) { case StartTrim: - show_verbose_time_cursor((nframes_t) (rv->region()->position()/speed), 10); + show_verbose_time_cursor((nframes64_t) (rv->region()->position()/speed), 10); break; case EndTrim: - show_verbose_time_cursor((nframes_t) (rv->region()->last_frame()/speed), 10); + show_verbose_time_cursor((nframes64_t) (rv->region()->last_frame()/speed), 10); break; case ContentsTrim: show_verbose_time_cursor(drag_info.current_pointer_frame, 10); @@ -4719,7 +4741,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) } void -Editor::single_contents_trim (RegionView& rv, nframes_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap) +Editor::single_contents_trim (RegionView& rv, nframes64_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap) { boost::shared_ptr region (rv.region()); @@ -4727,7 +4749,7 @@ Editor::single_contents_trim (RegionView& rv, nframes_t frame_delta, bool left_d return; } - nframes_t new_bound; + nframes64_t new_bound; double speed = 1.0; TimeAxisView* tvp = clicked_axisview; @@ -4739,27 +4761,27 @@ Editor::single_contents_trim (RegionView& rv, nframes_t frame_delta, bool left_d if (left_direction) { if (swap_direction) { - new_bound = (nframes_t) (region->position()/speed) + frame_delta; + new_bound = (nframes64_t) (region->position()/speed) + frame_delta; } else { - new_bound = (nframes_t) (region->position()/speed) - frame_delta; + new_bound = (nframes64_t) (region->position()/speed) - frame_delta; } } else { if (swap_direction) { - new_bound = (nframes_t) (region->position()/speed) - frame_delta; + new_bound = (nframes64_t) (region->position()/speed) - frame_delta; } else { - new_bound = (nframes_t) (region->position()/speed) + frame_delta; + new_bound = (nframes64_t) (region->position()/speed) + frame_delta; } } if (obey_snap) { snap_to (new_bound); } - region->trim_start ((nframes_t) (new_bound * speed), this); + region->trim_start ((nframes64_t) (new_bound * speed), this); rv.region_changed (StartChanged); } void -Editor::single_start_trim (RegionView& rv, nframes_t frame_delta, bool left_direction, bool obey_snap) +Editor::single_start_trim (RegionView& rv, nframes64_t frame_delta, bool left_direction, bool obey_snap) { boost::shared_ptr region (rv.region()); @@ -4767,7 +4789,7 @@ Editor::single_start_trim (RegionView& rv, nframes_t frame_delta, bool left_dire return; } - nframes_t new_bound; + nframes64_t new_bound; double speed = 1.0; TimeAxisView* tvp = clicked_axisview; @@ -4778,22 +4800,22 @@ Editor::single_start_trim (RegionView& rv, nframes_t frame_delta, bool left_dire } if (left_direction) { - new_bound = (nframes_t) (region->position()/speed) - frame_delta; + new_bound = (nframes64_t) (region->position()/speed) - frame_delta; } else { - new_bound = (nframes_t) (region->position()/speed) + frame_delta; + new_bound = (nframes64_t) (region->position()/speed) + frame_delta; } if (obey_snap) { snap_to (new_bound, (left_direction ? 0 : 1)); } - region->trim_front ((nframes_t) (new_bound * speed), this); + region->trim_front ((nframes64_t) (new_bound * speed), this); rv.region_changed (Change (LengthChanged|PositionChanged|StartChanged)); } void -Editor::single_end_trim (RegionView& rv, nframes_t frame_delta, bool left_direction, bool obey_snap) +Editor::single_end_trim (RegionView& rv, nframes64_t frame_delta, bool left_direction, bool obey_snap) { boost::shared_ptr region (rv.region()); @@ -4801,7 +4823,7 @@ Editor::single_end_trim (RegionView& rv, nframes_t frame_delta, bool left_direct return; } - nframes_t new_bound; + nframes64_t new_bound; double speed = 1.0; TimeAxisView* tvp = clicked_axisview; @@ -4812,15 +4834,15 @@ Editor::single_end_trim (RegionView& rv, nframes_t frame_delta, bool left_direct } if (left_direction) { - new_bound = (nframes_t) ((region->last_frame() + 1)/speed) - frame_delta; + new_bound = (nframes64_t) ((region->last_frame() + 1)/speed) - frame_delta; } else { - new_bound = (nframes_t) ((region->last_frame() + 1)/speed) + frame_delta; + new_bound = (nframes64_t) ((region->last_frame() + 1)/speed) + frame_delta; } if (obey_snap) { snap_to (new_bound); } - region->trim_end ((nframes_t) (new_bound * speed), this); + region->trim_end ((nframes64_t) (new_bound * speed), this); rv.region_changed (LengthChanged); } @@ -4860,7 +4882,7 @@ void Editor::point_trim (GdkEvent* event) { RegionView* rv = clicked_regionview; - nframes_t new_bound = drag_info.current_pointer_frame; + nframes64_t new_bound = drag_info.current_pointer_frame; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (new_bound); @@ -5008,8 +5030,8 @@ Editor::start_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event, Ran void Editor::drag_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event) { - nframes_t start = 0; - nframes_t end = 0; + nframes64_t start = 0; + nframes64_t end = 0; ArdourCanvas::SimpleRect *crect; switch (range_marker_op) { @@ -5140,8 +5162,8 @@ Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event) if (Keyboard::no_modifier_keys_pressed (&event->button) && range_marker_op != CreateCDMarker) { - nframes_t start; - nframes_t end; + nframes64_t start; + nframes64_t end; start = session->locations()->first_mark_before (drag_info.grab_frame); end = session->locations()->first_mark_after (drag_info.grab_frame); @@ -5191,8 +5213,8 @@ Editor::start_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event) void Editor::drag_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event) { - nframes_t start; - nframes_t end; + nframes64_t start; + nframes64_t end; if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { snap_to (drag_info.current_pointer_frame); @@ -5252,7 +5274,7 @@ Editor::end_mouse_zoom (ArdourCanvas::Item* item, GdkEvent* event) } void -Editor::reposition_zoom_rect (nframes_t start, nframes_t end) +Editor::reposition_zoom_rect (nframes64_t start, nframes64_t end) { double x1 = frame_to_pixel (start); double x2 = frame_to_pixel (end); @@ -5279,8 +5301,8 @@ Editor::start_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event) void Editor::drag_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event) { - nframes_t start; - nframes_t end; + nframes64_t start; + nframes64_t end; double y1; double y2; @@ -5453,7 +5475,7 @@ Editor::end_time_fx (ArdourCanvas::Item* item, GdkEvent* event) return; } - nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region()->position(); + nframes64_t newlen = drag_info.last_pointer_frame - clicked_regionview->region()->position(); float percentage = (double) newlen / (double) clicked_regionview->region()->length(); @@ -5477,7 +5499,7 @@ Editor::end_time_fx (ArdourCanvas::Item* item, GdkEvent* event) } void -Editor::mouse_brush_insert_region (RegionView* rv, nframes_t pos) +Editor::mouse_brush_insert_region (RegionView* rv, nframes64_t pos) { /* no brushing without a useful snap setting */ @@ -5516,7 +5538,7 @@ Editor::mouse_brush_insert_region (RegionView* rv, nframes_t pos) double speed = rtv->get_diskstream()->speed(); XMLNode &before = playlist->get_state(); - playlist->add_region (boost::dynamic_pointer_cast (RegionFactory::create (arv->audio_region())), (nframes_t) (pos * speed)); + playlist->add_region (boost::dynamic_pointer_cast (RegionFactory::create (arv->audio_region())), (nframes64_t) (pos * speed)); XMLNode &after = playlist->get_state(); session->add_command(new MementoCommand(*playlist.get(), &before, &after)); @@ -5528,13 +5550,7 @@ Editor::mouse_brush_insert_region (RegionView* rv, nframes_t pos) gint Editor::track_height_step_timeout () { - struct timeval now; - struct timeval delta; - - gettimeofday (&now, 0); - timersub (&now, &last_track_height_step_timestamp, &delta); - - if (delta.tv_sec * 1000000 + delta.tv_usec > 250000) { /* milliseconds */ + if (get_microseconds() - last_track_height_step_timestamp < 250000) { current_stepping_trackview = 0; return false; } diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index ffe7c1fe16..fd482a9dd6 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,8 @@ #include #include #include +#include + #include #include @@ -109,7 +112,7 @@ Editor::split_region () } void -Editor::split_region_at (nframes_t where) +Editor::split_region_at (nframes64_t where) { RegionSelection rs; @@ -118,7 +121,7 @@ Editor::split_region_at (nframes_t where) } void -Editor::split_regions_at (nframes_t where, RegionSelection& regions) +Editor::split_regions_at (nframes64_t where, RegionSelection& regions) { list > used_playlists; @@ -144,6 +147,8 @@ Editor::split_regions_at (nframes_t where, RegionSelection& regions) snap_to (where); } + cerr << "Split " << regions.size() << " at " << where << endl; + for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) { RegionSelection::iterator tmp; @@ -219,21 +224,44 @@ Editor::remove_clicked_region () void Editor::remove_selected_regions () { - if (selection->regions.empty()) { + RegionSelection rs; + get_regions_for_action (rs); + + if (!session) { + return; + } + + if (rs.empty()) { return; } - /* XXX: should be called remove regions if we're removing more than one */ begin_reversible_command (_("remove region")); + + list > regions_to_remove; + + for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { + // we can't just remove the region(s) in this loop because + // this removes them from the RegionSelection, and they thus + // disappear from underneath the iterator, and the ++i above + // SEGVs in a puzzling fashion. + + // so, first iterate over the regions to be removed from rs and + // add them to the regions_to_remove list, and then + // iterate over the list to actually remove them. + + regions_to_remove.push_back ((*i)->region()); + } + for (list >::iterator rl = regions_to_remove.begin(); rl != regions_to_remove.end(); ++rl) { + boost::shared_ptr playlist = (*rl)->playlist(); + if (!playlist) { + // is this check necessary? + continue; + } - while (!selection->regions.empty()) { - boost::shared_ptr region = selection->regions.front()->region (); - boost::shared_ptr playlist = region->playlist (); - - XMLNode &before = playlist->get_state(); - playlist->remove_region (region); - XMLNode &after = playlist->get_state(); + XMLNode &before = playlist->get_state(); + playlist->remove_region (*rl); + XMLNode &after = playlist->get_state(); session->add_command(new MementoCommand(*playlist, &before, &after)); } @@ -245,7 +273,7 @@ Editor::select_region_for_operation (int dir, TimeAxisView **tv) { RegionView* rv; boost::shared_ptr region; - nframes_t start = 0; + nframes64_t start = 0; if (selection->time.start () == selection->time.end_frame ()) { @@ -288,7 +316,7 @@ Editor::extend_selection_to_end_of_region (bool next) { TimeAxisView *tv; boost::shared_ptr region; - nframes_t start; + nframes64_t start; if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) { return; @@ -316,7 +344,7 @@ Editor::extend_selection_to_start_of_region (bool previous) { TimeAxisView *tv; boost::shared_ptr region; - nframes_t end; + nframes64_t end; if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) { return; @@ -365,8 +393,8 @@ Editor::nudge_backward_release (GdkEventButton* ev) void Editor::nudge_forward (bool next, bool force_playhead) { - nframes_t distance; - nframes_t next_distance; + nframes64_t distance; + nframes64_t next_distance; RegionSelection rs; get_regions_for_action (rs); @@ -441,8 +469,8 @@ Editor::nudge_forward (bool next, bool force_playhead) void Editor::nudge_backward (bool next, bool force_playhead) { - nframes_t distance; - nframes_t next_distance; + nframes64_t distance; + nframes64_t next_distance; RegionSelection rs; get_regions_for_action (rs); @@ -528,7 +556,7 @@ Editor::nudge_backward (bool next, bool force_playhead) void Editor::nudge_forward_capture_offset () { - nframes_t distance; + nframes64_t distance; RegionSelection rs; get_regions_for_action (rs); @@ -558,7 +586,7 @@ Editor::nudge_forward_capture_offset () void Editor::nudge_backward_capture_offset () { - nframes_t distance; + nframes64_t distance; RegionSelection rs; get_regions_for_action (rs); @@ -607,7 +635,7 @@ Editor::move_to_end () void Editor::build_region_boundary_cache () { - nframes_t pos = 0; + nframes64_t pos = 0; vector interesting_points; boost::shared_ptr r; TrackViewList tracks; @@ -650,8 +678,8 @@ Editor::build_region_boundary_cache () while (pos < session->current_end_frame() && !at_end) { - nframes_t rpos; - nframes_t lpos = max_frames; + nframes64_t rpos; + nframes64_t lpos = max_frames; for (vector::iterator p = interesting_points.begin(); p != interesting_points.end(); ++p) { @@ -699,7 +727,7 @@ Editor::build_region_boundary_cache () to sort later. */ - vector::iterator ri; + vector::iterator ri; for (ri = region_boundary_cache.begin(); ri != region_boundary_cache.end(); ++ri) { if (*ri == rpos) { @@ -721,20 +749,20 @@ Editor::build_region_boundary_cache () } boost::shared_ptr -Editor::find_next_region (nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack) +Editor::find_next_region (nframes64_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack) { TrackViewList::iterator i; - nframes_t closest = max_frames; + nframes64_t closest = max_frames; boost::shared_ptr ret; - nframes_t rpos = 0; + nframes64_t rpos = 0; float track_speed; - nframes_t track_frame; + nframes64_t track_frame; RouteTimeAxisView *rtav; for (i = tracks.begin(); i != tracks.end(); ++i) { - nframes_t distance; + nframes64_t distance; boost::shared_ptr r; track_speed = 1.0f; @@ -866,7 +894,7 @@ void Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir) { boost::shared_ptr r; - nframes_t pos = cursor->current_frame; + nframes64_t pos = cursor->current_frame; if (!session) { return; @@ -945,7 +973,7 @@ Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point) void Editor::cursor_to_selection_start (Cursor *cursor) { - nframes_t pos = 0; + nframes64_t pos = 0; RegionSelection rs; get_regions_for_action (rs); @@ -977,7 +1005,7 @@ Editor::cursor_to_selection_start (Cursor *cursor) void Editor::cursor_to_selection_end (Cursor *cursor) { - nframes_t pos = 0; + nframes64_t pos = 0; RegionSelection rs; get_regions_for_action (rs); @@ -1071,7 +1099,7 @@ void Editor::selected_marker_to_region_point (RegionPoint point, int32_t dir) { boost::shared_ptr r; - nframes_t pos; + nframes64_t pos; Location* loc; bool ignored; @@ -1147,7 +1175,7 @@ Editor::selected_marker_to_previous_region_point (RegionPoint point) void Editor::selected_marker_to_selection_start () { - nframes_t pos = 0; + nframes64_t pos = 0; Location* loc; bool ignored; @@ -1186,7 +1214,7 @@ Editor::selected_marker_to_selection_start () void Editor::selected_marker_to_selection_end () { - nframes_t pos = 0; + nframes64_t pos = 0; Location* loc; bool ignored; @@ -1225,8 +1253,8 @@ Editor::selected_marker_to_selection_end () void Editor::scroll_playhead (bool forward) { - nframes_t pos = playhead_cursor->current_frame; - nframes_t delta = (nframes_t) floor (current_page_frames() / 0.8); + nframes64_t pos = playhead_cursor->current_frame; + nframes64_t delta = (nframes64_t) floor (current_page_frames() / 0.8); if (forward) { if (pos == max_frames) { @@ -1258,8 +1286,8 @@ Editor::scroll_playhead (bool forward) void Editor::playhead_backward () { - nframes_t pos; - nframes_t cnt; + nframes64_t pos; + nframes64_t cnt; float prefix; bool was_floating; @@ -1267,15 +1295,15 @@ Editor::playhead_backward () cnt = 1; } else { if (was_floating) { - cnt = (nframes_t) floor (prefix * session->frame_rate ()); + cnt = (nframes64_t) floor (prefix * session->frame_rate ()); } else { - cnt = (nframes_t) prefix; + cnt = (nframes64_t) prefix; } } pos = playhead_cursor->current_frame; - if ((nframes_t) pos < cnt) { + if ((nframes64_t) pos < cnt) { pos = 0; } else { pos -= cnt; @@ -1292,8 +1320,8 @@ Editor::playhead_backward () void Editor::playhead_forward () { - nframes_t pos; - nframes_t cnt; + nframes64_t pos; + nframes64_t cnt; bool was_floating; float prefix; @@ -1301,9 +1329,9 @@ Editor::playhead_forward () cnt = 1; } else { if (was_floating) { - cnt = (nframes_t) floor (prefix * session->frame_rate ()); + cnt = (nframes64_t) floor (prefix * session->frame_rate ()); } else { - cnt = (nframes_t) floor (prefix); + cnt = (nframes64_t) floor (prefix); } } @@ -1362,9 +1390,9 @@ Editor::edit_cursor_backward () cnt = 1; } else { if (was_floating) { - cnt = (nframes_t) floor (prefix * session->frame_rate ()); + cnt = (nframes64_t) floor (prefix * session->frame_rate ()); } else { - cnt = (nframes_t) prefix; + cnt = (nframes64_t) prefix; } } @@ -1384,8 +1412,8 @@ Editor::edit_cursor_backward () void Editor::edit_cursor_forward () { - //nframes_t pos; - nframes_t cnt; + //nframes64_t pos; + nframes64_t cnt; bool was_floating; float prefix; @@ -1393,9 +1421,9 @@ Editor::edit_cursor_forward () cnt = 1; } else { if (was_floating) { - cnt = (nframes_t) floor (prefix * session->frame_rate ()); + cnt = (nframes64_t) floor (prefix * session->frame_rate ()); } else { - cnt = (nframes_t) floor (prefix); + cnt = (nframes64_t) floor (prefix); } } @@ -1408,16 +1436,16 @@ Editor::goto_frame () { float prefix; bool was_floating; - nframes_t frame; + nframes64_t frame; if (get_prefix (prefix, was_floating)) { return; } if (was_floating) { - frame = (nframes_t) floor (prefix * session->frame_rate()); + frame = (nframes64_t) floor (prefix * session->frame_rate()); } else { - frame = (nframes_t) floor (prefix); + frame = (nframes64_t) floor (prefix); } session->request_locate (frame); @@ -1426,19 +1454,19 @@ Editor::goto_frame () void Editor::scroll_backward (float pages) { - nframes_t frame; - nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit); + nframes64_t frame; + nframes64_t one_page = (nframes64_t) rint (canvas_width * frames_per_unit); bool was_floating; float prefix; - nframes_t cnt; + nframes64_t cnt; if (get_prefix (prefix, was_floating)) { - cnt = (nframes_t) floor (pages * one_page); + cnt = (nframes64_t) floor (pages * one_page); } else { if (was_floating) { - cnt = (nframes_t) floor (prefix * session->frame_rate()); + cnt = (nframes64_t) floor (prefix * session->frame_rate()); } else { - cnt = (nframes_t) floor (prefix * one_page); + cnt = (nframes64_t) floor (prefix * one_page); } } @@ -1454,19 +1482,19 @@ Editor::scroll_backward (float pages) void Editor::scroll_forward (float pages) { - nframes_t frame; - nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit); + nframes64_t frame; + nframes64_t one_page = (nframes64_t) rint (canvas_width * frames_per_unit); bool was_floating; float prefix; - nframes_t cnt; + nframes64_t cnt; if (get_prefix (prefix, was_floating)) { - cnt = (nframes_t) floor (pages * one_page); + cnt = (nframes64_t) floor (pages * one_page); } else { if (was_floating) { - cnt = (nframes_t) floor (prefix * session->frame_rate()); + cnt = (nframes64_t) floor (prefix * session->frame_rate()); } else { - cnt = (nframes_t) floor (prefix * one_page); + cnt = (nframes64_t) floor (prefix * one_page); } } @@ -1581,7 +1609,7 @@ Editor::temporal_zoom (gdouble fpu) nfpu = fpu; - new_page_size = (nframes_t) floor (canvas_width * nfpu); + new_page_size = (nframes64_t) floor (canvas_width * nfpu); half_page_size = new_page_size / 2; switch (zoom_focus) { @@ -1681,12 +1709,14 @@ Editor::temporal_zoom (gdouble fpu) } void -Editor::temporal_zoom_region () +Editor::temporal_zoom_region (bool both_axes) { nframes64_t start = max_frames; nframes64_t end = 0; RegionSelection rs; + set tracks; + double top_y_position = DBL_MAX; get_regions_for_action (rs); @@ -1695,12 +1725,20 @@ Editor::temporal_zoom_region () } for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { + if ((*i)->region()->position() < start) { start = (*i)->region()->position(); } + if ((*i)->region()->last_frame() + 1 > end) { end = (*i)->region()->last_frame() + 1; } + + tracks.insert (&((*i)->get_time_axis_view())); + + if ((*i)->get_time_axis_view().y_position < top_y_position) { + top_y_position = (*i)->get_time_axis_view().y_position; + } } /* now comes an "interesting" hack ... make sure we leave a little space @@ -1713,8 +1751,15 @@ Editor::temporal_zoom_region () gint mmwidth = gdk_screen_get_width_mm (screen); double pix_per_mm = (double) pixwidth/ (double) mmwidth; double one_centimeter_in_pixels = pix_per_mm * 10.0; - nframes_t extra_samples = unit_to_frame (one_centimeter_in_pixels); - + + if ((start == 0 && end == 0) || end < start) { + return; + } + + nframes64_t range = end - start; + double new_fpu = (double)range / (double)canvas_width; + nframes64_t extra_samples = (nframes64_t) floor (one_centimeter_in_pixels * new_fpu); + if (start > extra_samples) { start -= extra_samples; } else { @@ -1727,17 +1772,53 @@ Editor::temporal_zoom_region () end = max_frames; } + if (both_axes) { + /* save visual state with track states included, and prevent + set_frames_per_unit() from doing it again. + */ + undo_visual_stack.push_back (current_visual_state(true)); + no_save_visual = true; + } + temporal_zoom_by_frame (start, end, "zoom to region"); + + if (both_axes) { + uint32_t per_track_height = (uint32_t) floor ((canvas_height - 10.0) / tracks.size()); + + /* set visible track heights appropriately */ + + for (set::iterator t = tracks.begin(); t != tracks.end(); ++t) { + (*t)->set_height (per_track_height); + } + + /* hide irrelevant tracks */ + + no_route_list_redisplay = true; + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + if (find (tracks.begin(), tracks.end(), (*i)) == tracks.end()) { + hide_track_in_display (**i, true); + } + } + + no_route_list_redisplay = false; + redisplay_route_list (); + + vertical_adjustment.set_value (std::max (top_y_position - 5.0, 0.0)); + no_save_visual = false; + } + zoomed_to_region = true; + redo_visual_stack.push_back (current_visual_state()); } void -Editor::toggle_zoom_region () +Editor::toggle_zoom_region (bool both_axes) { if (zoomed_to_region) { swap_visual_state (); } else { - temporal_zoom_region (); + temporal_zoom_region (both_axes); } } @@ -1750,8 +1831,8 @@ Editor::temporal_zoom_selection () return; } - nframes_t start = selection->time[clicked_selection].start; - nframes_t end = selection->time[clicked_selection].end; + nframes64_t start = selection->time[clicked_selection].start; + nframes64_t end = selection->time[clicked_selection].end; temporal_zoom_by_frame (start, end, "zoom to selection"); } @@ -1762,12 +1843,13 @@ Editor::temporal_zoom_session () ENSURE_GUI_THREAD (mem_fun (*this, &Editor::temporal_zoom_session)); if (session) { + last_canvas_frame = ((session->current_end_frame() - session->current_start_frame()) + (current_page_frames() / 24)); temporal_zoom_by_frame (session->current_start_frame(), session->current_end_frame(), "zoom to session"); } } void -Editor::temporal_zoom_by_frame (nframes_t start, nframes_t end, const string & op) +Editor::temporal_zoom_by_frame (nframes64_t start, nframes64_t end, const string & op) { if (!session) return; @@ -1775,32 +1857,23 @@ Editor::temporal_zoom_by_frame (nframes_t start, nframes_t end, const string & o return; } - nframes_t range = end - start; + nframes64_t range = end - start; double new_fpu = (double)range / (double)canvas_width; -// double p2 = 1.0; - -// while (p2 < new_fpu) { -// p2 *= 2.0; -// } -// new_fpu = p2; - nframes_t new_page = (nframes_t) floor (canvas_width * new_fpu); - nframes_t middle = (nframes_t) floor( (double)start + ((double)range / 2.0f )); - nframes_t new_leftmost = (nframes_t) floor( (double)middle - ((double)new_page/2.0f)); + nframes64_t new_page = (nframes64_t) floor (canvas_width * new_fpu); + nframes64_t middle = (nframes64_t) floor( (double)start + ((double)range / 2.0f )); + nframes64_t new_leftmost = (nframes64_t) floor( (double)middle - ((double)new_page/2.0f)); - if (new_leftmost > middle) new_leftmost = 0; - -// begin_reversible_command (op); -// session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit)); -// session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu)); -// commit_reversible_command (); + if (new_leftmost > middle) { + new_leftmost = 0; + } reposition_and_zoom (new_leftmost, new_fpu); } void -Editor::temporal_zoom_to_frame (bool coarser, nframes_t frame) +Editor::temporal_zoom_to_frame (bool coarser, nframes64_t frame) { if (!session) return; @@ -1819,7 +1892,7 @@ Editor::temporal_zoom_to_frame (bool coarser, nframes_t frame) if (new_fpu == frames_per_unit) return; - nframes_t new_leftmost = frame - (nframes_t)range_before; + nframes64_t new_leftmost = frame - (nframes64_t)range_before; if (new_leftmost > frame) new_leftmost = 0; @@ -1831,6 +1904,46 @@ Editor::temporal_zoom_to_frame (bool coarser, nframes_t frame) reposition_and_zoom (new_leftmost, new_fpu); } + +bool +Editor::choose_new_marker_name(string &name) { + + if (!Config->get_name_new_markers()) { + /* don't prompt user for a new name */ + return true; + } + + ArdourPrompter dialog (true); + + dialog.set_prompt (_("New Name:")); + + WindowTitle title(Glib::get_application_name()); + title += _("Name New Location Marker"); + + dialog.set_title(title.get_string()); + + dialog.set_name ("MarkNameWindow"); + dialog.set_size_request (250, -1); + dialog.set_position (Gtk::WIN_POS_MOUSE); + + dialog.add_button (Stock::OK, RESPONSE_ACCEPT); + dialog.set_initial_text (name); + + dialog.show (); + + switch (dialog.run ()) { + case RESPONSE_ACCEPT: + break; + default: + return false; + } + + dialog.get_result(name); + return true; + +} + + void Editor::add_location_from_selection () { @@ -1844,8 +1957,8 @@ Editor::add_location_from_selection () return; } - nframes_t start = selection->time[clicked_selection].start; - nframes_t end = selection->time[clicked_selection].end; + nframes64_t start = selection->time[clicked_selection].start; + nframes64_t end = selection->time[clicked_selection].end; session->locations()->next_available_name(rangename,"selection"); Location *location = new Location (start, end, rangename, Location::IsRangeMarker); @@ -1866,6 +1979,9 @@ Editor::add_location_mark (nframes64_t where) select_new_marker = true; session->locations()->next_available_name(markername,"mark"); + if (!choose_new_marker_name(markername)) { + return; + } Location *location = new Location (where, where, markername, Location::IsMark); session->begin_reversible_command (_("add marker")); XMLNode &before = session->locations()->get_state(); @@ -1994,7 +2110,7 @@ Editor::jump_backward_to_mark () void Editor::set_mark () { - nframes_t pos; + nframes64_t pos; float prefix; bool was_floating; string markername; @@ -2003,13 +2119,16 @@ Editor::set_mark () pos = session->audible_frame (); } else { if (was_floating) { - pos = (nframes_t) floor (prefix * session->frame_rate ()); + pos = (nframes64_t) floor (prefix * session->frame_rate ()); } else { - pos = (nframes_t) floor (prefix); + pos = (nframes64_t) floor (prefix); } } session->locations()->next_available_name(markername,"mark"); + if (!choose_new_marker_name(markername)) { + return; + } session->locations()->add (new Location (pos, 0, markername, Location::IsMark), true); } @@ -2089,7 +2208,7 @@ Editor::insert_region_list_drag (boost::shared_ptr region, int x, int y) double wx, wy; double cx, cy; TimeAxisView *tv; - nframes_t where; + nframes64_t where; RouteTimeAxisView *rtv = 0; boost::shared_ptr playlist; @@ -2545,6 +2664,11 @@ Editor::build_interthread_progress_window () interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT); + interthread_progress_window->set_border_width (12); + interthread_progress_window->get_vbox()->set_spacing (6); + + interthread_progress_label.set_alignment (0.5, 0.5); + interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false); interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false); @@ -2577,17 +2701,17 @@ Editor::region_from_selection () return; } - nframes_t start = selection->time[clicked_selection].start; - nframes_t end = selection->time[clicked_selection].end; + nframes64_t start = selection->time[clicked_selection].start; + nframes64_t end = selection->time[clicked_selection].end; - nframes_t selection_cnt = end - start + 1; + nframes64_t selection_cnt = end - start + 1; for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { boost::shared_ptr current; boost::shared_ptr current_r; boost::shared_ptr pl; - nframes_t internal_start; + nframes64_t internal_start; string new_name; if ((pl = (*i)->playlist()) == 0) { @@ -2615,8 +2739,8 @@ Editor::create_region_from_selection (vector >& new_re return; } - nframes_t start = selection->time[clicked_selection].start; - nframes_t end = selection->time[clicked_selection].end; + nframes64_t start = selection->time[clicked_selection].start; + nframes64_t end = selection->time[clicked_selection].end; sort_track_selection (); @@ -2625,7 +2749,7 @@ Editor::create_region_from_selection (vector >& new_re boost::shared_ptr current; boost::shared_ptr current_r; boost::shared_ptr playlist; - nframes_t internal_start; + nframes64_t internal_start; string new_name; if ((playlist = (*i)->playlist()) == 0) { @@ -2762,7 +2886,7 @@ Editor::separate_regions_between (const TimeSelection& ts) sigc::connection c = rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); latest_regionviews.clear (); - playlist->partition ((nframes_t)((*t).start * speed), (nframes_t)((*t).end * speed), true); + playlist->partition ((nframes64_t)((*t).start * speed), (nframes64_t)((*t).end * speed), true); c.disconnect (); @@ -2879,7 +3003,7 @@ Editor::crop_region_to_selection () } void -Editor::crop_region_to (nframes_t start, nframes_t end) +Editor::crop_region_to (nframes64_t start, nframes64_t end) { vector > playlists; boost::shared_ptr playlist; @@ -2913,9 +3037,9 @@ Editor::crop_region_to (nframes_t start, nframes_t end) return; } - nframes_t the_start; - nframes_t the_end; - nframes_t cnt; + nframes64_t the_start; + nframes64_t the_end; + nframes64_t cnt; begin_reversible_command (_("trim to selection")); @@ -2933,7 +3057,7 @@ Editor::crop_region_to (nframes_t start, nframes_t end) if the selection extends beyond the region */ - the_start = max (the_start, region->position()); + the_start = max (the_start, (nframes64_t) region->position()); if (max_frames - the_start < region->length()) { the_end = the_start + region->length() - 1; } else { @@ -2954,7 +3078,7 @@ Editor::crop_region_to (nframes_t start, nframes_t end) void Editor::region_fill_track () { - nframes_t end; + nframes64_t end; RegionSelection rs; get_regions_for_action (rs); @@ -3016,8 +3140,8 @@ Editor::region_fill_selection () TreeModel::iterator i = region_list_display.get_selection()->get_selected(); boost::shared_ptr region = (*i)[region_list_columns.region]; - nframes_t start = selection->time[clicked_selection].start; - nframes_t end = selection->time[clicked_selection].end; + nframes64_t start = selection->time[clicked_selection].start; + nframes64_t end = selection->time[clicked_selection].end; boost::shared_ptr playlist; @@ -3025,7 +3149,7 @@ Editor::region_fill_selection () return; } - nframes_t selection_length = end - start; + nframes64_t selection_length = end - start; float times = (float)selection_length / region->length(); begin_reversible_command (_("fill selection")); @@ -3086,16 +3210,22 @@ Editor::set_sync_point (nframes64_t where, const RegionSelection& rs) void Editor::remove_region_sync () { - begin_reversible_command (_("remove sync")); + RegionSelection rs; - for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { - boost::shared_ptr r = (*i)->region(); - XMLNode &before = r->playlist()->get_state(); - r->clear_sync_position (); - XMLNode &after = r->playlist()->get_state(); - session->add_command(new MementoCommand(*(r->playlist()), &before, &after)); + get_regions_for_action (rs); + + if (rs.empty()) { + return; } + begin_reversible_command (_("remove sync")); + for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { + + XMLNode &before = (*i)->region()->playlist()->get_state(); + (*i)->region()->clear_sync_position (); + XMLNode &after = (*i)->region()->playlist()->get_state(); + session->add_command(new MementoCommand(*((*i)->region()->playlist()), &before, &after)); + } commit_reversible_command (); } @@ -3158,18 +3288,19 @@ struct RegionSortByTime { }; void -Editor::align_selection_relative (RegionPoint point, nframes_t position, const RegionSelection& rs) +Editor::align_selection_relative (RegionPoint point, nframes64_t position, const RegionSelection& rs) { if (rs.empty()) { return; } - nframes_t distance = 0; - nframes_t pos = 0; + nframes64_t distance; + nframes64_t pos = 0; int dir = 0; list sorted; rs.by_position (sorted); + boost::shared_ptr r ((*sorted.begin())->region()); switch (point) { @@ -3246,7 +3377,7 @@ Editor::align_selection_relative (RegionPoint point, nframes_t position, const R } void -Editor::align_selection (RegionPoint point, nframes_t position, const RegionSelection& rs) +Editor::align_selection (RegionPoint point, nframes64_t position, const RegionSelection& rs) { if (rs.empty()) { return; @@ -3262,7 +3393,7 @@ Editor::align_selection (RegionPoint point, nframes_t position, const RegionSele } void -Editor::align_region (boost::shared_ptr region, RegionPoint point, nframes_t position) +Editor::align_region (boost::shared_ptr region, RegionPoint point, nframes64_t position) { begin_reversible_command (_("align region")); align_region_internal (region, point, position); @@ -3270,7 +3401,7 @@ Editor::align_region (boost::shared_ptr region, RegionPoint point, nfram } void -Editor::align_region_internal (boost::shared_ptr region, RegionPoint point, nframes_t position) +Editor::align_region_internal (boost::shared_ptr region, RegionPoint point, nframes64_t position) { XMLNode &before = region->playlist()->get_state(); @@ -3346,8 +3477,8 @@ Editor::trim_region_to_location (const Location& loc, const char* str) } float speed = 1.0; - nframes_t start; - nframes_t end; + nframes64_t start; + nframes64_t end; if (atav->get_diskstream() != 0) { speed = atav->get_diskstream()->speed(); @@ -3537,7 +3668,7 @@ Editor::freeze_route () } void -Editor::bounce_range_selection () +Editor::bounce_range_selection (bool replace) { if (selection->time.empty()) { return; @@ -3545,9 +3676,9 @@ Editor::bounce_range_selection () TrackSelection views = selection->tracks; - nframes_t start = selection->time[clicked_selection].start; - nframes_t end = selection->time[clicked_selection].end; - nframes_t cnt = end - start + 1; + nframes64_t start = selection->time[clicked_selection].start; + nframes64_t end = selection->time[clicked_selection].end; + nframes64_t cnt = end - start + 1; begin_reversible_command (_("bounce range")); @@ -3571,9 +3702,17 @@ Editor::bounce_range_selection () itt.cancel = false; itt.progress = false; - XMLNode &before = playlist->get_state(); - rtv->track()->bounce_range (start, cnt, itt); - XMLNode &after = playlist->get_state(); + XMLNode &before = playlist->get_state(); + boost::shared_ptr r = rtv->track()->bounce_range (start, start+cnt, itt); + + if (replace) { + list ranges; + ranges.push_back (AudioRange (start, start+cnt, 0)); + playlist->cut (ranges); // discard result + playlist->add_region (r, start); + } + + XMLNode &after = playlist->get_state(); session->add_command (new MementoCommand (*playlist, &before, &after)); } @@ -3642,6 +3781,19 @@ Editor::cut_copy (CutCopyOp op) opname = _("clear"); break; } + + /* if we're deleting something, and the mouse is still pressed, + the thing we started a drag for will be gone when we release + the mouse button(s). avoid this. see part 2 at the end of + this function. + */ + + if (op == Cut || op == Clear) { + if (drag_info.item) { + drag_info.item->ungrab (0); + drag_info.item = 0; + } + } cut_buffer->clear (); @@ -3656,6 +3808,8 @@ Editor::cut_copy (CutCopyOp op) Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::really_remove_marker), loc)); } + break_drag (); + return; } @@ -3720,6 +3874,11 @@ Editor::cut_copy (CutCopyOp op) default: break; } + + + if (op == Cut || op == Clear) { + break_drag (); + } } /** Cut, copy or clear selected automation points. @@ -3769,7 +3928,7 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs) vector pmap; - nframes_t first_position = max_frames; + nframes64_t first_position = max_frames; set freezelist; pair::iterator,bool> insert_result; @@ -3780,7 +3939,7 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs) for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) { - first_position = min ((*x)->region()->position(), first_position); + first_position = min ((nframes64_t) (*x)->region()->position(), first_position); if (op == Cut || op == Clear) { boost::shared_ptr pl = (*x)->region()->playlist(); @@ -3934,7 +4093,7 @@ Editor::mouse_paste () } void -Editor::paste_internal (nframes_t position, float times) +Editor::paste_internal (nframes64_t position, float times) { bool commit = false; @@ -4152,9 +4311,9 @@ void Editor::nudge_track (bool use_edit, bool forwards) { boost::shared_ptr playlist; - nframes_t distance; - nframes_t next_distance; - nframes_t start; + nframes64_t distance; + nframes64_t next_distance; + nframes64_t start; if (use_edit) { start = get_preferred_edit_position(); @@ -4442,7 +4601,7 @@ Editor::external_edit_region () } void -Editor::brush (nframes_t pos) +Editor::brush (nframes64_t pos) { RegionSelection sel; RegionSelection rs; @@ -4586,7 +4745,7 @@ Editor::set_fade_length (bool in) } nframes64_t pos = get_preferred_edit_position(); - nframes_t len; + nframes64_t len; char* cmd; if (pos > rv->region()->last_frame() || pos < rv->region()->first_frame()) { @@ -5029,8 +5188,8 @@ Editor::set_loop_from_selection (bool play) return; } - nframes_t start = selection->time[clicked_selection].start; - nframes_t end = selection->time[clicked_selection].end; + nframes64_t start = selection->time[clicked_selection].start; + nframes64_t end = selection->time[clicked_selection].end; set_loop_range (start, end, _("set loop range from selection")); @@ -5100,8 +5259,8 @@ Editor::set_punch_from_selection () return; } - nframes_t start = selection->time[clicked_selection].start; - nframes_t end = selection->time[clicked_selection].end; + nframes64_t start = selection->time[clicked_selection].start; + nframes64_t end = selection->time[clicked_selection].end; set_punch_range (start, end, _("set punch range from selection")); } @@ -5517,14 +5676,13 @@ Editor::tab_to_transient (bool forward) } } } - void Editor::playhead_forward_to_grid () { if (!session) return; nframes64_t pos = playhead_cursor->current_frame; - if (pos < max_frames) { - pos++; + if (pos < max_frames - 1) { + pos += 2; snap_to_internal (pos, 1, false); session->request_locate (pos); } @@ -5536,15 +5694,15 @@ Editor::playhead_backward_to_grid () { if (!session) return; nframes64_t pos = playhead_cursor->current_frame; - if (pos > 1) { - pos--; + if (pos > 2) { + pos -= 2; snap_to_internal (pos, -1, false); session->request_locate (pos); } } void -Editor::set_track_height (TimeAxisView::TrackHeight h) +Editor::set_track_height (uint32_t h) { TrackSelection& ts (selection->tracks); @@ -5560,32 +5718,32 @@ Editor::set_track_height (TimeAxisView::TrackHeight h) void Editor::set_track_height_largest () { - set_track_height (TimeAxisView::Largest); + set_track_height (TimeAxisView::hLargest); } void Editor::set_track_height_large () { - set_track_height (TimeAxisView::Large); + set_track_height (TimeAxisView::hLarge); } void Editor::set_track_height_larger () { - set_track_height (TimeAxisView::Larger); + set_track_height (TimeAxisView::hLarger); } void Editor::set_track_height_normal () { - set_track_height (TimeAxisView::Normal); + set_track_height (TimeAxisView::hNormal); } void Editor::set_track_height_smaller () { - set_track_height (TimeAxisView::Smaller); + set_track_height (TimeAxisView::hSmaller); } void Editor::set_track_height_small () { - set_track_height (TimeAxisView::Small); + set_track_height (TimeAxisView::hSmall); } void @@ -5725,7 +5883,8 @@ Editor::do_insert_time () RadioButton move_button (group, _("Move")); RadioButton split_button (group, _("Split & Later Section Moves")); Label intersect_option_label (_("Intersected regions should:")); - ToggleButton glue_button (_("Move Glued Regions")); + CheckButton glue_button (_("Move Glued Regions")); + CheckButton marker_button (_("Move Markers")); AudioClock clock ("insertTimeClock", true, X_("InsertTimeClock"), true, true, true); HBox clock_box; @@ -5739,6 +5898,7 @@ Editor::do_insert_time () option_box.pack_start (intersect_option_label, false, false); option_box.pack_start (button_box, false, false); option_box.pack_start (glue_button, false, false); + option_box.pack_start (marker_button, false, false); button_box.pack_start (leave_button, false, false); button_box.pack_start (move_button, false, false); @@ -5757,6 +5917,7 @@ Editor::do_insert_time () glue_button.show (); clock.show_all(); clock_box.show (); + marker_button.show (); d.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); d.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); @@ -5768,7 +5929,7 @@ Editor::do_insert_time () return; } - nframes_t distance = clock.current_duration (pos); + nframes64_t distance = clock.current_duration (pos); if (distance == 0) { return; @@ -5784,11 +5945,12 @@ Editor::do_insert_time () opt = SplitIntersected; } - insert_time (pos, distance, opt, glue_button.get_active()); + insert_time (pos, distance, opt, glue_button.get_active(), marker_button.get_active()); } - + void -Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt, bool ignore_music_glue) +Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt, + bool ignore_music_glue, bool markers_too) { bool commit = false; @@ -5819,7 +5981,130 @@ Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt, commit = true; } + if (markers_too) { + bool moved = false; + XMLNode& before (session->locations()->get_state()); + Locations::LocationList copy (session->locations()->list()); + + for (Locations::LocationList::iterator i = copy.begin(); i != copy.end(); ++i) { + + Locations::LocationList::const_iterator tmp; + + if ((*i)->start() >= pos) { + (*i)->set_start ((*i)->start() + frames); + if (!(*i)->is_mark()) { + (*i)->set_end ((*i)->end() + frames); + } + moved = true; + } + } + + if (moved) { + XMLNode& after (session->locations()->get_state()); + session->add_command (new MementoCommand(*session->locations(), &before, &after)); + } + } + if (commit) { commit_reversible_command (); } } + +void +Editor::fit_tracks () +{ + if (selection->tracks.empty()) { + return; + } + + uint32_t child_heights = 0; + + for (TrackSelection::iterator t = selection->tracks.begin(); t != selection->tracks.end(); ++t) { + + if (!(*t)->marked_for_display()) { + continue; + } + + child_heights += ((*t)->effective_height - (*t)->current_height()); + } + + uint32_t h = (uint32_t) floor ((canvas_height - child_heights)/selection->tracks.size()); + double first_y_pos = DBL_MAX; + + undo_visual_stack.push_back (current_visual_state()); + + for (TrackSelection::iterator t = selection->tracks.begin(); t != selection->tracks.end(); ++t) { + (*t)->set_height (h); + first_y_pos = std::min ((*t)->y_position, first_y_pos); + } + + + vertical_adjustment.set_value (first_y_pos); + + redo_visual_stack.push_back (current_visual_state()); +} + +void +Editor::save_visual_state (uint32_t n) +{ + while (visual_states.size() <= n) { + visual_states.push_back (0); + } + + if (visual_states[n] != 0) { + delete visual_states[n]; + } + + visual_states[n] = current_visual_state (true); + gdk_beep (); +} + +void +Editor::goto_visual_state (uint32_t n) +{ + if (visual_states.size() <= n) { + return; + } + + if (visual_states[n] == 0) { + return; + } + + use_visual_state (*visual_states[n]); +} + +void +Editor::start_visual_state_op (uint32_t n) +{ + cerr << "Start\n"; + if (visual_state_op_connection.empty()) { + cerr << "\tqueue\n"; + visual_state_op_connection = Glib::signal_timeout().connect (bind (mem_fun (*this, &Editor::end_visual_state_op), n), 1000); + } +} + +void +Editor::cancel_visual_state_op (uint32_t n) +{ + cerr << "Cancel\n"; + if (!visual_state_op_connection.empty()) { + cerr << "\tgoto\n"; + visual_state_op_connection.disconnect(); + goto_visual_state (n); + } +} + +bool +Editor::end_visual_state_op (uint32_t n) +{ + visual_state_op_connection.disconnect(); + save_visual_state (n); + + PopUp* pup = new PopUp (WIN_POS_MOUSE, 1000, true); + char buf[32]; + snprintf (buf, sizeof (buf), _("Saved view %u"), n+1); + pup->set_text (buf); + pup->touch(); + + return false; // do not call again +} diff --git a/gtk2_ardour/editor_region_list.cc b/gtk2_ardour/editor_region_list.cc index c9067cacfe..54bc71e074 100644 --- a/gtk2_ardour/editor_region_list.cc +++ b/gtk2_ardour/editor_region_list.cc @@ -134,6 +134,18 @@ Editor::add_region_to_region_display (boost::shared_ptr region) } else if (region->whole_file()) { + TreeModel::iterator i; + TreeModel::Children rows = region_list_model->children(); + + for (i = rows.begin(); i != rows.end(); ++i) { + + boost::shared_ptr rr = (*i)[region_list_columns.region]; + + if (region->region_list_equivalent (rr)) { + return; + } + } + row = *(region_list_model->append()); if (missing_source) { c.set_rgb(65535,0,0); // FIXME: error color from style @@ -203,6 +215,18 @@ Editor::add_region_to_region_display (boost::shared_ptr region) break; } } + + TreeModel::iterator ii; + TreeModel::Children subrows = (*i).children(); + + for (ii = subrows.begin(); ii != subrows.end(); ++ii) { + + boost::shared_ptr rrr = (*ii)[region_list_columns.region]; + + if (region->region_list_equivalent (rrr)) { + return; + } + } } if (!found_parent) { @@ -307,6 +331,10 @@ Editor::insert_into_tmp_regionlist(boost::shared_ptr region) void Editor::redisplay_regions () { + if (no_region_list_redisplay) { + return; + } + if (session) { region_list_display.set_model (Glib::RefPtr(0)); diff --git a/gtk2_ardour/editor_route_list.cc b/gtk2_ardour/editor_route_list.cc index 65202cb0db..c12a30ca73 100644 --- a/gtk2_ardour/editor_route_list.cc +++ b/gtk2_ardour/editor_route_list.cc @@ -148,11 +148,18 @@ Editor::handle_gui_changes (const string & what, void *src) ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_gui_changes), what, src)); if (what == "track_height") { + /* make tracks change height while it happens, instead + of on first-idle + */ + track_canvas->update_now (); + redisplay_route_list (); + } + + if (what == "visible_tracks") { redisplay_route_list (); } } - void Editor::remove_route (TimeAxisView *tv) { @@ -162,6 +169,10 @@ Editor::remove_route (TimeAxisView *tv) TreeModel::Children rows = route_display_model->children(); TreeModel::Children::iterator ri; + if (tv == entered_track) { + entered_track = 0; + } + /* Decrement old order keys for tracks `above' the one that is being removed */ for (ri = rows.begin(); ri != rows.end(); ++ri) { TimeAxisView* v = (*ri)[route_display_columns.tv]; @@ -209,11 +220,27 @@ Editor::route_name_changed (TimeAxisView *tv) break; } } - } void -Editor::hide_track_in_display (TimeAxisView& tv) +Editor::update_route_visibility () +{ + TreeModel::Children rows = route_display_model->children(); + TreeModel::Children::iterator i; + + no_route_list_redisplay = true; + + for (i = rows.begin(); i != rows.end(); ++i) { + TimeAxisView *tv = (*i)[route_display_columns.tv]; + (*i)[route_display_columns.visible] = tv->marked_for_display (); + } + + no_route_list_redisplay = false; + redisplay_route_list (); +} + +void +Editor::hide_track_in_display (TimeAxisView& tv, bool temponly) { TreeModel::Children rows = route_display_model->children(); TreeModel::Children::iterator i; @@ -221,6 +248,9 @@ Editor::hide_track_in_display (TimeAxisView& tv) for (i = rows.begin(); i != rows.end(); ++i) { if ((*i)[route_display_columns.tv] == &tv) { (*i)[route_display_columns.visible] = false; + // if (temponly) { + tv.set_marked_for_display (false); + // } break; } } @@ -598,7 +628,6 @@ Editor::route_list_delete (const Gtk::TreeModel::Path& path) redisplay_route_list (); } - void Editor::route_list_display_drag_data_received (const RefPtr& context, int x, int y, @@ -616,7 +645,6 @@ Editor::route_list_display_drag_data_received (const RefPtr& c context->drag_finish (true, false, time); } - RouteTimeAxisView* Editor::get_route_view_by_id (PBD::ID& id) { diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc index 02e8f70727..dc62f669f8 100644 --- a/gtk2_ardour/editor_rulers.cc +++ b/gtk2_ardour/editor_rulers.cc @@ -95,7 +95,7 @@ Editor::initialize_rulers () bool Editor::ruler_scroll (GdkEventScroll* event) { - nframes_t xdelta; + nframes64_t xdelta; int direction = event->direction; bool handled = false; @@ -168,7 +168,7 @@ Editor::ruler_button_press (GdkEventButton* ev) /* need to use the correct x,y, the event lies */ time_canvas_event_box.get_window()->get_pointer (x, y, state); - nframes_t where = leftmost_frame + pixel_to_frame (x); + nframes64_t where = leftmost_frame + pixel_to_frame (x); switch (ev->button) { case 1: @@ -212,7 +212,7 @@ Editor::ruler_button_release (GdkEventButton* ev) stop_canvas_autoscroll(); - nframes_t where = leftmost_frame + pixel_to_frame (x); + nframes64_t where = leftmost_frame + pixel_to_frame (x); switch (ev->button) { case 1: @@ -280,10 +280,10 @@ Editor::ruler_mouse_motion (GdkEventMotion* ev) track_canvas->c2w (x, y, wcx, wcy); track_canvas->w2c (wcx, wcy, cx, cy); - nframes_t where = leftmost_frame + pixel_to_frame (x); + nframes64_t where = leftmost_frame + pixel_to_frame (x); /// ripped from maybe_autoscroll, and adapted to work here - nframes_t rightmost_frame = leftmost_frame + current_page_frames (); + nframes64_t rightmost_frame = leftmost_frame + current_page_frames (); jack_nframes_t frame = pixel_to_frame (cx); @@ -336,7 +336,7 @@ Editor::ruler_mouse_motion (GdkEventMotion* ev) void -Editor::popup_ruler_menu (nframes_t where, ItemType t) +Editor::popup_ruler_menu (nframes64_t where, ItemType t) { using namespace Menu_Helpers; @@ -750,8 +750,8 @@ Editor::update_ruler_visibility () time_canvas_event_box.show_all(); time_button_frame.show_all(); - compute_current_bbt_points (leftmost_frame, leftmost_frame + (nframes_t)(edit_packer.get_width() * frames_per_unit)); - compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + (nframes_t)(edit_packer.get_width() * frames_per_unit)); + compute_current_bbt_points (leftmost_frame, leftmost_frame + (nframes64_t)(edit_packer.get_width() * frames_per_unit)); + compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + (nframes64_t)(edit_packer.get_width() * frames_per_unit)); redisplay_tempo (false); } @@ -765,7 +765,7 @@ Editor::update_just_smpte () return; } - nframes_t rightmost_frame = leftmost_frame + current_page_frames(); + nframes64_t rightmost_frame = leftmost_frame + current_page_frames(); if (ruler_timecode_action->get_active()) { gtk_custom_ruler_set_range (GTK_CUSTOM_RULER(_smpte_ruler), leftmost_frame, rightmost_frame, @@ -792,7 +792,7 @@ Editor::compute_fixed_ruler_scale () void Editor::update_fixed_rulers () { - nframes_t rightmost_frame; + nframes64_t rightmost_frame; if (session == 0) { return; @@ -868,9 +868,9 @@ Editor::_metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble u void Editor::set_smpte_ruler_scale (gdouble lower, gdouble upper) { - nframes_t range; - nframes_t spacer; - nframes_t fr; + nframes64_t range; + nframes64_t spacer; + nframes64_t fr; if (session == 0) { return; @@ -878,13 +878,13 @@ Editor::set_smpte_ruler_scale (gdouble lower, gdouble upper) fr = session->frame_rate(); - if (lower > (spacer = (nframes_t)(128 * Editor::get_current_zoom ()))) { + if (lower > (spacer = (nframes64_t)(128 * Editor::get_current_zoom ()))) { lower = lower - spacer; } else { lower = 0; } upper = upper + spacer; - range = (nframes_t) floor (upper - lower); + range = (nframes64_t) floor (upper - lower); if (range < (2 * session->frames_per_smpte_frame())) { /* 0 - 2 frames */ smpte_ruler_scale = smpte_show_bits; @@ -893,19 +893,19 @@ Editor::set_smpte_ruler_scale (gdouble lower, gdouble upper) } else if (range <= (fr / 4)) { /* 2 frames - 0.250 second */ smpte_ruler_scale = smpte_show_frames; smpte_mark_modulo = 1; - smpte_nmarks = 2 + (range / (nframes_t)session->frames_per_smpte_frame()); + smpte_nmarks = 2 + (range / (nframes64_t)session->frames_per_smpte_frame()); } else if (range <= (fr / 2)) { /* 0.25-0.5 second */ smpte_ruler_scale = smpte_show_frames; smpte_mark_modulo = 2; - smpte_nmarks = 2 + (range / (nframes_t)session->frames_per_smpte_frame()); + smpte_nmarks = 2 + (range / (nframes64_t)session->frames_per_smpte_frame()); } else if (range <= fr) { /* 0.5-1 second */ smpte_ruler_scale = smpte_show_frames; smpte_mark_modulo = 5; - smpte_nmarks = 2 + (range / (nframes_t)session->frames_per_smpte_frame()); + smpte_nmarks = 2 + (range / (nframes64_t)session->frames_per_smpte_frame()); } else if (range <= 2 * fr) { /* 1-2 seconds */ smpte_ruler_scale = smpte_show_frames; smpte_mark_modulo = 10; - smpte_nmarks = 2 + (range / (nframes_t)session->frames_per_smpte_frame()); + smpte_nmarks = 2 + (range / (nframes64_t)session->frames_per_smpte_frame()); } else if (range <= 8 * fr) { /* 2-8 seconds */ smpte_ruler_scale = smpte_show_seconds; smpte_mark_modulo = 1; @@ -956,7 +956,7 @@ Editor::set_smpte_ruler_scale (gdouble lower, gdouble upper) smpte_nmarks = 2 + 24; } else { - /* not possible if nframes_t is a 32 bit quantity */ + /* not possible if nframes64_t is a 32 bit quantity */ smpte_ruler_scale = smpte_show_hours; smpte_mark_modulo = 4; @@ -969,7 +969,7 @@ gint Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars) { nframes_t pos; - nframes_t spacer; + nframes64_t spacer; SMPTE::Time smpte; gchar buf[16]; gint n; @@ -978,7 +978,7 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp return 0; } - if (lower > (spacer = (nframes_t)(128 * Editor::get_current_zoom ()))) { + if (lower > (spacer = (nframes64_t)(128 * Editor::get_current_zoom ()))) { lower = lower - spacer; } else { lower = 0; @@ -1124,7 +1124,7 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp void -Editor::compute_bbt_ruler_scale (nframes_t lower, nframes_t upper) +Editor::compute_bbt_ruler_scale (nframes64_t lower, nframes64_t upper) { if (session == 0) { return; @@ -1219,15 +1219,15 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper char buf[64]; gint n = 0; - nframes_t pos; + nframes64_t pos; BBT_Time next_beat; - nframes_t next_beat_pos; + nframes64_t next_beat_pos; uint32_t beats = 0; uint32_t tick = 0; uint32_t skip; uint32_t t; - nframes_t frame_skip; + nframes64_t frame_skip; double frame_skip_error; double bbt_position_of_helper; double accumulated_error; @@ -1330,7 +1330,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper next_beat_pos = session->tempo_map().frame_time(next_beat); - frame_skip = (nframes_t) floor (frame_skip_error = (session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute())); + frame_skip = (nframes64_t) floor (frame_skip_error = (session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute())); frame_skip_error -= frame_skip; skip = (uint32_t) (Meter::ticks_per_beat / bbt_beat_subdivision); @@ -1348,7 +1348,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper snprintf (buf, sizeof(buf), " "); (*marks)[n].label = g_strdup (buf); - /* Error compensation for float to nframes_t*/ + /* Error compensation for float to nframes64_t*/ accumulated_error += frame_skip_error; if (accumulated_error > 1) { pos += 1; @@ -1422,7 +1422,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper next_beat_pos = session->tempo_map().frame_time(next_beat); - frame_skip = (nframes_t) floor (frame_skip_error = (session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute())); + frame_skip = (nframes64_t) floor (frame_skip_error = (session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute())); frame_skip_error -= frame_skip; skip = (uint32_t) (Meter::ticks_per_beat / bbt_beat_subdivision); @@ -1445,7 +1445,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper (*marks)[n].label = g_strdup (buf); - /* Error compensation for float to nframes_t*/ + /* Error compensation for float to nframes64_t*/ accumulated_error += frame_skip_error; if (accumulated_error > 1) { pos += 1; @@ -1519,7 +1519,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper next_beat_pos = session->tempo_map().frame_time(next_beat); - frame_skip = (nframes_t) floor (frame_skip_error = (session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute())); + frame_skip = (nframes64_t) floor (frame_skip_error = (session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute())); frame_skip_error -= frame_skip; skip = (uint32_t) (Meter::ticks_per_beat / bbt_beat_subdivision); @@ -1542,7 +1542,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper (*marks)[n].label = g_strdup (buf); - /* Error compensation for float to nframes_t*/ + /* Error compensation for float to nframes64_t*/ accumulated_error += frame_skip_error; if (accumulated_error > 1) { pos += 1; @@ -1683,10 +1683,10 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper gint Editor::metric_get_frames (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars) { - nframes_t mark_interval; - nframes_t pos; - nframes_t ilower = (nframes_t) floor (lower); - nframes_t iupper = (nframes_t) floor (upper); + nframes64_t mark_interval; + nframes64_t pos; + nframes64_t ilower = (nframes64_t) floor (lower); + nframes64_t iupper = (nframes64_t) floor (upper); gchar buf[16]; gint nmarks; gint n; @@ -1714,15 +1714,15 @@ Editor::metric_get_frames (GtkCustomRulerMark **marks, gdouble lower, gdouble up } static void -sample_to_clock_parts ( nframes_t sample, - nframes_t sample_rate, +sample_to_clock_parts ( nframes64_t sample, + nframes64_t sample_rate, long *hrs_p, long *mins_p, long *secs_p, long *millisecs_p) { - nframes_t left; + nframes64_t left; long hrs; long mins; long secs; @@ -1748,9 +1748,9 @@ sample_to_clock_parts ( nframes_t sample, void Editor::set_minsec_ruler_scale (gdouble lower, gdouble upper) { - nframes_t range; - nframes_t fr; - nframes_t spacer; + nframes64_t range; + nframes64_t fr; + nframes64_t spacer; if (session == 0) { return; @@ -1759,13 +1759,13 @@ Editor::set_minsec_ruler_scale (gdouble lower, gdouble upper) fr = session->frame_rate(); /* to prevent 'flashing' */ - if (lower > (spacer = (nframes_t)(128 * Editor::get_current_zoom ()))) { + if (lower > (spacer = (nframes64_t)(128 * Editor::get_current_zoom ()))) { lower -= spacer; } else { lower = 0; } upper += spacer; - range = (nframes_t) (upper - lower); + range = (nframes64_t) (upper - lower); if (range < (fr / 50)) { minsec_mark_interval = fr / 1000; /* show 1/1000 seconds */ @@ -1837,7 +1837,7 @@ Editor::set_minsec_ruler_scale (gdouble lower, gdouble upper) minsec_mark_modulo = 2; } else { - /* not possible if nframes_t is a 32 bit quantity */ + /* not possible if nframes64_t is a 32 bit quantity */ minsec_mark_interval = 4 * 60 * 60 * fr; /* show 4 hrs */ } @@ -1847,8 +1847,8 @@ Editor::set_minsec_ruler_scale (gdouble lower, gdouble upper) gint Editor::metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars) { - nframes_t pos; - nframes_t spacer; + nframes64_t pos; + nframes64_t spacer; long hrs, mins, secs, millisecs; gchar buf[16]; gint n; @@ -1858,14 +1858,14 @@ Editor::metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble up } /* to prevent 'flashing' */ - if (lower > (spacer = (nframes_t)(128 * Editor::get_current_zoom ()))) { + if (lower > (spacer = (nframes64_t)(128 * Editor::get_current_zoom ()))) { lower = lower - spacer; } else { lower = 0; } *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * minsec_nmarks); - pos = ((((nframes_t) floor(lower)) + (minsec_mark_interval/2))/minsec_mark_interval) * minsec_mark_interval; + pos = ((((nframes64_t) floor(lower)) + (minsec_mark_interval/2))/minsec_mark_interval) * minsec_mark_interval; switch (minsec_ruler_scale) { case minsec_show_seconds: for (n = 0; n < minsec_nmarks; pos += minsec_mark_interval, ++n) { diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc index 9d0347e0e2..f35391cff5 100644 --- a/gtk2_ardour/editor_selection.cc +++ b/gtk2_ardour/editor_selection.cc @@ -18,7 +18,7 @@ */ #include -#include +#include #include @@ -235,7 +235,7 @@ Editor::set_selected_control_point_from_click (Selection::Operation op, bool no_ /* select this point and any others that it represents */ double y1, y2; - nframes_t x1, x2; + nframes64_t x1, x2; x1 = pixel_to_frame (clicked_control_point->get_x() - 10); x2 = pixel_to_frame (clicked_control_point->get_x() + 10); @@ -449,8 +449,8 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, } else if (op == Selection::Extend) { list results; - nframes_t last_frame; - nframes_t first_frame; + nframes64_t last_frame; + nframes64_t first_frame; bool same_track = false; /* 1. find the last selected regionview in the track that was clicked in */ @@ -909,7 +909,7 @@ Editor::invert_selection () } bool -Editor::select_all_within (nframes_t start, nframes_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op) +Editor::select_all_within (nframes64_t start, nframes64_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op) { list touched; list::size_type n = 0; @@ -1029,8 +1029,8 @@ Editor::select_all_selectables_using_time_selection () return; } - nframes_t start = selection->time[clicked_selection].start; - nframes_t end = selection->time[clicked_selection].end; + nframes64_t start = selection->time[clicked_selection].start; + nframes64_t end = selection->time[clicked_selection].end; if (end - start < 1) { return; @@ -1122,8 +1122,8 @@ Editor::select_all_selectables_using_loop() void Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after) { - nframes_t start; - nframes_t end; + nframes64_t start; + nframes64_t end; list touched; if (after) { @@ -1162,8 +1162,8 @@ Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after) void Editor::select_all_selectables_using_edit (bool after) { - nframes_t start; - nframes_t end; + nframes64_t start; + nframes64_t end; list touched; if (after) { diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc index c9bd50607b..1e5c02f5d8 100644 --- a/gtk2_ardour/editor_tempodisplay.cc +++ b/gtk2_ardour/editor_tempodisplay.cc @@ -210,7 +210,7 @@ Editor::draw_measures () } void -Editor::mouse_add_new_tempo_event (nframes_t frame) +Editor::mouse_add_new_tempo_event (nframes64_t frame) { if (session == 0) { return; @@ -252,7 +252,7 @@ Editor::mouse_add_new_tempo_event (nframes_t frame) } void -Editor::mouse_add_new_meter_event (nframes_t frame) +Editor::mouse_add_new_meter_event (nframes64_t frame) { if (session == 0) { return; diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc index 652973ca26..6628be7116 100644 --- a/gtk2_ardour/editor_timefx.cc +++ b/gtk2_ardour/editor_timefx.cc @@ -279,7 +279,6 @@ Editor::time_fx (RegionSelection& regions, float val, bool pitching) bool realtime = false; bool precise = false; bool peaklock = true; - bool softening = true; bool longwin = false; bool shortwin = false; string txt; @@ -314,7 +313,6 @@ Editor::time_fx (RegionSelection& regions, float val, bool pitching) if (realtime) options |= RubberBandStretcher::OptionProcessRealTime; if (precise) options |= RubberBandStretcher::OptionStretchPrecise; if (!peaklock) options |= RubberBandStretcher::OptionPhaseIndependent; - if (!softening) options |= RubberBandStretcher::OptionPhasePeakLocked; if (longwin) options |= RubberBandStretcher::OptionWindowLong; if (shortwin) options |= RubberBandStretcher::OptionWindowShort; diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc index ab02a051c2..7d8f29cce4 100644 --- a/gtk2_ardour/engine_dialog.cc +++ b/gtk2_ardour/engine_dialog.cc @@ -452,11 +452,19 @@ EngineControl::build_command_line (vector& cmd) } else if (str == _("Playback/Recording on 2 Devices")) { + string input_device = get_device_name (driver, input_device_combo.get_active_text()); + string output_device = get_device_name (driver, output_device_combo.get_active_text()); + + if (input_device.empty() || output_device.empty()) { + cmd.clear (); + return; + } + cmd.push_back ("-C"); - cmd.push_back (get_device_name (driver, input_device_combo.get_active_text())); + cmd.push_back (input_device); cmd.push_back ("-P"); - cmd.push_back (get_device_name (driver, output_device_combo.get_active_text())); - + cmd.push_back (output_device); + } else if (str == _("Playback only")) { cmd.push_back ("-P"); } else if (str == _("Recording only")) { @@ -478,8 +486,15 @@ EngineControl::build_command_line (vector& cmd) if (using_alsa) { if (audio_mode_combo.get_active_text() != _("Playback/Recording on 2 Devices")) { + + string device = get_device_name (driver, interface_combo.get_active_text()); + if (device.empty()) { + cmd.clear (); + return; + } + cmd.push_back ("-d"); - cmd.push_back (get_device_name (driver, interface_combo.get_active_text())); + cmd.push_back (device); } if (hw_meter_button.get_active()) { @@ -513,8 +528,15 @@ EngineControl::build_command_line (vector& cmd) #ifdef __APPLE__ // note: older versions of the CoreAudio JACK backend use -n instead of -d here + + string device = get_device_name (driver, interface_combo.get_active_text()); + if (device.empty()) { + cmd.clear (); + return; + } + cmd.push_back ("-d"); - cmd.push_back (get_device_name (driver, interface_combo.get_active_text())); + cmd.push_back (device); #endif } else if (using_oss) { @@ -544,6 +566,10 @@ EngineControl::setup_engine () std::string cwd = "/tmp"; build_command_line (args); + + if (args.empty()) { + return 1; // try again + } Glib::ustring jackdrc_path = Glib::get_home_dir(); jackdrc_path += "/.jackdrc"; @@ -990,6 +1016,15 @@ EngineControl::get_device_name (const string& driver, const string& human_readab vector::iterator n; vector::iterator i; + if (human_readable.empty()) { + /* this can happen if the user's .ardourrc file has a device name from + another computer system in it + */ + MessageDialog msg (_("You need to choose an audio device first.")); + msg.run (); + return string(); + } + if (backend_devs.empty()) { return human_readable; } @@ -1001,12 +1036,9 @@ EngineControl::get_device_name (const string& driver, const string& human_readab } if (i == devices[driver].end()) { - fatal << string_compose (_("programming error: %1"), "true hardware name for ID missing") << endmsg; - /*NOTREACHED*/ + warning << string_compose (_("Audio device \"%1\" not known on this computer."), human_readable) << endmsg; } - /* keep gcc happy */ - return string(); } diff --git a/gtk2_ardour/export_dialog.cc b/gtk2_ardour/export_dialog.cc index db741d66ed..ef99bf43bf 100644 --- a/gtk2_ardour/export_dialog.cc +++ b/gtk2_ardour/export_dialog.cc @@ -975,8 +975,9 @@ ExportDialog::do_export () progress_connection = Glib::signal_timeout().connect (mem_fun(*this, &ExportDialog::progress_timeout), 100); cancel_label.set_text (_("Stop Export")); + session->pre_export (); export_data(); - + progress_connection.disconnect (); end_dialog (); } @@ -996,7 +997,7 @@ ExportDialog::end_dialog () } } - session->finalize_audio_export (); + session->finalize_export (); hide_all (); @@ -1017,6 +1018,7 @@ ExportDialog::start_export () */ if (file_entry.get_text().length() == 0) { + sys::path export_file_path = session->session_directory().export_path(); if (!wants_dir()) { @@ -1229,7 +1231,7 @@ ExportDialog::initSpec(string &filepath) { spec.path = filepath; spec.progress = 0; - spec.running = true; + spec.running = false; spec.stop = false; spec.port_map.clear(); diff --git a/gtk2_ardour/export_range_markers_dialog.cc b/gtk2_ardour/export_range_markers_dialog.cc index 8bb93eb4aa..bf2f0e3989 100644 --- a/gtk2_ardour/export_range_markers_dialog.cc +++ b/gtk2_ardour/export_range_markers_dialog.cc @@ -81,8 +81,6 @@ ExportRangeMarkersDialog::process_range_markers_export(Locations::LocationList& spec.start_frame = currentLocation->start(); spec.end_frame = currentLocation->end(); - getSession().request_locate(spec.start_frame, false); - if (getSession().start_export(spec)){ // if export fails return; @@ -100,6 +98,8 @@ ExportRangeMarkersDialog::process_range_markers_export(Locations::LocationList& } current_range_marker_index++; + + getSession().stop_export (spec); } } diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc index 0e51b7a68c..107b0eedfc 100644 --- a/gtk2_ardour/gain_meter.cc +++ b/gtk2_ardour/gain_meter.cc @@ -57,42 +57,49 @@ using namespace Gtk; using namespace sigc; using namespace std; -sigc::signal GainMeter::ResetAllPeakDisplays; -sigc::signal GainMeter::ResetGroupPeakDisplays; -Glib::RefPtr GainMeter::slider; -Glib::RefPtr GainMeter::rail; -map > GainMeter::metric_pixmaps; +sigc::signal GainMeterBase::ResetAllPeakDisplays; +sigc::signal GainMeterBase::ResetGroupPeakDisplays; -int +map > GainMeter::metric_pixmaps; +Glib::RefPtr GainMeter::slider; + + +void GainMeter::setup_slider_pix () { - slider = ::get_icon ("fader_belt"); - return 0; + if ((slider = ::get_icon ("fader_belt")) == 0) { + throw failed_constructor(); + } } -GainMeter::GainMeter (boost::shared_ptr io, Session& s) +GainMeterBase::GainMeterBase (boost::shared_ptr io, Session& s, + const Glib::RefPtr& pix, + bool horizontal) : _io (io), _session (s), - gain_slider (0), // 0.781787 is the value needed for gain to be set to 0. gain_adjustment (0.781787, 0.0, 1.0, 0.01, 0.1), gain_automation_style_button (""), gain_automation_state_button ("") { - if (slider == 0) { - setup_slider_pix (); - } - ignore_toggle = false; meter_menu = 0; next_release_selects = false; style_changed = true; + _width = Wide; - gain_slider = manage (new VSliderController (slider, - &gain_adjustment, - *_io->gain_control().get(), - false)); + if (horizontal) { + gain_slider = manage (new HSliderController (pix, + &gain_adjustment, + _io->gain_control(), + false)); + } else { + gain_slider = manage (new VSliderController (pix, + &gain_adjustment, + _io->gain_control(), + false)); + } level_meter = new LevelMeter(_io, _session); @@ -107,11 +114,6 @@ GainMeter::GainMeter (boost::shared_ptr io, Session& s) gain_display.signal_focus_in_event().connect (mem_fun (*this, &GainMeter::gain_focused), false); gain_display.signal_focus_out_event().connect (mem_fun (*this, &GainMeter::gain_focused), false); - gain_display_box.set_name ("MeterMetricsStrip"); - gain_display_box.set_homogeneous (true); - gain_display_box.set_spacing (2); - gain_display_box.pack_start (gain_display, true, true); - peak_display.set_name ("MixerStripPeakDisplay"); // peak_display.set_has_frame (false); // peak_display.set_editable (false); @@ -120,7 +122,644 @@ GainMeter::GainMeter (boost::shared_ptr io, Session& s) peak_display.set_label (_("-inf")); peak_display.unset_flags (Gtk::CAN_FOCUS); - meter_metric_area.set_name ("MeterMetricsStrip"); + gain_automation_style_button.set_name ("MixerAutomationModeButton"); + gain_automation_state_button.set_name ("MixerAutomationPlaybackButton"); + + ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_state_button, _("Fader automation mode")); + ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_style_button, _("Fader automation type")); + + gain_automation_style_button.unset_flags (Gtk::CAN_FOCUS); + gain_automation_state_button.unset_flags (Gtk::CAN_FOCUS); + + gain_automation_state_button.set_size_request(15, 15); + gain_automation_style_button.set_size_request(15, 15); + + + + + + boost::shared_ptr r; + + if ((r = boost::dynamic_pointer_cast (_io)) != 0) { + + if (!r->is_hidden()) { + + using namespace Menu_Helpers; + + gain_astate_menu.items().push_back (MenuElem (_("Manual"), + bind (mem_fun (*_io, &IO::set_parameter_automation_state), + Parameter(GainAutomation), (AutoState) Off))); + gain_astate_menu.items().push_back (MenuElem (_("Play"), + bind (mem_fun (*_io, &IO::set_parameter_automation_state), + Parameter(GainAutomation), (AutoState) Play))); + gain_astate_menu.items().push_back (MenuElem (_("Write"), + bind (mem_fun (*_io, &IO::set_parameter_automation_state), + Parameter(GainAutomation), (AutoState) Write))); + gain_astate_menu.items().push_back (MenuElem (_("Touch"), + bind (mem_fun (*_io, &IO::set_parameter_automation_state), + Parameter(GainAutomation), (AutoState) Touch))); + + gain_astyle_menu.items().push_back (MenuElem (_("Trim"))); + gain_astyle_menu.items().push_back (MenuElem (_("Abs"))); + + gain_astate_menu.set_name ("ArdourContextMenu"); + gain_astyle_menu.set_name ("ArdourContextMenu"); + + gain_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_style_button_event), false); + gain_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_state_button_event), false); + + r->gain_control()->list()->automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed)); + r->gain_control()->list()->automation_style_changed.connect (mem_fun(*this, &GainMeter::gain_automation_style_changed)); + + gain_automation_state_changed (); + } + } + + _io->gain_control()->Changed.connect (mem_fun(*this, &GainMeterBase::gain_changed)); + + gain_adjustment.signal_value_changed().connect (mem_fun(*this, &GainMeterBase::gain_adjusted)); + peak_display.signal_button_release_event().connect (mem_fun(*this, &GainMeterBase::peak_button_release), false); + gain_display.signal_key_press_event().connect (mem_fun(*this, &GainMeterBase::gain_key_press), false); + + gain_changed (); + show_gain (); + + update_gain_sensitive (); + + ResetAllPeakDisplays.connect (mem_fun(*this, &GainMeterBase::reset_peak_display)); + ResetGroupPeakDisplays.connect (mem_fun(*this, &GainMeterBase::reset_group_peak_display)); + + UI::instance()->theme_changed.connect (mem_fun(*this, &GainMeterBase::on_theme_changed)); + ColorsChanged.connect (bind(mem_fun (*this, &GainMeterBase::color_handler), false)); + DPIReset.connect (bind(mem_fun (*this, &GainMeterBase::color_handler), true)); +} + +GainMeterBase::~GainMeterBase () +{ + if (meter_menu) { + delete meter_menu; + } + + if (level_meter) { + delete level_meter; + } +} + +void +GainMeterBase::hide_all_meters () +{ + level_meter->hide_meters(); +} + +void +GainMeter::hide_all_meters () +{ + bool remove_metric_area = false; + + GainMeterBase::hide_all_meters (); + + if (remove_metric_area) { + if (meter_metric_area.get_parent()) { + level_meter->remove (meter_metric_area); + } + } +} + +void +GainMeterBase::setup_meters (int len) +{ + level_meter->setup_meters(len, 5); +} + +void +GainMeter::setup_meters (int len) +{ + if (!meter_metric_area.get_parent()) { + level_meter->pack_end (meter_metric_area, false, false); + meter_metric_area.show_all (); + } + GainMeterBase::setup_meters (len); +} + +bool +GainMeterBase::gain_key_press (GdkEventKey* ev) +{ + if (key_is_legal_for_numeric_entry (ev->keyval)) { + /* drop through to normal handling */ + return false; + } + /* illegal key for gain entry */ + return true; +} + +bool +GainMeterBase::peak_button_release (GdkEventButton* ev) +{ + /* reset peak label */ + + if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier|Keyboard::TertiaryModifier)) { + ResetAllPeakDisplays (); + } else if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { + boost::shared_ptr r; + + if ((r = boost::dynamic_pointer_cast (_io)) != 0) { + ResetGroupPeakDisplays (r->mix_group()); + } + } else { + reset_peak_display (); + } + + return true; +} + +void +GainMeterBase::reset_peak_display () +{ + boost::shared_ptr r; + + if ((r = boost::dynamic_pointer_cast (_io)) != 0) { + r->peak_meter().reset_max(); + } + + level_meter->clear_meters(); + max_peak = -INFINITY; + peak_display.set_label (_("-Inf")); + peak_display.set_name ("MixerStripPeakDisplay"); +} + +void +GainMeterBase::reset_group_peak_display (RouteGroup* group) +{ + boost::shared_ptr r; + + if ((r = boost::dynamic_pointer_cast (_io)) != 0) { + if (group == r->mix_group()) { + reset_peak_display (); + } + } +} + +void +GainMeterBase::popup_meter_menu (GdkEventButton *ev) +{ + using namespace Menu_Helpers; + + if (meter_menu == 0) { + meter_menu = new Gtk::Menu; + MenuList& items = meter_menu->items(); + + items.push_back (MenuElem ("-inf .. +0dBFS")); + items.push_back (MenuElem ("-10dB .. +0dBFS")); + items.push_back (MenuElem ("-4 .. +0dBFS")); + items.push_back (SeparatorElem()); + items.push_back (MenuElem ("-inf .. -2dBFS")); + items.push_back (MenuElem ("-10dB .. -2dBFS")); + items.push_back (MenuElem ("-4 .. -2dBFS")); + } + + meter_menu->popup (1, ev->time); +} + +bool +GainMeterBase::gain_focused (GdkEventFocus* ev) +{ + if (ev->in) { + gain_display.select_region (0, -1); + } else { + gain_display.select_region (0, 0); + } + return false; +} + +void +GainMeterBase::gain_activated () +{ + float f; + + if (sscanf (gain_display.get_text().c_str(), "%f", &f) == 1) { + + /* clamp to displayable values */ + + f = min (f, 6.0f); + + _io->gain_control()->set_value (dB_to_coefficient(f)); + + if (gain_display.has_focus()) { + PublicEditor::instance().reset_focus(); + } + } +} + +void +GainMeterBase::show_gain () +{ + char buf[32]; + + float v = gain_adjustment.get_value(); + + if (v == 0.0) { + strcpy (buf, _("-inf")); + } else { + snprintf (buf, 32, "%.1f", coefficient_to_dB (slider_position_to_gain (v))); + } + + gain_display.set_text (buf); +} + +void +GainMeterBase::gain_adjusted () +{ + if (!ignore_toggle) { + _io->gain_control()->set_value (slider_position_to_gain (gain_adjustment.get_value())); + } + show_gain (); +} + +void +GainMeterBase::effective_gain_display () +{ + gfloat value = gain_to_slider_position (_io->effective_gain()); + + if (gain_adjustment.get_value() != value) { + ignore_toggle = true; + gain_adjustment.set_value (value); + ignore_toggle = false; + } +} + +void +GainMeterBase::gain_changed () +{ + Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &GainMeterBase::effective_gain_display)); +} + +void +GainMeterBase::set_meter_strip_name (const char * name) +{ + meter_metric_area.set_name (name); +} + +void +GainMeterBase::set_fader_name (const char * name) +{ + gain_slider->set_name (name); +} + +void +GainMeterBase::update_gain_sensitive () +{ + static_cast(gain_slider)->set_sensitive (!(_io->gain_control()->list()->automation_state() & Play)); +} + + +static MeterPoint +next_meter_point (MeterPoint mp) +{ + switch (mp) { + case MeterInput: + return MeterPreFader; + break; + + case MeterPreFader: + return MeterPostFader; + break; + + case MeterPostFader: + return MeterInput; + break; + } + /*NOTREACHED*/ + return MeterInput; +} + +gint +GainMeterBase::meter_press(GdkEventButton* ev) +{ + boost::shared_ptr _route; + + wait_for_release = false; + + if ((_route = boost::dynamic_pointer_cast(_io)) == 0) { + return FALSE; + } + + if (!ignore_toggle) { + + if (Keyboard::is_context_menu_event (ev)) { + + // no menu at this time. + + } else { + + if (ev->button == 2) { + + // Primary-button2 click is the midi binding click + // button2-click is "momentary" + + if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) { + wait_for_release = true; + old_meter_point = _route->meter_point (); + } + } + + if (ev->button == 1 || ev->button == 2) { + + if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) { + + /* Primary+Tertiary-click applies change to all routes */ + + _session.begin_reversible_command (_("meter point change")); + Session::GlobalMeteringStateCommand *cmd = new Session::GlobalMeteringStateCommand (_session, this); + _session.foreach_route (this, &GainMeterBase::set_meter_point, next_meter_point (_route->meter_point())); + cmd->mark(); + _session.add_command (cmd); + _session.commit_reversible_command (); + + + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { + + /* Primary-click: solo mix group. + NOTE: Primary-button2 is MIDI learn. + */ + + if (ev->button == 1) { + _session.begin_reversible_command (_("meter point change")); + Session::GlobalMeteringStateCommand *cmd = new Session::GlobalMeteringStateCommand (_session, this); + set_mix_group_meter_point (*_route, next_meter_point (_route->meter_point())); + cmd->mark(); + _session.add_command (cmd); + _session.commit_reversible_command (); + } + + } else { + + /* click: change just this route */ + + // XXX no undo yet + + _route->set_meter_point (next_meter_point (_route->meter_point()), this); + } + } + } + } + + return true; + +} + +gint +GainMeterBase::meter_release(GdkEventButton* ev) +{ + if(!ignore_toggle){ + if (wait_for_release){ + wait_for_release = false; + + boost::shared_ptr r; + + if ((r = boost::dynamic_pointer_cast(_io)) != 0) { + set_meter_point (*r, old_meter_point); + } + } + } + + return true; +} + +void +GainMeterBase::set_meter_point (Route& route, MeterPoint mp) +{ + route.set_meter_point (mp, this); +} + +void +GainMeterBase::set_mix_group_meter_point (Route& route, MeterPoint mp) +{ + RouteGroup* mix_group; + + if((mix_group = route.mix_group()) != 0){ + mix_group->apply (&Route::set_meter_point, mp, this); + } else { + route.set_meter_point (mp, this); + } +} + +void +GainMeterBase::meter_point_clicked () +{ + boost::shared_ptr r; + + if ((r = boost::dynamic_pointer_cast (_io)) != 0) { + /* WHAT? */ + } +} + +gint +GainMeterBase::start_gain_touch (GdkEventButton* ev) +{ + _io->gain_control()->list()->start_touch (); + return FALSE; +} + +gint +GainMeterBase::end_gain_touch (GdkEventButton* ev) +{ + _io->gain_control()->list()->stop_touch (); + return FALSE; +} + +gint +GainMeterBase::gain_automation_state_button_event (GdkEventButton *ev) +{ + if (ev->type == GDK_BUTTON_RELEASE) { + return TRUE; + } + + switch (ev->button) { + case 1: + gain_astate_menu.popup (1, ev->time); + break; + default: + break; + } + + return TRUE; +} + +gint +GainMeterBase::gain_automation_style_button_event (GdkEventButton *ev) +{ + if (ev->type == GDK_BUTTON_RELEASE) { + return TRUE; + } + + switch (ev->button) { + case 1: + gain_astyle_menu.popup (1, ev->time); + break; + default: + break; + } + return TRUE; +} + +string +GainMeterBase::astate_string (AutoState state) +{ + return _astate_string (state, false); +} + +string +GainMeterBase::short_astate_string (AutoState state) +{ + return _astate_string (state, true); +} + +string +GainMeterBase::_astate_string (AutoState state, bool shrt) +{ + string sstr; + + switch (state) { + case Off: + sstr = (shrt ? "M" : _("M")); + break; + case Play: + sstr = (shrt ? "P" : _("P")); + break; + case Touch: + sstr = (shrt ? "T" : _("T")); + break; + case Write: + sstr = (shrt ? "W" : _("W")); + break; + } + + return sstr; +} + +string +GainMeterBase::astyle_string (AutoStyle style) +{ + return _astyle_string (style, false); +} + +string +GainMeterBase::short_astyle_string (AutoStyle style) +{ + return _astyle_string (style, true); +} + +string +GainMeterBase::_astyle_string (AutoStyle style, bool shrt) +{ + if (style & Trim) { + return _("Trim"); + } else { + /* XXX it might different in different languages */ + + return (shrt ? _("Abs") : _("Abs")); + } +} + +void +GainMeterBase::gain_automation_style_changed () +{ + switch (_width) { + case Wide: + gain_automation_style_button.set_label (astyle_string(_io->gain_control()->list()->automation_style())); + break; + case Narrow: + gain_automation_style_button.set_label (short_astyle_string(_io->gain_control()->list()->automation_style())); + break; + } +} + +void +GainMeterBase::gain_automation_state_changed () +{ + ENSURE_GUI_THREAD(mem_fun(*this, &GainMeterBase::gain_automation_state_changed)); + + bool x; + + switch (_width) { + case Wide: + gain_automation_state_button.set_label (astate_string(_io->gain_control()->list()->automation_state())); + break; + case Narrow: + gain_automation_state_button.set_label (short_astate_string(_io->gain_control()->list()->automation_state())); + break; + } + + x = (_io->gain_control()->list()->automation_state() != Off); + + if (gain_automation_state_button.get_active() != x) { + ignore_toggle = true; + gain_automation_state_button.set_active (x); + ignore_toggle = false; + } + + update_gain_sensitive (); + + /* start watching automation so that things move */ + + gain_watching.disconnect(); + + if (x) { + gain_watching = ARDOUR_UI::RapidScreenUpdate.connect (mem_fun (*this, &GainMeterBase::effective_gain_display)); + } +} + +void +GainMeterBase::update_meters() +{ + char buf[32]; + float mpeak = level_meter->update_meters(); + + if (mpeak > max_peak) { + max_peak = mpeak; + if (mpeak <= -200.0f) { + peak_display.set_label (_("-inf")); + } else { + snprintf (buf, sizeof(buf), "%.1f", mpeak); + peak_display.set_label (buf); + } + + if (mpeak >= 0.0f) { + peak_display.set_name ("MixerStripPeakDisplayPeak"); + } + } +} + +void GainMeterBase::color_handler(bool dpi) +{ + color_changed = true; + dpi_changed = (dpi) ? true : false; + setup_meters(); +} + +void +GainMeterBase::set_width (Width w, int len) +{ + _width = w; + level_meter->setup_meters (len); +} + + +void +GainMeterBase::on_theme_changed() +{ + style_changed = true; +} + +GainMeter::GainMeter (boost::shared_ptr io, Session& s) + : GainMeterBase (io, s, slider, false) +{ + + gain_display_box.set_homogeneous (true); + gain_display_box.set_spacing (2); + gain_display_box.pack_start (gain_display, true, true); + + meter_metric_area.set_name ("AudioTrackMetrics"); set_size_request_to_display_given_text (meter_metric_area, "-50", 0, 0); gain_automation_style_button.set_name ("MixerAutomationModeButton"); @@ -143,17 +782,12 @@ GainMeter::GainMeter (boost::shared_ptr io, Session& s) fader_vbox->pack_start (*fader_centering_box, false, false, 0); hbox.set_spacing (2); + hbox.pack_start (*fader_vbox, true, true); - if (_io->default_type() == ARDOUR::DataType::AUDIO) { - hbox.pack_start (*fader_vbox, true, true); - } - - set_width (Narrow); - - Route* r; - - if ((r = dynamic_cast (_io.get())) != 0) { + boost::shared_ptr r; + if ((r = boost::dynamic_pointer_cast (_io)) != 0) { + /* if we have a non-hidden route (ie. we're not the click or the auditioner), pack some route-dependent stuff. @@ -162,35 +796,9 @@ GainMeter::GainMeter (boost::shared_ptr io, Session& s) gain_display_box.pack_end (peak_display, true, true); hbox.pack_end (*level_meter, true, true); - using namespace Menu_Helpers; - - gain_astate_menu.items().push_back (MenuElem (_("Manual"), - bind (mem_fun (*_io, &IO::set_parameter_automation_state), - Parameter(GainAutomation), (AutoState) Off))); - gain_astate_menu.items().push_back (MenuElem (_("Play"), - bind (mem_fun (*_io, &IO::set_parameter_automation_state), - Parameter(GainAutomation), (AutoState) Play))); - gain_astate_menu.items().push_back (MenuElem (_("Write"), - bind (mem_fun (*_io, &IO::set_parameter_automation_state), - Parameter(GainAutomation), (AutoState) Write))); - gain_astate_menu.items().push_back (MenuElem (_("Touch"), - bind (mem_fun (*_io, &IO::set_parameter_automation_state), - Parameter(GainAutomation), (AutoState) Touch))); - - gain_astyle_menu.items().push_back (MenuElem (_("Trim"))); - gain_astyle_menu.items().push_back (MenuElem (_("Abs"))); - - gain_astate_menu.set_name ("ArdourContextMenu"); - gain_astyle_menu.set_name ("ArdourContextMenu"); - - gain_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &GainMeter::gain_automation_style_button_event), false); - gain_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &GainMeter::gain_automation_state_button_event), false); - - r->gain_control()->list()->automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed)); - r->gain_control()->list()->automation_style_changed.connect (mem_fun(*this, &GainMeter::gain_automation_style_changed)); - fader_vbox->pack_start (gain_automation_state_button, false, false, 0); - - gain_automation_state_changed (); + if (!r->is_hidden()) { + fader_vbox->pack_start (gain_automation_state_button, false, false, 0); + } } set_spacing (2); @@ -198,40 +806,21 @@ GainMeter::GainMeter (boost::shared_ptr io, Session& s) pack_start (gain_display_box, Gtk::PACK_SHRINK); pack_start (hbox, Gtk::PACK_SHRINK); - _io->gain_control()->Changed.connect (mem_fun(*this, &GainMeter::gain_changed)); - meter_metric_area.signal_expose_event().connect (mem_fun(*this, &GainMeter::meter_metrics_expose)); - gain_adjustment.signal_value_changed().connect (mem_fun(*this, &GainMeter::gain_adjusted)); - peak_display.signal_button_release_event().connect (mem_fun(*this, &GainMeter::peak_button_release), false); - gain_display.signal_key_press_event().connect (mem_fun(*this, &GainMeter::gain_key_press), false); - - gain_changed (); - show_gain (); - - update_gain_sensitive (); - - ResetAllPeakDisplays.connect (mem_fun(*this, &GainMeter::reset_peak_display)); - ResetGroupPeakDisplays.connect (mem_fun(*this, &GainMeter::reset_group_peak_display)); - - UI::instance()->theme_changed.connect (mem_fun(*this, &GainMeter::on_theme_changed)); - - ColorsChanged.connect (bind (mem_fun (*this, &GainMeter::color_handler), false)); - DPIReset.connect (bind (mem_fun (*this, &GainMeter::color_handler), true)); - - //hide_all(); } -void -GainMeter::set_width (Width w, int len) + +int +GainMeter::get_gm_width () { - _width = w; - level_meter->setup_meters (len); + Gtk::Requisition sz; + hbox.size_request (sz); + return sz.width; } Glib::RefPtr GainMeter::render_metrics (Gtk::Widget& w) { - //cerr << "GainMeter::render_metrics() called, red = " << w.get_style()->get_bg(Gtk::STATE_NORMAL).get_red() << endl;//DEBUG Glib::RefPtr win (w.get_window()); Glib::RefPtr fg_gc (w.get_style()->get_fg_gc (Gtk::STATE_NORMAL)); Glib::RefPtr bg_gc (w.get_style()->get_bg_gc (Gtk::STATE_NORMAL)); @@ -273,20 +862,12 @@ GainMeter::render_metrics (Gtk::Widget& w) gint GainMeter::meter_metrics_expose (GdkEventExpose *ev) { - /* Only draw dB scale if we're metering audio */ - if (_io->n_inputs().n_audio() + _io->n_outputs().n_audio() == 0) - return true; - static Glib::RefPtr meter_style; - if (style_changed) { meter_style = meter_metric_area.get_style(); } - Glib::RefPtr win (meter_metric_area.get_window()); - Glib::RefPtr fg_gc (meter_style->get_fg_gc (Gtk::STATE_NORMAL)); - Glib::RefPtr bg_gc (meter_style->get_bg_gc (Gtk::STATE_NORMAL)); - + Glib::RefPtr bg_gc (meter_style->get_bg_gc (Gtk::STATE_INSENSITIVE)); GdkRectangle base_rect; GdkRectangle draw_rect; gint width, height; @@ -308,547 +889,8 @@ GainMeter::meter_metrics_expose (GdkEventExpose *ev) } gdk_rectangle_intersect (&ev->area, &base_rect, &draw_rect); - win->draw_rectangle (bg_gc, false, draw_rect.x, draw_rect.y, draw_rect.width, draw_rect.height); - win->draw_drawable (fg_gc, pixmap, draw_rect.x, draw_rect.y, draw_rect.x, draw_rect.y, draw_rect.width, draw_rect.height); - + win->draw_drawable (bg_gc, pixmap, draw_rect.x, draw_rect.y, draw_rect.x, draw_rect.y, draw_rect.width, draw_rect.height); style_changed = false; return true; } -void -GainMeter::on_theme_changed() -{ - style_changed = true; -} - -GainMeter::~GainMeter () -{ - if (meter_menu) { - delete meter_menu; - } - - if (level_meter) { - delete level_meter; - } -} - -void -GainMeter::hide_all_meters () -{ - bool remove_metric_area = false; - - level_meter->hide_meters(); - - if (remove_metric_area) { - if (meter_metric_area.get_parent()) { - level_meter->remove (meter_metric_area); - } - } -} - -void -GainMeter::setup_meters (int len) -{ - if (!meter_metric_area.get_parent()) { - level_meter->pack_end (meter_metric_area, false, false); - meter_metric_area.show_all (); - } - level_meter->setup_meters(len, 5); -} - -int -GainMeter::get_gm_width () -{ - Gtk::Requisition sz = hbox.size_request (); - return sz.width; -} - -bool -GainMeter::gain_key_press (GdkEventKey* ev) -{ - if (key_is_legal_for_numeric_entry (ev->keyval)) { - /* drop through to normal handling */ - return false; - } - /* illegal key for gain entry */ - return true; -} - -bool -GainMeter::peak_button_release (GdkEventButton* ev) -{ - /* reset peak label */ - - if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier|Keyboard::TertiaryModifier)) { - ResetAllPeakDisplays (); - } else if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { - Route* r; - if ((r = dynamic_cast (_io.get())) != 0) { - ResetGroupPeakDisplays (r->mix_group()); - } - } else { - reset_peak_display (); - } - - return true; -} - -void -GainMeter::reset_peak_display () -{ - Route * r; - if ((r = dynamic_cast (_io.get())) != 0) { - r->peak_meter().reset_max(); - } - - level_meter->clear_meters(); - max_peak = -INFINITY; - peak_display.set_label (_("-Inf")); - peak_display.set_name ("MixerStripPeakDisplay"); -} - -void -GainMeter::reset_group_peak_display (RouteGroup* group) -{ - Route* r; - if ((r = dynamic_cast (_io.get())) != 0) { - if (group == r->mix_group()) { - reset_peak_display (); - } - } -} - -void -GainMeter::popup_meter_menu (GdkEventButton *ev) -{ - using namespace Menu_Helpers; - - if (meter_menu == 0) { - meter_menu = new Gtk::Menu; - MenuList& items = meter_menu->items(); - - items.push_back (MenuElem ("-inf .. +0dBFS")); - items.push_back (MenuElem ("-10dB .. +0dBFS")); - items.push_back (MenuElem ("-4 .. +0dBFS")); - items.push_back (SeparatorElem()); - items.push_back (MenuElem ("-inf .. -2dBFS")); - items.push_back (MenuElem ("-10dB .. -2dBFS")); - items.push_back (MenuElem ("-4 .. -2dBFS")); - } - - meter_menu->popup (1, ev->time); -} - -bool -GainMeter::gain_focused (GdkEventFocus* ev) -{ - if (ev->in) { - gain_display.select_region (0, -1); - } else { - gain_display.select_region (0, 0); - } - return false; -} - -void -GainMeter::gain_activated () -{ - float f; - - if (sscanf (gain_display.get_text().c_str(), "%f", &f) == 1) { - - /* clamp to displayable values */ - - f = min (f, 6.0f); - - _io->gain_control()->set_value (dB_to_coefficient(f)); - - if (gain_display.has_focus()) { - PublicEditor::instance().reset_focus(); - } - } -} - -void -GainMeter::show_gain () -{ - char buf[32]; - - float v = gain_adjustment.get_value(); - - if (v == 0.0) { - strcpy (buf, _("-inf")); - } else { - snprintf (buf, 32, "%.1f", coefficient_to_dB (slider_position_to_gain (v))); - } - - gain_display.set_text (buf); -} - -void -GainMeter::gain_adjusted () -{ - if (!ignore_toggle) { - _io->gain_control()->set_value (slider_position_to_gain (gain_adjustment.get_value())); - } - show_gain (); -} - -void -GainMeter::effective_gain_display () -{ - gfloat value = gain_to_slider_position (_io->effective_gain()); - - if (gain_adjustment.get_value() != value) { - ignore_toggle = true; - gain_adjustment.set_value (value); - ignore_toggle = false; - } -} - -void -GainMeter::gain_changed () -{ - Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &GainMeter::effective_gain_display)); -} - -void -GainMeter::set_meter_strip_name (const char * name) -{ - meter_metric_area.set_name (name); -} - -void -GainMeter::set_fader_name (const char * name) -{ - gain_slider->set_name (name); -} - -void -GainMeter::update_gain_sensitive () -{ - static_cast(gain_slider)->set_sensitive (!(_io->gain_control()->list()->automation_state() & Play)); -} - - -static MeterPoint -next_meter_point (MeterPoint mp) -{ - switch (mp) { - case MeterInput: - return MeterPreFader; - break; - - case MeterPreFader: - return MeterPostFader; - break; - - case MeterPostFader: - return MeterInput; - break; - } - /*NOTREACHED*/ - return MeterInput; -} - -gint -GainMeter::meter_press(GdkEventButton* ev) -{ - Route* _route; - - wait_for_release = false; - - if ((_route = dynamic_cast(_io.get())) == 0) { - return FALSE; - } - - if (!ignore_toggle) { - - if (Keyboard::is_context_menu_event (ev)) { - - // no menu at this time. - - } else { - - if (ev->button == 2) { - - // Primary-button2 click is the midi binding click - // button2-click is "momentary" - - if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) { - wait_for_release = true; - old_meter_point = _route->meter_point (); - } - } - - if (ev->button == 1 || ev->button == 2) { - - if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) { - - /* Primary+Tertiary-click applies change to all routes */ - - _session.begin_reversible_command (_("meter point change")); - Session::GlobalMeteringStateCommand *cmd = new Session::GlobalMeteringStateCommand (_session, this); - _session.foreach_route (this, &GainMeter::set_meter_point, next_meter_point (_route->meter_point())); - cmd->mark(); - _session.add_command (cmd); - _session.commit_reversible_command (); - - - } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { - - /* Primary-click: solo mix group. - NOTE: Primary-button2 is MIDI learn. - */ - - if (ev->button == 1) { - _session.begin_reversible_command (_("meter point change")); - Session::GlobalMeteringStateCommand *cmd = new Session::GlobalMeteringStateCommand (_session, this); - set_mix_group_meter_point (*_route, next_meter_point (_route->meter_point())); - cmd->mark(); - _session.add_command (cmd); - _session.commit_reversible_command (); - } - - } else { - - /* click: change just this route */ - - // XXX no undo yet - - _route->set_meter_point (next_meter_point (_route->meter_point()), this); - } - } - } - } - - return true; - -} - -gint -GainMeter::meter_release(GdkEventButton* ev) -{ - - if(!ignore_toggle){ - if (wait_for_release){ - wait_for_release = false; - set_meter_point (*(dynamic_cast(_io.get())), old_meter_point); - } - } - return true; -} - -void -GainMeter::set_meter_point (Route& route, MeterPoint mp) -{ - route.set_meter_point (mp, this); -} - -void -GainMeter::set_mix_group_meter_point (Route& route, MeterPoint mp) -{ - RouteGroup* mix_group; - - if((mix_group = route.mix_group()) != 0){ - mix_group->apply (&Route::set_meter_point, mp, this); - } else { - route.set_meter_point (mp, this); - } -} - -void -GainMeter::meter_point_clicked () -{ - Route* r; - - if ((r = dynamic_cast (_io.get())) != 0) { - - } -} - -gint -GainMeter::start_gain_touch (GdkEventButton* ev) -{ - _io->gain_control()->list()->start_touch (); - return FALSE; -} - -gint -GainMeter::end_gain_touch (GdkEventButton* ev) -{ - _io->gain_control()->list()->stop_touch (); - return FALSE; -} - -gint -GainMeter::gain_automation_state_button_event (GdkEventButton *ev) -{ - if (ev->type == GDK_BUTTON_RELEASE) { - return TRUE; - } - - switch (ev->button) { - case 1: - gain_astate_menu.popup (1, ev->time); - break; - default: - break; - } - - return TRUE; -} - -gint -GainMeter::gain_automation_style_button_event (GdkEventButton *ev) -{ - if (ev->type == GDK_BUTTON_RELEASE) { - return TRUE; - } - - switch (ev->button) { - case 1: - gain_astyle_menu.popup (1, ev->time); - break; - default: - break; - } - return TRUE; -} - -string -GainMeter::astate_string (AutoState state) -{ - return _astate_string (state, false); -} - -string -GainMeter::short_astate_string (AutoState state) -{ - return _astate_string (state, true); -} - -string -GainMeter::_astate_string (AutoState state, bool shrt) -{ - string sstr; - - switch (state) { - case Off: - sstr = (shrt ? "M" : _("M")); - break; - case Play: - sstr = (shrt ? "P" : _("P")); - break; - case Touch: - sstr = (shrt ? "T" : _("T")); - break; - case Write: - sstr = (shrt ? "W" : _("W")); - break; - } - - return sstr; -} - -string -GainMeter::astyle_string (AutoStyle style) -{ - return _astyle_string (style, false); -} - -string -GainMeter::short_astyle_string (AutoStyle style) -{ - return _astyle_string (style, true); -} - -string -GainMeter::_astyle_string (AutoStyle style, bool shrt) -{ - if (style & Trim) { - return _("Trim"); - } else { - /* XXX it might different in different languages */ - - return (shrt ? _("Abs") : _("Abs")); - } -} - -void -GainMeter::gain_automation_style_changed () -{ - // Route* _route = dynamic_cast(&_io); - switch (_width) { - case Wide: - gain_automation_style_button.set_label (astyle_string(_io->gain_control()->list()->automation_style())); - break; - case Narrow: - gain_automation_style_button.set_label (short_astyle_string(_io->gain_control()->list()->automation_style())); - break; - } -} - -void -GainMeter::gain_automation_state_changed () -{ - ENSURE_GUI_THREAD(mem_fun(*this, &GainMeter::gain_automation_state_changed)); - //Route* _route = dynamic_cast(&_io); - - bool x; - - switch (_width) { - case Wide: - gain_automation_state_button.set_label (astate_string(_io->gain_control()->list()->automation_state())); - break; - case Narrow: - gain_automation_state_button.set_label (short_astate_string(_io->gain_control()->list()->automation_state())); - break; - } - - x = (_io->gain_control()->list()->automation_state() != Off); - - if (gain_automation_state_button.get_active() != x) { - ignore_toggle = true; - gain_automation_state_button.set_active (x); - ignore_toggle = false; - } - - update_gain_sensitive (); - - /* start watching automation so that things move */ - - gain_watching.disconnect(); - - if (x) { - gain_watching = ARDOUR_UI::RapidScreenUpdate.connect (mem_fun (*this, &GainMeter::effective_gain_display)); - } -} - -void -GainMeter::update_meters() -{ - char buf[32]; - float mpeak = level_meter->update_meters(); - - if (mpeak > max_peak) { - max_peak = mpeak; - if (mpeak <= -200.0f) { - peak_display.set_label (_("-inf")); - } else { - snprintf (buf, sizeof(buf), "%.1f", mpeak); - peak_display.set_label (buf); - } - - if (mpeak >= 0.0f) { - peak_display.set_name ("MixerStripPeakDisplayPeak"); - } - } -} - -void GainMeter::color_handler (bool dpi) -{ - color_changed = true; - dpi_changed = (dpi) ? true : false; - setup_meters(); -} diff --git a/gtk2_ardour/gain_meter.h b/gtk2_ardour/gain_meter.h index cd8e74d59d..d493edf0fb 100644 --- a/gtk2_ardour/gain_meter.h +++ b/gtk2_ardour/gain_meter.h @@ -55,33 +55,29 @@ namespace Gtk { class Menu; } -class GainMeter : public Gtk::VBox +class GainMeterBase : virtual public sigc::trackable { public: - GainMeter (boost::shared_ptr, ARDOUR::Session&); - ~GainMeter (); + GainMeterBase (boost::shared_ptr, ARDOUR::Session&, const Glib::RefPtr& pix, + bool horizontal); + virtual ~GainMeterBase (); void update_gain_sensitive (); - void update_meters (); void effective_gain_display (); - void set_width (Width, int len=0); - void setup_meters (int len=0); - - int get_gm_width (); - void set_meter_strip_name (const char * name); void set_fader_name (const char * name); - /* should probably switch to using the shared_ptr that underlies - all this stuff - */ + virtual void setup_meters (int len=0); - PBD::Controllable* get_controllable() { return _io->gain_control().get(); } + boost::shared_ptr get_controllable() { return _io->gain_control(); } - private: + LevelMeter& get_level_meter() const { return *level_meter; } + Gtkmm2ext::SliderController& get_gain_slider() const { return *gain_slider; } + + protected: friend class MixerStrip; boost::shared_ptr _io; @@ -90,14 +86,12 @@ class GainMeter : public Gtk::VBox bool ignore_toggle; bool next_release_selects; - Gtkmm2ext::VSliderController *gain_slider; + Gtkmm2ext::SliderController *gain_slider; Gtk::Adjustment gain_adjustment; Gtkmm2ext::FocusEntry gain_display; Gtk::Button peak_display; - Gtk::HBox gain_display_box; - Gtk::HBox fader_box; Gtk::DrawingArea meter_metric_area; - LevelMeter *level_meter; + LevelMeter *level_meter; sigc::connection gain_watching; @@ -125,27 +119,19 @@ class GainMeter : public Gtk::VBox Width _width; - static std::map > metric_pixmaps; - static Glib::RefPtr render_metrics (Gtk::Widget&); - - gint meter_metrics_expose (GdkEventExpose *); - void show_gain (); void gain_activated (); bool gain_focused (GdkEventFocus*); float max_peak; - Gtk::VBox* fader_vbox; - Gtk::HBox hbox; - void gain_adjusted (); void gain_changed (); void meter_point_clicked (); void gain_unit_changed (); - void hide_all_meters (); + virtual void hide_all_meters (); gint meter_button_press (GdkEventButton*, uint32_t); @@ -173,10 +159,6 @@ class GainMeter : public Gtk::VBox static sigc::signal ResetAllPeakDisplays; static sigc::signal ResetGroupPeakDisplays; - static Glib::RefPtr slider; - static Glib::RefPtr rail; - static int setup_slider_pix (); - void on_theme_changed (); bool style_changed; bool dpi_changed; @@ -184,5 +166,33 @@ class GainMeter : public Gtk::VBox void color_handler(bool); }; +class GainMeter : public GainMeterBase, public Gtk::VBox +{ + public: + GainMeter (boost::shared_ptr, ARDOUR::Session&); + ~GainMeter () {} + + int get_gm_width (); + void setup_meters (int len=0); + + static void setup_slider_pix (); + + protected: + void hide_all_meters (); + + gint meter_metrics_expose (GdkEventExpose *); + + static std::map > metric_pixmaps; + static Glib::RefPtr render_metrics (Gtk::Widget&); + + private: + Gtk::HBox gain_display_box; + Gtk::HBox fader_box; + Gtk::VBox* fader_vbox; + Gtk::HBox hbox; + + static Glib::RefPtr slider; +}; + #endif /* __ardour_gtk_gain_meter_h__ */ diff --git a/gtk2_ardour/ghostregion.cc b/gtk2_ardour/ghostregion.cc index 4e06ece82f..9da7ceb370 100644 --- a/gtk2_ardour/ghostregion.cc +++ b/gtk2_ardour/ghostregion.cc @@ -43,7 +43,7 @@ GhostRegion::GhostRegion (ArdourCanvas::Group* parent, TimeAxisView& tv, TimeAxi base_rect = new ArdourCanvas::SimpleRect (*group); base_rect->property_x1() = (double) 0.0; base_rect->property_y1() = (double) 0.0; - base_rect->property_y2() = (double) trackview.height; + base_rect->property_y2() = (double) trackview.current_height(); base_rect->property_outline_what() = (guint32) 0; if (!is_automation_ghost()) { @@ -73,7 +73,7 @@ GhostRegion::set_duration (double units) void GhostRegion::set_height () { - base_rect->property_y2() = (double) trackview.height; + base_rect->property_y2() = (double) trackview.current_height(); } void @@ -121,7 +121,7 @@ AudioGhostRegion::set_height () GhostRegion::set_height(); - ht = ((trackview.height) / (double) waves.size()); + ht = ((trackview.current_height()) / (double) waves.size()); for (n = 0, i = waves.begin(); i != waves.end(); ++i, ++n) { gdouble yoff = n * ht; diff --git a/gtk2_ardour/imageframe_time_axis.cc b/gtk2_ardour/imageframe_time_axis.cc index 018fae6895..f3630e7152 100644 --- a/gtk2_ardour/imageframe_time_axis.cc +++ b/gtk2_ardour/imageframe_time_axis.cc @@ -81,7 +81,7 @@ ImageFrameTimeAxis::ImageFrameTimeAxis(const string & track_id, PublicEditor& ed label_view() ; // set the initial height of this time axis - set_height(Normal) ; + set_height(hNormal) ; } /** @@ -133,10 +133,10 @@ ImageFrameTimeAxis::~ImageFrameTimeAxis () /** * Sets the height of this TrackView to one of ths TrackHeghts * - * @param h the TrackHeight value to set + * @param h */ void -ImageFrameTimeAxis::set_height (TrackHeight h) +ImageFrameTimeAxis::set_height (uint32_t h) { VisualTimeAxis::set_height(h) ; diff --git a/gtk2_ardour/imageframe_time_axis.h b/gtk2_ardour/imageframe_time_axis.h index 4b3bf0c857..7cbed6a394 100644 --- a/gtk2_ardour/imageframe_time_axis.h +++ b/gtk2_ardour/imageframe_time_axis.h @@ -76,9 +76,9 @@ class ImageFrameTimeAxis : public VisualTimeAxis /** * Sets the height of this TrackView to one of ths TrackHeghts * - * @param h the TrackHeight value to set + * @param h the number of pixels to set the height too */ - virtual void set_height(TimeAxisView::TrackHeight) ; + virtual void set_height(uint32_t h) ; /** * Sets the number of samples per unit that are used. diff --git a/gtk2_ardour/imageframe_time_axis_view.cc b/gtk2_ardour/imageframe_time_axis_view.cc index 69205cd511..a57db60a38 100644 --- a/gtk2_ardour/imageframe_time_axis_view.cc +++ b/gtk2_ardour/imageframe_time_axis_view.cc @@ -50,7 +50,7 @@ using namespace Editing; ImageFrameTimeAxisView::ImageFrameTimeAxisView (ImageFrameTimeAxis& tv) : _trackview (tv), canvas_group (*_trackview.canvas_display), - canvas_rect (canvas_group, 0.0, 0.0, 1000000.0, tv.height) + canvas_rect (canvas_group, 0.0, 0.0, 1000000.0, tv.current_height()) { region_color = _trackview.color() ; stream_base_color = ARDOUR_UI::config()->canvasvar_ImageTrack.get() ; diff --git a/gtk2_ardour/imageframe_view.cc b/gtk2_ardour/imageframe_view.cc index f8bba3aa84..f35381301e 100644 --- a/gtk2_ardour/imageframe_view.cc +++ b/gtk2_ardour/imageframe_view.cc @@ -91,9 +91,9 @@ ImageFrameView::ImageFrameView(const string & item_id, //calculate our image width based on the track height double im_ratio = (double)width/(double)height ; - double im_width = ((double)(trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE) * im_ratio) ; + double im_width = ((double)(trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE) * im_ratio) ; - imageframe = new ImageFrame (*group, pbuf, 1.0, 1.0, ANCHOR_NW, im_width, (trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE)); + imageframe = new ImageFrame (*group, pbuf, 1.0, 1.0, ANCHOR_NW, im_width, (trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE)); frame_handle_start->signal_event().connect (bind (mem_fun (trackview.editor, &PublicEditor::canvas_imageframe_start_handle_event), frame_handle_start, this)); frame_handle_end->signal_event().connect (bind (mem_fun (trackview.editor, &PublicEditor::canvas_imageframe_end_handle_event), frame_handle_end, this)); diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc index b0b1a5f9b7..16576a0b8f 100644 --- a/gtk2_ardour/io_selector.cc +++ b/gtk2_ardour/io_selector.cc @@ -17,8 +17,11 @@ */ +#include #include + #include + #include #include "ardour/session.h" #include "ardour/io.h" @@ -27,11 +30,15 @@ #include "ardour/audio_track.h" #include "ardour/midi_track.h" #include "ardour/data_type.h" + #include "io_selector.h" #include "utils.h" #include "gui_thread.h" #include "i18n.h" +using namespace ARDOUR; +using namespace Gtk; + IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr io, bool offer_inputs) : PortMatrix ( session, io->default_type(), !offer_inputs, @@ -46,15 +53,13 @@ IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr _io->output_changed.connect (mem_fun(*this, &IOSelector::ports_changed)); } -#ifdef FIXME - /* these got lost in a merge from 2.0 */ - set_button_sensitivity (); - io->name_changed.connect (mem_fun(*this, &IOSelector::name_changed)); -#endif + /* this got lost in a merge from 2.0 */ + + // set_button_sensitivity (); + // io->name_changed.connect (mem_fun(*this, &IOSelector::name_changed)); } - void IOSelector::ports_changed (ARDOUR::IOChange change, void *src) { @@ -161,8 +166,8 @@ IOSelector::add_row () _io->add_input_port ("", this); } - catch (ARDOUR::AudioEngine::PortRegistrationFailure& err) { - Gtk::MessageDialog msg (0, _("There are no more JACK ports available.")); + catch (AudioEngine::PortRegistrationFailure& err) { + MessageDialog msg (_("There are no more JACK ports available.")); msg.run (); } @@ -172,14 +177,13 @@ IOSelector::add_row () _io->add_output_port ("", this); } - catch (ARDOUR::AudioEngine::PortRegistrationFailure& err) { - Gtk::MessageDialog msg (0, _("There are no more JACK ports available.")); + catch (AudioEngine::PortRegistrationFailure& err) { + MessageDialog msg (_("There are no more JACK ports available.")); msg.run (); } } } - void IOSelector::remove_row (int r) { @@ -199,7 +203,54 @@ IOSelector::row_descriptor () const return _("port"); } +#if 0 +void +IOSelector::set_button_sensitivity () +{ + if (for_input) { + if (io->input_maximum() < 0 || io->input_maximum() > (int) io->n_inputs()) { + add_port_button.set_sensitive (true); + } else { + add_port_button.set_sensitive (false); + } + + } else { + + if (io->output_maximum() < 0 || io->output_maximum() > (int) io->n_outputs()) { + add_port_button.set_sensitive (true); + } else { + add_port_button.set_sensitive (false); + } + + } + + if (for_input) { + if (io->n_inputs() && (io->input_minimum() < 0 || io->input_minimum() < (int) io->n_inputs())) { + remove_port_button.set_sensitive (true); + } else { + remove_port_button.set_sensitive (false); + } + + } else { + if (io->n_outputs() && (io->output_minimum() < 0 || io->output_minimum() < (int) io->n_outputs())) { + remove_port_button.set_sensitive (true); + } else { + remove_port_button.set_sensitive (false); + } + } +} +#endif + +#if 0 +void +IOSelector::name_changed (void* src) +{ + ENSURE_GUI_THREAD(bind (mem_fun(*this, &IOSelector::name_changed), src)); + + display_ports (); +} +#endif IOSelectorWindow::IOSelectorWindow ( ARDOUR::Session& session, boost::shared_ptr io, bool for_input, bool can_cancel diff --git a/gtk2_ardour/keyboard.cc b/gtk2_ardour/keyboard.cc index 22dd274306..ef8cc34389 100644 --- a/gtk2_ardour/keyboard.cc +++ b/gtk2_ardour/keyboard.cc @@ -17,6 +17,7 @@ */ +#include #include #include "ardour_ui.h" @@ -38,11 +39,14 @@ #include "keyboard.h" #include "gui_thread.h" #include "opts.h" +#include "actions.h" #include "i18n.h" using namespace PBD; using namespace ARDOUR; +using namespace Gtk; +using namespace std; #define KBD_DEBUG 1 bool debug_keyboard = false; @@ -75,8 +79,10 @@ bool Keyboard::_some_magic_widget_has_focus = false; std::string Keyboard::user_keybindings_path; bool Keyboard::can_save_keybindings = false; +bool Keyboard::bindings_changed_after_save_became_legal = false; map Keyboard::binding_files; -std::string Keyboard::_current_binding_name = _("Unknown"); +string Keyboard::_current_binding_name = _("Unknown"); +map,Keyboard::AccelKeyLess> Keyboard::release_keys; /* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */ @@ -186,6 +192,7 @@ gint Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) { uint32_t keyval; + bool ret = false; #if 0 cerr << "snoop widget " << widget << " key " << event->keyval << " type: " << event->type @@ -215,7 +222,23 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) if (find (state.begin(), state.end(), keyval) == state.end()) { state.push_back (keyval); sort (state.begin(), state.end()); - } + + } else { + + /* key is already down. if its also used for release, + prevent auto-repeat events. + */ + + for (map::iterator k = release_keys.begin(); k != release_keys.end(); ++k) { + + const AccelKey& ak (k->first); + + if (keyval == ak.get_key() && (Gdk::ModifierType)(event->state | Gdk::RELEASE_MASK) == ak.get_mod()) { + ret = true; + break; + } + } + } } else if (event->type == GDK_KEY_RELEASE) { @@ -226,6 +249,20 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) sort (state.begin(), state.end()); } + for (map::iterator k = release_keys.begin(); k != release_keys.end(); ++k) { + + const AccelKey& ak (k->first); + two_strings ts (k->second); + + if (keyval == ak.get_key() && (Gdk::ModifierType)(event->state | Gdk::RELEASE_MASK) == ak.get_mod()) { + Glib::RefPtr act = ActionManager::get_action (ts.first.c_str(), ts.second.c_str()); + if (act) { + act->activate(); + ret = true; + } + break; + } + } } if (event->type == GDK_KEY_RELEASE && event->keyval == GDK_w && modifier_state_equals (event->state, PrimaryModifier)) { @@ -235,7 +272,7 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) } } - return false; + return ret; } bool @@ -388,6 +425,16 @@ accel_map_changed (GtkAccelMap* map, GdkModifierType mod, gpointer arg) { + Keyboard::keybindings_changed (); +} + +void +Keyboard::keybindings_changed () +{ + if (Keyboard::can_save_keybindings) { + Keyboard::bindings_changed_after_save_became_legal = true; + } + Keyboard::save_keybindings (); } @@ -400,7 +447,7 @@ Keyboard::set_can_save_keybindings (bool yn) void Keyboard::save_keybindings () { - if (can_save_keybindings) { + if (can_save_keybindings && bindings_changed_after_save_became_legal) { Gtk::AccelMap::save (user_keybindings_path); } } @@ -555,13 +602,34 @@ Keyboard::load_keybindings (string path) } } - return true; } catch (...) { error << string_compose (_("Ardour key bindings file not found at \"%1\" or contains errors."), path) << endmsg; return false; } + + /* now find all release-driven bindings */ + + vector groups; + vector names; + vector bindings; + + ActionManager::get_all_actions (groups, names, bindings); + + vector::iterator g; + vector::iterator b; + vector::iterator n; + + release_keys.clear (); + + for (n = names.begin(), b = bindings.begin(), g = groups.begin(); n != names.end(); ++n, ++b, ++g) { + if ((*b).get_mod() & Gdk::RELEASE_MASK) { + release_keys.insert (pair (*b, two_strings (*g, *n))); + } + } + + return true; } diff --git a/gtk2_ardour/keyboard.h b/gtk2_ardour/keyboard.h index de2a0929ed..e6d5065e86 100644 --- a/gtk2_ardour/keyboard.h +++ b/gtk2_ardour/keyboard.h @@ -20,18 +20,19 @@ #ifndef __ardour_keyboard_h__ #define __ardour_keyboard_h__ +#include #include #include #include #include +#include #include #include #include "selection.h" -using std::vector; using std::string; class Keyboard : public sigc::trackable, PBD::Stateful @@ -43,7 +44,7 @@ class Keyboard : public sigc::trackable, PBD::Stateful XMLNode& get_state (void); int set_state (const XMLNode&); - typedef vector State; + typedef std::vector State; typedef uint32_t ModifierMask; static uint32_t PrimaryModifier; @@ -114,12 +115,23 @@ class Keyboard : public sigc::trackable, PBD::Stateful static void magic_widget_drop_focus (); static void setup_keybindings (); + static void keybindings_changed (); static void save_keybindings (); static bool load_keybindings (std::string path); static void set_can_save_keybindings (bool yn); static std::string current_binding_name () { return _current_binding_name; } static std::map binding_files; + struct AccelKeyLess { + bool operator() (const Gtk::AccelKey a, const Gtk::AccelKey b) const { + if (a.get_key() != b.get_key()) { + return a.get_key() < b.get_key(); + } else { + return a.get_mod() < b.get_mod(); + } + } + }; + private: static Keyboard* _the_keyboard; @@ -134,8 +146,13 @@ class Keyboard : public sigc::trackable, PBD::Stateful static Gtk::Window* current_window; static std::string user_keybindings_path; static bool can_save_keybindings; + static bool bindings_changed_after_save_became_legal; static std::string _current_binding_name; + typedef std::pair two_strings; + + static std::map release_keys; + static gint _snooper (GtkWidget*, GdkEventKey*, gpointer); gint snooper (GtkWidget*, GdkEventKey*); diff --git a/gtk2_ardour/keyeditor.cc b/gtk2_ardour/keyeditor.cc index cdac398a30..e44d92943f 100644 --- a/gtk2_ardour/keyeditor.cc +++ b/gtk2_ardour/keyeditor.cc @@ -16,6 +16,7 @@ #include "actions.h" #include "keyboard.h" #include "keyeditor.h" +#include "utils.h" #include "i18n.h" @@ -167,6 +168,8 @@ KeyEditor::on_key_release_event (GdkEventKey* ev) goto out; } + possibly_translate_keyval_to_make_legal_accelerator (ev->keyval); + bool result = AccelMap::change_entry (path, ev->keyval, (ModifierType) ev->state, diff --git a/gtk2_ardour/latency_gui.cc b/gtk2_ardour/latency_gui.cc index d03ad5b9f9..e7c42fd780 100644 --- a/gtk2_ardour/latency_gui.cc +++ b/gtk2_ardour/latency_gui.cc @@ -41,6 +41,7 @@ LatencyGUI::LatencyGUI (Latent& l, nframes64_t sr, nframes64_t psz) initial_value (_latent.signal_latency()), sample_rate (sr), period_size (psz), + ignored (new PBD::IgnorableControllable()), /* max 1 second, step by frames, page by msecs */ adjustment (initial_value, 0.0, sample_rate, 1.0, sample_rate / 1000.0f), bc (adjustment, ignored, sigc::mem_fun (*this, &LatencyGUI::latency_printer)), diff --git a/gtk2_ardour/latency_gui.h b/gtk2_ardour/latency_gui.h index 0be7fdbf4c..f352f698d7 100644 --- a/gtk2_ardour/latency_gui.h +++ b/gtk2_ardour/latency_gui.h @@ -35,7 +35,7 @@ class LatencyGUI : public Gtk::VBox nframes64_t initial_value; nframes64_t sample_rate; nframes64_t period_size; - PBD::IgnorableControllable ignored; + boost::shared_ptr ignored; Gtk::Adjustment adjustment; Gtkmm2ext::BarController bc; diff --git a/gtk2_ardour/level_meter.cc b/gtk2_ardour/level_meter.cc index 8a05d8da56..f6e3731aac 100644 --- a/gtk2_ardour/level_meter.cc +++ b/gtk2_ardour/level_meter.cc @@ -100,6 +100,9 @@ LevelMeter::update_meters () if (mpeak > max_peak) { max_peak = mpeak; } + if (mpeak > max_peak) { + max_peak = mpeak; + } } } return max_peak; @@ -143,6 +146,7 @@ LevelMeter::setup_meters (int len, int initial_width) { uint32_t nmeters = _io->n_outputs().n_total(); regular_meter_width = initial_width; + guint16 width; hide_all_meters (); diff --git a/gtk2_ardour/location_ui.cc b/gtk2_ardour/location_ui.cc index 2079d0dc7a..451a85efd7 100644 --- a/gtk2_ardour/location_ui.cc +++ b/gtk2_ardour/location_ui.cc @@ -46,10 +46,10 @@ using namespace Gtkmm2ext; LocationEditRow::LocationEditRow(Session * sess, Location * loc, int32_t num) : location(0), session(0), item_table (1, 7, false), - start_set_button (_("Set")), + start_set_button (_("Use PH")), start_go_button (_("Go")), start_clock (X_("locationstart"), true, X_("LocationEditRowClock"), true), - end_set_button (_("Set")), + end_set_button (_("Use PH")), end_go_button (_("Go")), end_clock (X_("locationend"), true, X_("LocationEditRowClock"), true), length_clock (X_("locationlength"), true, X_("LocationEditRowClock"), true, true), @@ -82,7 +82,9 @@ LocationEditRow::LocationEditRow(Session * sess, Location * loc, int32_t num) composer_label.set_name ("LocationEditNumberLabel"); composer_entry.set_name ("LocationEditNameEntry"); - + ARDOUR_UI::instance()->tooltips().set_tip(start_set_button, _("Set value to Playhead")); + ARDOUR_UI::instance()->tooltips().set_tip(end_set_button, _("Set value to Playhead")); + isrc_label.set_text ("ISRC: "); isrc_label.set_size_request (30, -1); performer_label.set_text ("Performer: "); @@ -131,6 +133,7 @@ LocationEditRow::LocationEditRow(Session * sess, Location * loc, int32_t num) start_set_button.signal_clicked().connect(bind (mem_fun (*this, &LocationEditRow::set_button_pressed), LocStart)); start_go_button.signal_clicked().connect(bind (mem_fun (*this, &LocationEditRow::go_button_pressed), LocStart)); start_clock.ValueChanged.connect (bind (mem_fun (*this, &LocationEditRow::clock_changed), LocStart)); + start_clock.ChangeAborted.connect (bind (mem_fun (*this, &LocationEditRow::change_aborted), LocStart)); end_hbox.pack_start (end_go_button, false, false); @@ -142,9 +145,11 @@ LocationEditRow::LocationEditRow(Session * sess, Location * loc, int32_t num) end_set_button.signal_clicked().connect(bind (mem_fun (*this, &LocationEditRow::set_button_pressed), LocEnd)); end_go_button.signal_clicked().connect(bind (mem_fun (*this, &LocationEditRow::go_button_pressed), LocEnd)); end_clock.ValueChanged.connect (bind (mem_fun (*this, &LocationEditRow::clock_changed), LocEnd)); + end_clock.ChangeAborted.connect (bind (mem_fun (*this, &LocationEditRow::change_aborted), LocEnd)); // item_table.attach (length_clock, 3, 4, 0, 1, 0, 0, 4, 0); length_clock.ValueChanged.connect (bind ( mem_fun(*this, &LocationEditRow::clock_changed), LocLength)); + length_clock.ChangeAborted.connect (bind (mem_fun (*this, &LocationEditRow::change_aborted), LocLength)); // item_table.attach (cd_check_button, 4, 5, 0, 1, 0, Gtk::FILL, 4, 0); // item_table.attach (hide_check_button, 5, 6, 0, 1, 0, Gtk::FILL, 4, 0); @@ -414,6 +419,14 @@ LocationEditRow::clock_changed (LocationPart part) } +void +LocationEditRow::change_aborted (LocationPart part) +{ + if (i_am_the_modifier || !location) return; + + set_location(location); +} + void LocationEditRow::cd_toggled () { @@ -600,6 +613,12 @@ LocationEditRow::flags_changed (ARDOUR::Location *loc, void *src) i_am_the_modifier--; } +void +LocationEditRow::focus_name() { + name_entry.grab_focus(); +} + + LocationUI::LocationUI () : ArdourDialog ("locations dialog"), add_location_button (_("Add New Location")), @@ -628,6 +647,8 @@ LocationUI::LocationUI () location_rows_scroller.set_name ("LocationLocRowsScroller"); location_rows_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); location_rows_scroller.set_size_request (-1, 130); + + newest_location = 0; loc_frame_box.set_spacing (5); loc_frame_box.set_border_width (5); @@ -789,6 +810,10 @@ LocationUI::map_locations (Locations::LocationList& locations) erow->remove_requested.connect (mem_fun(*this, &LocationUI::location_remove_requested)); erow->redraw_ranges.connect (mem_fun(*this, &LocationUI::location_redraw_ranges)); loc_children.push_back(Box_Helpers::Element(*erow, PACK_SHRINK, 1, PACK_START)); + if (location == newest_location) { + newest_location = 0; + erow->focus_name(); + } } else if (location->is_auto_punch()) { punch_edit_row.set_session (session); @@ -820,6 +845,9 @@ LocationUI::add_new_location() nframes_t where = session->audible_frame(); session->locations()->next_available_name(markername,"mark"); Location *location = new Location (where, where, markername, Location::IsMark); + if (Config->get_name_new_markers()) { + newest_location = location; + } session->begin_reversible_command (_("add marker")); XMLNode &before = session->locations()->get_state(); session->locations()->add (location, true); diff --git a/gtk2_ardour/location_ui.h b/gtk2_ardour/location_ui.h index de435b999f..3c32f02025 100644 --- a/gtk2_ardour/location_ui.h +++ b/gtk2_ardour/location_ui.h @@ -50,6 +50,7 @@ class LocationEditRow : public Gtk::HBox void set_session (ARDOUR::Session *); void set_number (int); + void focus_name(); sigc::signal remove_requested; sigc::signal redraw_ranges; @@ -114,6 +115,7 @@ class LocationEditRow : public Gtk::HBox void go_button_pressed (LocationPart part); void clock_changed (LocationPart part); + void change_aborted (LocationPart part); void cd_toggled (); void hide_toggled (); @@ -149,6 +151,7 @@ class LocationUI : public ArdourDialog private: ARDOUR::LocationStack* locations; + ARDOUR::Location *newest_location; void session_gone(); diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc index dd4bcab919..abbf216eea 100644 --- a/gtk2_ardour/main.cc +++ b/gtk2_ardour/main.cc @@ -205,6 +205,13 @@ fixup_bundle_environment () actually exists ... */ + try { + sys::create_directories (user_config_directory ()); + } + catch (const sys::filesystem_error& ex) { + error << _("Could not create user configuration directory") << endmsg; + } + sys::path pangopath = user_config_directory(); pangopath /= "pango.rc"; path = pangopath.to_string(); @@ -212,6 +219,7 @@ fixup_bundle_environment () std::ofstream pangorc (path.c_str()); if (!pangorc) { error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg; + return; } else { pangorc << "[Pango]\nModuleFiles="; @@ -221,6 +229,7 @@ fixup_bundle_environment () pangopath /= "pango.modules"; pangorc << pangopath.to_string() << endl; + pangorc.close (); setenv ("PANGO_RC_FILE", path.c_str(), 1); diff --git a/gtk2_ardour/marker.cc b/gtk2_ardour/marker.cc index dd5a70bb7d..edfec8a600 100644 --- a/gtk2_ardour/marker.cc +++ b/gtk2_ardour/marker.cc @@ -247,8 +247,8 @@ Marker::Marker (PublicEditor& ed, ArdourCanvas::Group& parent, guint32 rgba, con Pango::FontDescription* font = get_font_for_style (N_("MarkerText")); text = new Text (*group); - text->property_text() = annotation.c_str(); text->property_font_desc() = *font; + text->property_text() = annotation.c_str(); delete font; diff --git a/gtk2_ardour/marker_time_axis.cc b/gtk2_ardour/marker_time_axis.cc index e10967d01a..df041f8f76 100644 --- a/gtk2_ardour/marker_time_axis.cc +++ b/gtk2_ardour/marker_time_axis.cc @@ -82,7 +82,7 @@ MarkerTimeAxis::MarkerTimeAxis (PublicEditor& ed, ARDOUR::Session& sess, Canvas& label_view() ; // set the initial height of this time axis - set_height(Small) ; + set_height(hSmall) ; } /** @@ -106,13 +106,8 @@ MarkerTimeAxis::~MarkerTimeAxis() //---------------------------------------------------------------------------------------// // ui methods & data -/** - * Sets the height of this TrackView to one of the defined TrackHeights - * - * @param h the TrackHeight value to set - */ void -MarkerTimeAxis::set_height (TrackHeight h) +MarkerTimeAxis::set_height (uint32_t h) { VisualTimeAxis::set_height(h) ; diff --git a/gtk2_ardour/marker_time_axis.h b/gtk2_ardour/marker_time_axis.h index 13288ce66f..56856d3bd3 100644 --- a/gtk2_ardour/marker_time_axis.h +++ b/gtk2_ardour/marker_time_axis.h @@ -80,9 +80,9 @@ class MarkerTimeAxis : public VisualTimeAxis /** * Sets the height of this TrackView to one of the defined TrackHeights * - * @param h the TrackHeight value to set + * @param h the number of pixels to set the height to */ - virtual void set_height(TimeAxisView::TrackHeight h) ; + virtual void set_height(uint32_t h) ; /** * Sets the number of samples per unit that are used. diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index b38067bfbf..2f414405a0 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -78,7 +78,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView & } MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, boost::shared_ptr r, double spu, Gdk::Color& basic_color, TimeAxisViewItem::Visibility visibility) - : RegionView (parent, tv, r, spu, basic_color, visibility) + : RegionView (parent, tv, r, spu, basic_color, false, visibility) , _force_channel(-1) , _last_channel_selection(0xFFFF) , _default_note_length(0.0) @@ -112,7 +112,7 @@ MidiRegionView::init (Gdk::Color& basic_color, bool wfd) reset_width_dependent_items ((double) _region->length() / samples_per_unit); - set_y_position_and_height (0, trackview.height); + set_y_position_and_height (0, trackview.current_height()); region_muted (); region_resized (BoundsChanged); @@ -148,7 +148,7 @@ MidiRegionView::canvas_event(GdkEvent* ev) static double drag_start_x, drag_start_y; static double last_x, last_y; double event_x, event_y; - nframes_t event_frame = 0; + nframes64_t event_frame = 0; static ArdourCanvas::SimpleRect* drag_rect = NULL; @@ -381,7 +381,7 @@ MidiRegionView::create_note_at(double x, double y, double duration) assert(note >= 0.0); assert(note <= 127.0); - nframes_t new_note_time = trackview.editor.pixel_to_frame (x); + nframes64_t new_note_time = trackview.editor.pixel_to_frame (x); assert(new_note_time >= 0); new_note_time += _region->start(); @@ -391,14 +391,14 @@ MidiRegionView::create_note_at(double x, double y, double duration) double duration = m.frames_per_bar(t, trackview.session().frame_rate()) / m.beats_per_bar(); */ - // we need to snap here again in nframes_t in order to be sample accurate + // we need to snap here again in nframes64_t in order to be sample accurate // since note time is region-absolute but snap_to_frame expects position-relative // time we have to coordinate transform back and forth here. - nframes_t new_note_time_position_relative = new_note_time - _region->start(); + nframes64_t new_note_time_position_relative = new_note_time - _region->start(); new_note_time = snap_to_frame(new_note_time_position_relative) + _region->start(); // we need to snap the duration too to be sample accurate - nframes_t new_note_duration = nframes_t(duration); + nframes64_t new_note_duration = nframes_t(duration); new_note_duration = snap_to_frame(new_note_time_position_relative + new_note_duration) + _region->start() - new_note_time; @@ -648,7 +648,7 @@ MidiRegionView::set_y_position_and_height (double y, double h) note->property_y2() = y2; } if (CanvasHit* hit = dynamic_cast(event)) { - double x = trackview.editor.frame_to_pixel((nframes_t) + double x = trackview.editor.frame_to_pixel((nframes64_t) event->note()->time() - _region->start()); const double diamond_size = midi_stream_view()->note_height() / 2.0; double y = midi_stream_view()->note_to_y(event->note()->note()) @@ -744,7 +744,7 @@ MidiRegionView::resolve_note(uint8_t note, double end_time) return; if (_active_notes && _active_notes[note]) { - _active_notes[note]->property_x2() = trackview.editor.frame_to_pixel((nframes_t)end_time); + _active_notes[note]->property_x2() = trackview.editor.frame_to_pixel((nframes64_t)end_time); _active_notes[note]->property_outline_what() = (guint32) 0xF; // all edges _active_notes[note] = NULL; } @@ -792,13 +792,13 @@ MidiRegionView::add_note(const boost::shared_ptr note) CanvasNoteEvent* event = 0; - const double x = trackview.editor.frame_to_pixel((nframes_t)note->time() - _region->start()); + const double x = trackview.editor.frame_to_pixel((nframes64_t)note->time() - _region->start()); if (midi_view()->note_mode() == Sustained) { const double y1 = midi_stream_view()->note_to_y(note->note()); const double note_endpixel = - trackview.editor.frame_to_pixel((nframes_t)note->end_time() - _region->start()); + trackview.editor.frame_to_pixel((nframes64_t)note->end_time() - _region->start()); CanvasNote* ev_rect = new CanvasNote(*this, *group, note); ev_rect->property_x1() = x; @@ -880,7 +880,7 @@ MidiRegionView::add_pgm_change(boost::shared_ptr event) return; ArdourCanvas::Group* const group = (ArdourCanvas::Group*)get_canvas_group(); - const double x = trackview.editor.frame_to_pixel((nframes_t)event->time() - _region->start()); + const double x = trackview.editor.frame_to_pixel((nframes64_t)event->time() - _region->start()); double height = midi_stream_view()->contents_height(); _pgm_changes.push_back( @@ -1064,7 +1064,7 @@ MidiRegionView::note_dropped(CanvasNoteEvent* ev, double dt, uint8_t dnote) const boost::shared_ptr copy(new Note(*(*i)->note().get())); - // we need to snap here again in nframes_t in order to be sample accurate + // we need to snap here again in nframes64_t in order to be sample accurate double new_note_time = (*i)->note()->time(); new_note_time += dt; @@ -1075,7 +1075,7 @@ MidiRegionView::note_dropped(CanvasNoteEvent* ev, double dt, uint8_t dnote) // since note time is region-absolute but snap_to_frame expects position-relative // time we have to coordinate transform back and forth here. - new_note_time = snap_to_frame(nframes_t(new_note_time) - _region->start()) + _region->start(); + new_note_time = snap_to_frame(nframes64_t(new_note_time) - _region->start()) + _region->start(); copy->set_time(new_note_time); @@ -1111,26 +1111,26 @@ MidiRegionView::note_dropped(CanvasNoteEvent* ev, double dt, uint8_t dnote) } } -nframes_t +nframes64_t MidiRegionView::snap_to_frame(double x) { PublicEditor &editor = trackview.editor; // x is region relative // convert x to global frame - nframes_t frame = editor.pixel_to_frame(x) + _region->position(); + nframes64_t frame = editor.pixel_to_frame(x) + _region->position(); editor.snap_to(frame); // convert event_frame back to local coordinates relative to position frame -= _region->position(); return frame; } -nframes_t -MidiRegionView::snap_to_frame(nframes_t x) +nframes64_t +MidiRegionView::snap_to_frame(nframes64_t x) { PublicEditor &editor = trackview.editor; // x is region relative // convert x to global frame - nframes_t frame = x + _region->position(); + nframes64_t frame = x + _region->position(); editor.snap_to(frame); // convert event_frame back to local coordinates relative to position frame -= _region->position(); @@ -1146,7 +1146,7 @@ MidiRegionView::snap_to_pixel(double x) double MidiRegionView::get_position_pixels(void) { - nframes_t region_frame = get_position(); + nframes64_t region_frame = get_position(); return trackview.editor.frame_to_pixel(region_frame); } @@ -1250,7 +1250,7 @@ MidiRegionView::commit_resizing(CanvasNote::NoteEnd note_end, double event_x, bo // because snapping works on world coordinates we have to transform current_x // to world coordinates before snapping and transform it back afterwards - nframes_t current_frame = snap_to_frame(current_x); + nframes64_t current_frame = snap_to_frame(current_x); // transform to region start relative current_frame += _region->start(); diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index c2475f00fa..50cac66d77 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -164,7 +164,7 @@ class MidiRegionView : public RegionView /** * This function provides the snap function for region position relative coordinates - * for pixel units (double) instead of nframes_t + * for pixel units (double) instead of nframes64_t * @param x a pixel coordinate relative to region start * @return the snapped pixel coordinate relative to region start */ @@ -172,18 +172,18 @@ class MidiRegionView : public RegionView /** * This function provides the snap function for region position relative coordinates - * for pixel units (double) instead of nframes_t + * for pixel units (double) instead of nframes64_t * @param x a pixel coordinate relative to region start - * @return the snapped nframes_t coordinate relative to region start + * @return the snapped nframes64_t coordinate relative to region start */ - nframes_t snap_to_frame(double x); + nframes64_t snap_to_frame(double x); /** * This function provides the snap function for region position relative coordinates * @param x a pixel coordinate relative to region start - * @return the snapped nframes_t coordinate relative to region start + * @return the snapped nframes64_t coordinate relative to region start */ - nframes_t snap_to_frame(nframes_t x); + nframes64_t snap_to_frame(nframes64_t x); protected: diff --git a/gtk2_ardour/midi_streamview.cc b/gtk2_ardour/midi_streamview.cc index de14f302e5..5b162dc510 100644 --- a/gtk2_ardour/midi_streamview.cc +++ b/gtk2_ardour/midi_streamview.cc @@ -93,7 +93,7 @@ MidiStreamView::~MidiStreamView () RegionView* -MidiStreamView::add_region_view_internal (boost::shared_ptr r, bool wfd) +MidiStreamView::add_region_view_internal (boost::shared_ptr r, bool wfd, bool recording) { boost::shared_ptr region = boost::dynamic_pointer_cast (r); @@ -384,7 +384,7 @@ MidiStreamView::setup_rec_box () rec_rect->property_x1() = xstart; rec_rect->property_y1() = 1.0; rec_rect->property_x2() = xend; - rec_rect->property_y2() = (double) _trackview.height - 1; + rec_rect->property_y2() = (double) _trackview.current_height() - 1; rec_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_RecordingRect.get(); rec_rect->property_fill_color_rgba() = fill_color; rec_rect->lower_to_bottom(); diff --git a/gtk2_ardour/midi_streamview.h b/gtk2_ardour/midi_streamview.h index 60dde8cc85..1caad34819 100644 --- a/gtk2_ardour/midi_streamview.h +++ b/gtk2_ardour/midi_streamview.h @@ -81,7 +81,7 @@ class MidiStreamView : public StreamView void redisplay_diskstream (); inline double contents_height() const - { return (_trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 2); } + { return (_trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 2); } inline double note_to_y(uint8_t note) const { return contents_height() @@ -105,7 +105,7 @@ class MidiStreamView : public StreamView void rec_data_range_ready (jack_nframes_t start, jack_nframes_t dur, boost::weak_ptr src); void update_rec_regions (boost::shared_ptr data, jack_nframes_t start, jack_nframes_t dur); - RegionView* add_region_view_internal (boost::shared_ptr, bool wait_for_waves); + RegionView* add_region_view_internal (boost::shared_ptr, bool wait_for_waves, bool recording = false); void display_region(MidiRegionView* region_view, bool load_model); void display_diskstream (boost::shared_ptr ds); diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index f6d2993cfe..5802cc7e20 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -396,15 +396,19 @@ MidiTimeAxisView::route_active_changed () void MidiTimeAxisView::channel_selector_toggled() { - static TimeAxisView::TrackHeight previous_height; + static uint32_t previous_height; if(_midi_expander.property_expanded()) { - previous_height = height_style; - if(previous_height != TimeAxisView::Largest) { - set_height(TimeAxisView::Large); + + previous_height = current_height(); + + if (previous_height < TimeAxisView::hLargest) { + set_height (TimeAxisView::hLarge); } + } else { - set_height(previous_height); + + set_height (previous_height); } } diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index dff81bc5b6..c98f4c5a0f 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -682,7 +682,7 @@ MixerStrip::add_bundle_to_input_menu (boost::shared_ptr b, std::vectornchannels() == _route->n_inputs().n_total()) { + if (b->nchannels() == _route->n_inputs()) { citems.push_back (CheckMenuElem (b->name(), bind (mem_fun(*this, &MixerStrip::bundle_input_chosen), b))); @@ -705,7 +705,7 @@ MixerStrip::add_bundle_to_output_menu (boost::shared_ptr b, std::vector< return; } - if (b->nchannels() == _route->n_outputs().n_total()) { + if (b->nchannels() == _route->n_outputs()) { MenuList& citems = output_menu.items(); citems.push_back (CheckMenuElem (b->name(), bind (mem_fun(*this, &MixerStrip::bundle_output_chosen), b))); @@ -1208,7 +1208,6 @@ MixerStrip::map_frozen () break; } } - hide_redirect_editors (); } @@ -1303,6 +1302,8 @@ MixerStrip::meter_changed (void *src) } gpm.setup_meters (); + // reset peak when meter point changes + gpm.reset_peak_display(); set_width(_width, this); } diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index 6754581b43..b2f8ece64e 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -221,7 +221,7 @@ Mixer_UI::Mixer_UI () signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler)); _selection.RoutesChanged.connect (mem_fun(*this, &Mixer_UI::follow_strip_selection)); - + mix_group_display_button_box->show(); mix_group_add_button->show(); mix_group_remove_button->show(); @@ -797,34 +797,33 @@ Mixer_UI::auto_rebind_midi_controls () pos++; } - PBD::Controllable::CreateBinding ( strip->solo_button->get_controllable(), controlValue, 0); - PBD::Controllable::CreateBinding ( strip->mute_button->get_controllable(), controlValue, 1); + PBD::Controllable::CreateBinding ( strip->solo_button->get_controllable().get(), controlValue, 0); + PBD::Controllable::CreateBinding ( strip->mute_button->get_controllable().get(), controlValue, 1); if( strip->is_audio_track() ) { - PBD::Controllable::CreateBinding ( strip->rec_enable_button->get_controllable(), controlValue, 2); + PBD::Controllable::CreateBinding ( strip->rec_enable_button->get_controllable().get(), controlValue, 2); } - PBD::Controllable::CreateBinding ( strip->gpm.get_controllable(), controlValue, 3); - PBD::Controllable::CreateBinding ( strip->panners.get_controllable(), controlValue, 4); + PBD::Controllable::CreateBinding ( strip->gpm.get_controllable().get(), controlValue, 3); + PBD::Controllable::CreateBinding ( strip->panners.get_controllable().get(), controlValue, 4); } else { // Remove any existing binding - PBD::Controllable::DeleteBinding ( strip->solo_button->get_controllable() ); - PBD::Controllable::DeleteBinding ( strip->mute_button->get_controllable() ); + PBD::Controllable::DeleteBinding ( strip->solo_button->get_controllable().get() ); + PBD::Controllable::DeleteBinding ( strip->mute_button->get_controllable().get() ); if( strip->is_audio_track() ) { - PBD::Controllable::DeleteBinding ( strip->rec_enable_button->get_controllable() ); + PBD::Controllable::DeleteBinding ( strip->rec_enable_button->get_controllable().get() ); } - PBD::Controllable::DeleteBinding ( strip->gpm.get_controllable() ); - PBD::Controllable::DeleteBinding ( strip->panners.get_controllable() ); // This only takes the first panner if there are multiples... + PBD::Controllable::DeleteBinding ( strip->gpm.get_controllable().get() ); + PBD::Controllable::DeleteBinding ( strip->panners.get_controllable().get() ); // This only takes the first panner if there are multiples... } } // for } - struct SignalOrderRouteSorter { bool operator() (boost::shared_ptr a, boost::shared_ptr b) { /* use of ">" forces the correct sort order */ diff --git a/gtk2_ardour/mnemonic-us.bindings.in b/gtk2_ardour/mnemonic-us.bindings.in index 2eafa6e0ad..6326c868f9 100644 --- a/gtk2_ardour/mnemonic-us.bindings.in +++ b/gtk2_ardour/mnemonic-us.bindings.in @@ -79,7 +79,8 @@ (gtk_accel_path "/Common/Save" "<%PRIMARY%>s") (gtk_accel_path "/Editor/duplicate-region" "d") (gtk_accel_path "/Editor/select-all-in-punch-range" "<%PRIMARY%>d") -(gtk_accel_path "/Editor/toggle-follow-playhead" "f") +(gtk_accel_path "/Editor/fit-tracks" "f") +(gtk_accel_path "/Editor/toggle-follow-playhead" "<%PRIMARY%>f") (gtk_accel_path "/Editor/toggle-rhythm-ferret" "<%WINDOW%>f") (gtk_accel_path "/MouseMode/set-mouse-mode-gain" "g") (gtk_accel_path "/Editor/play-selected-regions" "h") @@ -92,11 +93,20 @@ ;; HOME ROW +<<<<<<< .working (gtk_accel_path "/Editor/zoom-to-region" "<%SECONDARY%>z") +======= +(gtk_accel_path "/Editor/zoom-to-region" "<%PRIMARY%><%SECONDARY%>z") +(gtk_accel_path "/Editor/zoom-to-region-both-axes" "<%SECONDARY%>z") +>>>>>>> .merge-right.r3622 (gtk_accel_path "/Editor/undo" "<%PRIMARY%>z") (gtk_accel_path "/Editor/toggle-zoom" "<%TERTIARY%>z") +<<<<<<< .working (gtk_accel_path "/MouseMode/set-mouse-mode-zoom" "z") (gtk_accel_path "/MouseMode/set-mouse-mode-note" "n") +======= +(gtk_accel_path "/MouseMode/set-mouse-mode-zoom" "z") +>>>>>>> .merge-right.r3622 (gtk_accel_path "/Editor/editor-cut" "<%PRIMARY%>x") (gtk_accel_path "/Editor/editor-copy" "<%PRIMARY%>c") (gtk_accel_path "/Common/ToggleColorManager" "<%WINDOW%>c") @@ -178,6 +188,33 @@ (gtk_accel_path "/Editor/select-range-between-cursors" "F6") (gtk_accel_path "/Common/ToggleMaximalEditor" "F11") +(gtk_accel_path "/Editor/save-visual-state-1" "<%PRIMARY%>F1") +(gtk_accel_path "/Editor/save-visual-state-2" "<%PRIMARY%>F2") +(gtk_accel_path "/Editor/save-visual-state-3" "<%PRIMARY%>F3") +(gtk_accel_path "/Editor/save-visual-state-4" "<%PRIMARY%>F4") +(gtk_accel_path "/Editor/save-visual-state-5" "<%PRIMARY%>F5") +(gtk_accel_path "/Editor/save-visual-state-6" "<%PRIMARY%>F6") +(gtk_accel_path "/Editor/save-visual-state-7" "<%PRIMARY%>F7") +(gtk_accel_path "/Editor/save-visual-state-8" "<%PRIMARY%>F8") +(gtk_accel_path "/Editor/save-visual-state-9" "<%PRIMARY%>F9") +(gtk_accel_path "/Editor/save-visual-state-10" "<%PRIMARY%>F10") +(gtk_accel_path "/Editor/save-visual-state-11" "<%PRIMARY%>F11") +(gtk_accel_path "/Editor/save-visual-state-12" "<%PRIMARY%>F12") + +(gtk_accel_path "/Editor/goto-visual-state-1" "<%PRIMARY%>F1") +(gtk_accel_path "/Editor/goto-visual-state-2" "<%PRIMARY%>F2") +(gtk_accel_path "/Editor/goto-visual-state-3" "<%PRIMARY%>F3") +(gtk_accel_path "/Editor/goto-visual-state-4" "<%PRIMARY%>F4") +(gtk_accel_path "/Editor/goto-visual-state-5" "<%PRIMARY%>F5") +(gtk_accel_path "/Editor/goto-visual-state-6" "<%PRIMARY%>F6") +(gtk_accel_path "/Editor/goto-visual-state-7" "<%PRIMARY%>F7") +(gtk_accel_path "/Editor/goto-visual-state-8" "<%PRIMARY%>F8") +(gtk_accel_path "/Editor/goto-visual-state-9" "<%PRIMARY%>F9") +(gtk_accel_path "/Editor/goto-visual-state-10" "<%PRIMARY%>F10") +(gtk_accel_path "/Editor/goto-visual-state-11" "<%PRIMARY%>F11") +(gtk_accel_path "/Editor/goto-visual-state-12" "<%PRIMARY%>F12") + + ;; numbers (gtk_accel_path "/Editor/toggle-edit-mode" "1") diff --git a/gtk2_ardour/option_editor.cc b/gtk2_ardour/option_editor.cc index 2dfa63080d..9ddf9999b9 100644 --- a/gtk2_ardour/option_editor.cc +++ b/gtk2_ardour/option_editor.cc @@ -113,6 +113,7 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui) { using namespace Notebook_Helpers; + first_click_setup = true; click_io_selector = 0; auditioner_io_selector = 0; session = 0; @@ -1036,8 +1037,8 @@ void OptionEditor::clear_click_editor () { if (click_io_selector) { - click_packer.remove (*click_io_selector); - click_packer.remove (*click_gpm); + click_hpacker.remove (*click_io_selector); + click_hpacker.remove (*click_gpm); delete click_io_selector; delete click_gpm; click_io_selector = 0; @@ -1049,31 +1050,59 @@ void OptionEditor::setup_click_editor () { Label* label; - HBox* hpacker = manage (new HBox); + + if (first_click_setup) { + + click_path_entry.set_name ("OptionsEntry"); + click_emphasis_path_entry.set_name ("OptionsEntry"); + + click_path_entry.signal_activate().connect (mem_fun(*this, &OptionEditor::click_sound_changed)); + click_emphasis_path_entry.signal_activate().connect (mem_fun(*this, &OptionEditor::click_emphasis_sound_changed)); + + click_path_entry.signal_focus_out_event().connect (bind (mem_fun(*this, &OptionEditor::focus_out_event_handler), &OptionEditor::click_sound_changed)); + click_emphasis_path_entry.signal_focus_out_event().connect (bind (mem_fun(*this, &OptionEditor::focus_out_event_handler), &OptionEditor::click_emphasis_sound_changed)); + + click_browse_button.set_name ("EditorGTKButton"); + click_emphasis_browse_button.set_name ("EditorGTKButton"); + + click_browse_button.signal_clicked().connect (mem_fun(*this, &OptionEditor::click_browse_clicked)); + click_emphasis_browse_button.signal_clicked().connect (mem_fun(*this, &OptionEditor::click_emphasis_browse_clicked)); + + click_packer.set_border_width (12); + click_packer.set_spacing (5); + + click_table.set_col_spacings (10); + + label = manage(new Label(_("Click audio file"))); + label->set_name ("OptionsLabel"); + click_table.attach (*label, 0, 1, 0, 1, FILL|EXPAND, FILL); + click_table.attach (click_path_entry, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, FILL); + click_table.attach (click_browse_button, 2, 3, 0, 1, FILL|EXPAND, FILL); + + label = manage(new Label(_("Click emphasis audiofile"))); + label->set_name ("OptionsLabel"); + click_table.attach (*label, 0, 1, 1, 2, FILL|EXPAND, FILL); + click_table.attach (click_emphasis_path_entry, 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, FILL); + click_table.attach (click_emphasis_browse_button, 2, 3, 1, 2, FILL|EXPAND, FILL); + + click_packer.pack_start (click_table, false, false); + click_packer.pack_start (click_hpacker, false, false); + + + click_hpacker.set_spacing (10); + + first_click_setup = false; + } click_path_entry.set_sensitive (true); click_emphasis_path_entry.set_sensitive (true); - click_path_entry.set_name ("OptionsEntry"); - click_emphasis_path_entry.set_name ("OptionsEntry"); - - click_path_entry.signal_activate().connect (mem_fun(*this, &OptionEditor::click_sound_changed)); - click_emphasis_path_entry.signal_activate().connect (mem_fun(*this, &OptionEditor::click_emphasis_sound_changed)); - - click_path_entry.signal_focus_out_event().connect (bind (mem_fun(*this, &OptionEditor::focus_out_event_handler), &OptionEditor::click_sound_changed)); - click_emphasis_path_entry.signal_focus_out_event().connect (bind (mem_fun(*this, &OptionEditor::focus_out_event_handler), &OptionEditor::click_emphasis_sound_changed)); - - click_browse_button.set_name ("EditorGTKButton"); - click_emphasis_browse_button.set_name ("EditorGTKButton"); - click_browse_button.signal_clicked().connect (mem_fun(*this, &OptionEditor::click_browse_clicked)); - click_emphasis_browse_button.signal_clicked().connect (mem_fun(*this, &OptionEditor::click_emphasis_browse_clicked)); - - click_packer.set_border_width (12); - click_packer.set_spacing (5); - click_io_selector = new IOSelector (*session, session->click_io(), false); click_gpm = new GainMeter (session->click_io(), *session); + click_hpacker.pack_start (*click_io_selector, false, false); + click_hpacker.pack_start (*click_gpm, false, false); + click_table.set_col_spacings (10); label = manage(new Label(_("Click audio file"))); @@ -1088,13 +1117,6 @@ OptionEditor::setup_click_editor () click_table.attach (click_emphasis_path_entry, 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, FILL); click_table.attach (click_emphasis_browse_button, 2, 3, 1, 2, FILL|EXPAND, FILL); - hpacker->set_spacing (10); - hpacker->pack_start (*click_io_selector, false, false); - hpacker->pack_start (*click_gpm, false, false); - - click_packer.pack_start (click_table, false, false); - click_packer.pack_start (*hpacker, false, false); - click_packer.show_all (); } diff --git a/gtk2_ardour/option_editor.h b/gtk2_ardour/option_editor.h index c6f13049b0..bb12698041 100644 --- a/gtk2_ardour/option_editor.h +++ b/gtk2_ardour/option_editor.h @@ -173,6 +173,8 @@ class OptionEditor : public ArdourDialog IOSelector* click_io_selector; GainMeter* click_gpm; PannerUI* click_panner; + bool first_click_setup; + Gtk::HBox click_hpacker; Gtk::VBox click_packer; Gtk::Table click_table; Gtk::Entry click_path_entry; diff --git a/gtk2_ardour/panner.cc b/gtk2_ardour/panner.cc index 2607cdf2b8..975f1e6b3b 100644 --- a/gtk2_ardour/panner.cc +++ b/gtk2_ardour/panner.cc @@ -35,7 +35,7 @@ null_label_callback (char* buf, unsigned int bufsize) PannerBar::PannerBar (Gtk::Adjustment& adj, boost::shared_ptr c) - : BarController (adj, *c.get(), sigc::ptr_fun (null_label_callback)) + : BarController (adj, c, sigc::ptr_fun (null_label_callback)) { set_style (BarController::Line); } diff --git a/gtk2_ardour/panner2d.cc b/gtk2_ardour/panner2d.cc index a1f99c40d4..6fa64be8e6 100644 --- a/gtk2_ardour/panner2d.cc +++ b/gtk2_ardour/panner2d.cc @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc index d4f0d9eeca..3fe43850a3 100644 --- a/gtk2_ardour/panner_ui.cc +++ b/gtk2_ardour/panner_ui.cc @@ -166,7 +166,7 @@ PannerUI::PannerUI (boost::shared_ptr io, Session& s) show(); } -PBD::Controllable* +boost::shared_ptr PannerUI::get_controllable() { return pan_bars[0]->get_controllable(); diff --git a/gtk2_ardour/panner_ui.h b/gtk2_ardour/panner_ui.h index 093800387d..e10080a317 100644 --- a/gtk2_ardour/panner_ui.h +++ b/gtk2_ardour/panner_ui.h @@ -68,7 +68,7 @@ class PannerUI : public Gtk::HBox void effective_pan_display (); void set_meter_strip_name (string name); - PBD::Controllable* get_controllable(); + boost::shared_ptr get_controllable(); private: friend class MixerStrip; diff --git a/gtk2_ardour/plugin_interest.h b/gtk2_ardour/plugin_interest.h new file mode 100644 index 0000000000..1b7d3c0959 --- /dev/null +++ b/gtk2_ardour/plugin_interest.h @@ -0,0 +1,36 @@ +/* + Copyright (C) 2008 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __gtkardour_plugin_interest_h__ +#define __gtkardour_plugin_interest_h__ + +#include +#include + +typedef std::vector SelectedPlugins; + +class PluginInterestedObject { + public: + PluginInterestedObject() {} + virtual ~PluginInterestedObject() {} + + virtual void use_plugins (const SelectedPlugins&) = 0; +}; + +#endif /* __gtkardour_plugin_interest_h__ */ diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc index aa269be577..87d5532d34 100644 --- a/gtk2_ardour/plugin_selector.cc +++ b/gtk2_ardour/plugin_selector.cc @@ -19,6 +19,7 @@ #include #include +#include #include @@ -51,6 +52,7 @@ static const char* _filter_mode_strings[] = { N_("Type contains"), N_("Author contains"), N_("Library contains"), + N_("Favorites only"), 0 }; @@ -64,9 +66,15 @@ PluginSelector::PluginSelector (PluginManager *mgr) manager = mgr; session = 0; - + _menu = 0; + in_row_change = false; + plugin_model = Gtk::ListStore::create (plugin_columns); plugin_display.set_model (plugin_model); + /* XXX translators: try to convert "Fav" into a short term + related to "favorite" + */ + plugin_display.append_column (_("Fav"), plugin_columns.favorite); plugin_display.append_column (_("Available Plugins"), plugin_columns.name); plugin_display.append_column (_("Type"), plugin_columns.type_name); plugin_display.append_column (_("Category"), plugin_columns.category); @@ -78,6 +86,13 @@ PluginSelector::PluginSelector (PluginManager *mgr) plugin_display.set_headers_visible (true); plugin_display.set_headers_clickable (true); plugin_display.set_reorderable (false); + plugin_display.set_rules_hint (true); + + CellRendererToggle* fav_cell = dynamic_cast(plugin_display.get_column_cell_renderer (0)); + fav_cell->property_activatable() = true; + fav_cell->property_radio() = false; + fav_cell->signal_toggled().connect (mem_fun (*this, &PluginSelector::favorite_changed)); + scroller.set_border_width(10); scroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); scroller.add(plugin_display); @@ -187,6 +202,10 @@ PluginSelector::show_this_plugin (const PluginInfoPtr& info, const std::string& std::string compstr; std::string mode = filter_mode.get_active_text (); + if (mode == _("Favorites only")) { + return manager->is_a_favorite_plugin (info); + } + if (!filterstr.empty()) { if (mode == _("Name contains")) { @@ -197,8 +216,8 @@ PluginSelector::show_this_plugin (const PluginInfoPtr& info, const std::string& compstr = info->creator; } else if (mode == _("Library contains")) { compstr = info->path; - } - + } + transform (compstr.begin(), compstr.end(), compstr.begin(), ::toupper); if (compstr.find (filterstr) != string::npos) { @@ -206,7 +225,6 @@ PluginSelector::show_this_plugin (const PluginInfoPtr& info, const std::string& } else { return false; } - } return true; @@ -224,6 +242,8 @@ PluginSelector::refill () { std::string filterstr; + in_row_change = true; + plugin_model->clear (); setup_filter_string (filterstr); @@ -232,6 +252,8 @@ PluginSelector::refill () lv2_refiller (filterstr); vst_refiller (filterstr); au_refiller (filterstr); + + in_row_change = false; } void @@ -244,11 +266,11 @@ PluginSelector::refiller (const PluginInfoList& plugs, const::std::string& filte if (show_this_plugin (*i, filterstr)) { TreeModel::Row newrow = *(plugin_model->append()); + newrow[plugin_columns.favorite] = manager->is_a_favorite_plugin (*i); newrow[plugin_columns.name] = (*i)->name; newrow[plugin_columns.type_name] = type; newrow[plugin_columns.category] = (*i)->category; - string creator = (*i)->creator; string::size_type pos = 0; @@ -313,18 +335,14 @@ PluginSelector::au_refiller (const std::string& filterstr) #endif } -void -PluginSelector::use_plugin (PluginInfoPtr pi) +PluginPtr +PluginSelector::load_plugin (PluginInfoPtr pi) { if (session == 0) { - return; + return PluginPtr(); } - PluginPtr plugin = pi->load (*session); - - if (plugin) { - PluginCreated (plugin); - } + return pi->load (*session); } void @@ -390,6 +408,7 @@ PluginSelector::run () { ResponseType r; TreeModel::Children::iterator i; + SelectedPlugins plugins; r = (ResponseType) Dialog::run (); @@ -397,24 +416,26 @@ PluginSelector::run () case RESPONSE_APPLY: for (i = amodel->children().begin(); i != amodel->children().end(); ++i) { PluginInfoPtr pp = (*i)[acols.plugin]; - use_plugin (pp); + PluginPtr p = load_plugin (pp); + if (p) { + plugins.push_back (p); + } } + if (interested_object && !plugins.empty()) { + interested_object->use_plugins (plugins); + } + break; default: break; } - cleanup (); - - return (int) r; -} - -void -PluginSelector::cleanup () -{ hide(); amodel->clear(); + interested_object = 0; + + return (int) r; } void @@ -432,6 +453,14 @@ PluginSelector::filter_entry_changed () void PluginSelector::filter_mode_changed () { + std::string mode = filter_mode.get_active_text (); + + if (mode == _("Favorites only")) { + filter_entry.set_sensitive (false); + } else { + filter_entry.set_sensitive (true); + } + refill (); } @@ -441,3 +470,153 @@ PluginSelector::on_show () ArdourDialog::on_show (); filter_entry.grab_focus (); } + +struct PluginMenuCompare { + bool operator() (PluginInfoPtr a, PluginInfoPtr b) const { + int cmp; + + cmp = strcasecmp (a->creator.c_str(), b->creator.c_str()); + + if (cmp < 0) { + return true; + } else if (cmp == 0) { + /* same creator ... compare names */ + if (strcasecmp (a->name.c_str(), b->name.c_str()) < 0) { + return true; + } + } + return false; + } +}; + +Gtk::Menu& +PluginSelector::plugin_menu() +{ + using namespace Menu_Helpers; + + typedef std::map SubmenuMap; + SubmenuMap submenu_map; + + if (!_menu) { + _menu = new Menu(); + _menu->set_name("ArdourContextMenu"); + } + + MenuList& items = _menu->items(); + Menu* favs = new Menu(); + favs->set_name("ArdourContextMenu"); + + items.clear (); + items.push_back (MenuElem (_("Favorites"), *favs)); + items.push_back (MenuElem (_("Plugin Manager"), mem_fun (*this, &PluginSelector::show_manager))); + items.push_back (SeparatorElem ()); + + PluginInfoList all_plugs; + + all_plugs.insert (all_plugs.end(), manager->ladspa_plugin_info().begin(), manager->ladspa_plugin_info().end()); +#ifdef VST_SUPPORT + all_plugs.insert (all_plugs.end(), manager->vst_plugin_info().begin(), manager->vst_plugin_info().end()); +#endif +#ifdef HAVE_AUDIOUNITS + all_plugs.insert (all_plugs.end(), manager->au_plugin_info().begin(), manager->au_plugin_info().end()); +#endif +#ifdef HAVE_SLV2 + all_plugs.insert (all_plugs.end(), manager->lv2_plugin_info().begin(), manager->lv2_plugin_info().end()); +#endif + + PluginMenuCompare cmp; + all_plugs.sort (cmp); + + for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) { + SubmenuMap::iterator x; + Gtk::Menu* submenu; + + string creator = (*i)->creator; + string::size_type pos = 0; + + if (manager->is_a_favorite_plugin (*i)) { + favs->items().push_back (MenuElem ((*i)->name, (bind (mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i)))); + } + + /* stupid LADSPA creator strings */ + + while (pos < creator.length() && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos; + creator = creator.substr (0, pos); + + if ((x = submenu_map.find (creator)) != submenu_map.end()) { + submenu = x->second; + } else { + submenu = new Gtk::Menu; + items.push_back (MenuElem (creator, *submenu)); + submenu_map.insert (pair (creator, submenu)); + submenu->set_name("ArdourContextMenu"); + } + + submenu->items().push_back (MenuElem ((*i)->name, (bind (mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i)))); + } + + return *_menu; +} + +void +PluginSelector::plugin_chosen_from_menu (const PluginInfoPtr& pi) +{ + PluginPtr p = load_plugin (pi); + + if (p && interested_object) { + SelectedPlugins plugins; + plugins.push_back (p); + interested_object->use_plugins (plugins); + } + + interested_object = 0; +} + +void +PluginSelector::favorite_changed (const Glib::ustring& path) +{ + PluginInfoPtr pi; + + if (in_row_change) { + return; + } + + in_row_change = true; + + TreeModel::iterator iter = plugin_model->get_iter (path); + + if (iter) { + + bool favorite = !(*iter)[plugin_columns.favorite]; + + /* change state */ + + (*iter)[plugin_columns.favorite] = favorite; + + /* save new favorites list */ + + pi = (*iter)[plugin_columns.plugin]; + + if (favorite) { + manager->add_favorite (pi->type, pi->unique_id); + } else { + manager->remove_favorite (pi->type, pi->unique_id); + } + + manager->save_favorites (); + } + in_row_change = false; +} + +void +PluginSelector::show_manager () +{ + show_all(); + run (); +} + +void +PluginSelector::set_interested_object (PluginInterestedObject& obj) +{ + interested_object = &obj; +} diff --git a/gtk2_ardour/plugin_selector.h b/gtk2_ardour/plugin_selector.h index fe797588de..c4b613647d 100644 --- a/gtk2_ardour/plugin_selector.h +++ b/gtk2_ardour/plugin_selector.h @@ -26,6 +26,7 @@ #include #include +#include "plugin_interest.h" namespace ARDOUR { class Session; @@ -36,16 +37,21 @@ class PluginSelector : public ArdourDialog { public: PluginSelector (ARDOUR::PluginManager *); - sigc::signal > PluginCreated; + void set_interested_object (PluginInterestedObject&); + int run (); // XXX should we try not to overload the non-virtual Gtk::Dialog::run() ? void set_session (ARDOUR::Session*); void on_show (); + Gtk::Menu& plugin_menu (); + private: + PluginInterestedObject* interested_object; + ARDOUR::Session* session; - Gtk::ScrolledWindow scroller; // Available plugins + Gtk::ScrolledWindow scroller; // Available plugins Gtk::ScrolledWindow ascroller; // Added plugins Gtk::ComboBoxText filter_mode; @@ -58,6 +64,7 @@ class PluginSelector : public ArdourDialog struct PluginColumns : public Gtk::TreeModel::ColumnRecord { PluginColumns () { + add (favorite); add (name); add (type_name); add (category); @@ -68,6 +75,7 @@ class PluginSelector : public ArdourDialog add (midi_outs); add (plugin); } + Gtk::TreeModelColumn favorite; Gtk::TreeModelColumn name; Gtk::TreeModelColumn type_name; Gtk::TreeModelColumn category; @@ -112,10 +120,16 @@ class PluginSelector : public ArdourDialog void added_list_selection_changed(); void display_selection_changed(); void btn_apply_clicked(); - void use_plugin (ARDOUR::PluginInfoPtr); - void cleanup (); + ARDOUR::PluginPtr load_plugin (ARDOUR::PluginInfoPtr); bool show_this_plugin (const ARDOUR::PluginInfoPtr&, const std::string&); void setup_filter_string (std::string&); + + void favorite_changed (const Glib::ustring& path); + bool in_row_change; + + void plugin_chosen_from_menu (const ARDOUR::PluginInfoPtr&); + Gtk::Menu* _menu; + void show_manager (); }; #endif // __ardour_plugin_selector_h__ diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc index 014638e9cd..d3c9effaa2 100644 --- a/gtk2_ardour/plugin_ui.cc +++ b/gtk2_ardour/plugin_ui.cc @@ -51,6 +51,7 @@ #include "utils.h" #include "gui_thread.h" #include "public_editor.h" +#include "keyboard.h" #include "i18n.h" @@ -150,6 +151,20 @@ PluginUIWindow::on_map () set_keep_above (true); } +bool +PluginUIWindow::on_enter_notify_event (GdkEventCrossing *ev) +{ + Keyboard::the_keyboard().enter_window (ev, this); + return false; +} + +bool +PluginUIWindow::on_leave_notify_event (GdkEventCrossing *ev) +{ + Keyboard::the_keyboard().leave_window (ev, this); + return false; +} + void PluginUIWindow::on_show () { diff --git a/gtk2_ardour/plugin_ui.h b/gtk2_ardour/plugin_ui.h index 65b7b0d7fb..acc1e4d53a 100644 --- a/gtk2_ardour/plugin_ui.h +++ b/gtk2_ardour/plugin_ui.h @@ -214,11 +214,14 @@ class PluginUIWindow : public Gtk::Window void resize_preferred(); void set_parent (Gtk::Window*); + bool on_enter_notify_event (GdkEventCrossing*); + bool on_leave_notify_event (GdkEventCrossing*); bool on_key_press_event (GdkEventKey*); bool on_key_release_event (GdkEventKey*); void on_show (); void on_hide (); void on_map (); + private: PlugUIBase* _pluginui; Gtk::Window* parent; diff --git a/gtk2_ardour/po/sv_SE.po b/gtk2_ardour/po/sv_SE.po index d870c203fe..158b1c4cec 100644 --- a/gtk2_ardour/po/sv_SE.po +++ b/gtk2_ardour/po/sv_SE.po @@ -1966,15 +1966,6 @@ msgstr "Tona Ut" msgid "Audition" msgstr "Avlyssna" - -#: gtk2_ardour/editor.cc:105 gtk2_ardour/editor.cc:3517 -msgid "Slide Edit" -msgstr "Glidred." - -#: gtk2_ardour/editor.cc:106 gtk2_ardour/editor.cc:3515 -msgid "Splice Edit" -msgstr "Fogred." - #: gtk2_ardour/editor.cc:111 gtk2_ardour/editor.cc:3572 #: gtk2_ardour/export_dialog.cc:78 gtk2_ardour/export_dialog.cc:92 #: gtk2_ardour/export_dialog.cc:893 gtk2_ardour/export_dialog.cc:1225 @@ -7102,6 +7093,7 @@ msgstr "EJ tonhöjdsändrat soloslagverk" #: gtk2_ardour/editor_timefx.cc:73 msgid "Contents:" msgstr "Innehåll" +<<<<<<< .working #: gtk2_ardour/editor_actions.cc:359 @@ -7442,3 +7434,558 @@ msgstr "FFT-analysfönster" #: gtk2_ardour/analysis_window.cc:135 msgid "Re-analyze data" msgstr "Återanalysera data" +======= + +#: gtk2_ardour/editor_actions.cc:359 +msgid "Playhead to Mouse" +msgstr "Startmarkören till mus" + +#: gtk2_ardour/editor_actions.cc:277 +msgid "Playhead To Active Mark" +msgstr "Startmarkören till aktiv markör" + +#: gtk2_ardour/editor_actions.cc:231 +msgid "Nudge Playhead Forward" +msgstr "Knuffa startmarkören framåt" + +#: gtk2_ardour/editor_actions.cc:233 +msgid "Nudge Playhead Backward" +msgstr "Knuffa startmarkören bakåt" + +#: gtk2_ardour/editor_actions.cc:475 +msgid "Move Forward to Transient" +msgstr "Gå framåt till transient" + +#: gtk2_ardour/editor_actions.cc:477 +msgid "Move Backwards to Transient" +msgstr "Gå bakåt till transient" + +#: gtk2_ardour/editor_actions.cc:235 +msgid "Forward To Grid" +msgstr "Framåt till rutnät" + +#: gtk2_ardour/editor_actions.cc:237 +msgid "Backward To Grid" +msgstr "Bakåt till rutnät" + +#: gtk2_ardour/editor_actions.cc:66 gtk2_ardour/editor.cc:151 +#: gtk2_ardour/editor.cc:3446 +msgid "Active Mark" +msgstr "Aktiv markör" + +#: gtk2_ardour/editor_actions.cc:137 +msgid "to Next Region Boundary" +msgstr "till nästa regionsgränsen" + +#: gtk2_ardour/editor_actions.cc:139 +msgid "to Previous Region Boundary" +msgstr "till förra regionsgränsen" + +#: gtk2_ardour/editor_actions.cc:279 +msgid "Active Mark To Playhead" +msgstr "Aktiv markör till startmarkören" + +#: gtk2_ardour/editor_actions.cc:361 +msgid "Active Marker to Mouse" +msgstr "Aktiv markör till musen" + +#: gtk2_ardour/editor_actions.cc:61 gtk2_ardour/editor_actions.cc:613 +msgid "Markers" +msgstr "Markörer" + +#: gtk2_ardour/ardour_ui_ed.cc:333 +msgid "Punch In/Out" +msgstr "Inslag/utslag" + +#: gtk2_ardour/editor_actions.cc:177 +msgid "Select All Overlapping Edit Range" +msgstr "Välj allt som överlappar redigeringsomfånget" + +#: gtk2_ardour/editor_actions.cc:179 +msgid "Select All Inside Edit Range" +msgstr "Välj allt inom redigeringsomfånget" + +#: gtk2_ardour/editor_actions.cc:182 +msgid "Select Edit Range" +msgstr "Välj redigeringsomfång" + + +#: gtk2_ardour/editor_actions.cc:444 +msgid "Separate Using Punch Range" +msgstr "Separera utifrån in-/utslagsomfånget" + +#: gtk2_ardour/editor_actions.cc:447 +msgid "Separate Using Loop Range" +msgstr "Separera utifrån loopomfånget" + +#: gtk2_ardour/editor_actions.cc:469 +msgid "Split Regions At Percussion Onsets" +msgstr "Dela regioner vid perkussiva anslag" + +#: gtk2_ardour/editor_actions.cc:282 +msgid "Trim Start At Edit Point" +msgstr "Beskär början vid redigeringspunkten" + +#: gtk2_ardour/editor_actions.cc:285 +msgid "Trim End At Edit Point" +msgstr "Beskär slutet vid redigeringspunkten" + +#: gtk2_ardour/ardour_ui_ed.cc:95 +msgid "Misc. Shortcuts" +msgstr "Diverse kortkommandon" + +#: gtk2_ardour/editor_actions.cc:385 +msgid "Boost Region Gain" +msgstr "Öka regionens volym" + +#: gtk2_ardour/editor_actions.cc:388 +msgid "Cut Region Gain" +msgstr "Sänk regionens volym" + +#: gtk2_ardour/editor_actions.cc:99 +msgid "Break drag" +msgstr "Avbryt dragning" + + +#: gtk2_ardour/editor_actions.cc:400 +msgid "Raise Region" +msgstr "Höj regionen" + +#: gtk2_ardour/editor_actions.cc:403 +msgid "Lower Region" +msgstr "Sänk regionen" + +#: gtk2_ardour/editor_actions.cc:415 +msgid "Move To Original Position" +msgstr "Flytta till ursprunglig position" + +#: gtk2_ardour/editor_actions.cc:409 +msgid "Lock Region" +msgstr "Lås region" + +#: gtk2_ardour/editor_actions.cc:397 +msgid "Remove Region Sync" +msgstr "Ta bort regionsynk.-punkt" + +#: gtk2_ardour/editor_actions.cc:505 gtk2_ardour/editor_ops.cc:5651 +msgid "Insert Time" +msgstr "Infoga tid" + +#: gtk2_ardour/editor_actions.cc:93 +msgid "Waveforms" +msgstr "Vågformer" + +#: gtk2_ardour/editor_actions.cc:509 +msgid "Toggle Active" +msgstr "Växla aktiv" + +#: gtk2_ardour/editor_actions.cc:547 +msgid "Zoom Focus Mouse" +msgstr "Zoomfokus: mus" + +#: gtk2_ardour/editor_actions.cc:582 +msgid "Next Snap Mode" +msgstr "Nästa fästläge" + +#: gtk2_ardour/editor_actions.cc:583 +msgid "Next Snap Choice" +msgstr "Nästa fästlägealternativ" + +#: gtk2_ardour/editor_actions.cc:70 +msgid "Primary Clock" +msgstr "Primär klocka" + +#: gtk2_ardour/editor_actions.cc:77 +msgid "Secondary Clock" +msgstr "Sekundär klocka" + +#: gtk2_ardour/ardour_ui_ed.cc:309 gtk2_ardour/ardour_ui_ed.cc:318 +#: gtk2_ardour/editor_actions.cc:616 +msgid "Bars & Beats" +msgstr "Takter & slag" + +#: gtk2_ardour/ardour_ui_ed.cc:311 gtk2_ardour/ardour_ui_ed.cc:320 +msgid "Minutes & Seconds" +msgstr "Minuter & sekunder" + +#: gtk2_ardour/editor_actions.cc:75 +msgid "Rulers" +msgstr "Tidslinjevisning" + +#: gtk2_ardour/editor_actions.cc:619 +msgid "Min:Sec" +msgstr "Min:sek" + +#: gtk2_ardour/editor_actions.cc:615 +msgid "Loop/Punch" +msgstr "Loop-/inslagsmarkörer" + +#: gtk2_ardour/editor_actions.cc:76 +msgid "Scroll" +msgstr "Skrollning" + +#: gtk2_ardour/rhythm_ferret.cc:40 +msgid "Analysis" +msgstr "Analys" + +#: gtk2_ardour/rhythm_ferret.cc:30 +msgid "Percussive Onset" +msgstr "Perkussivt anslag" + +#: gtk2_ardour/rhythm_ferret.cc:31 +msgid "Note Onset" +msgstr "Notanslag" + +#: gtk2_ardour/rhythm_ferret.cc:48 +msgid "Threshold" +msgstr "Tröskel" + +#: gtk2_ardour/rhythm_ferret.cc:51 +msgid "Sensitivity" +msgstr "Känslighet" + +#: gtk2_ardour/rhythm_ferret.cc:52 +msgid "Analyze" +msgstr "Analysera" + +#: gtk2_ardour/rhythm_ferret.cc:55 +msgid "Trigger gap (msecs)" +msgstr "Utlösningsmellanrum (msek)" + +#: gtk2_ardour/rhythm_ferret.cc:43 +msgid "Set Tempo Map" +msgstr "Sätt tempokarta" + +#: gtk2_ardour/rhythm_ferret.cc:44 +msgid "Conform Region" +msgstr "Anpassa region" + +#: gtk2_ardour/rhythm_ferret.cc:39 +msgid "Selection" +msgstr "Markering" + + +#: gtk2_ardour/editor_actions.cc:463 +msgid "Set Tempo from Region=Bar" +msgstr "Sätt tempo från region=takt" + +#: gtk2_ardour/editor_actions.cc:466 +msgid "Set Tempo from Edit Range=Bar" +msgstr "Sätt tempo från redigeringsomfång=takt" + + +#: gtk2_ardour/ardour_ui_ed.cc:548 +msgid "JACK does monitoring" +msgstr "JACK sköter medhörning" + +#: gtk2_ardour/ardour_ui_ed.cc:552 +msgid "Ardour does monitoring" +msgstr "Ardour sköter medhörning" + +#: gtk2_ardour/ardour_ui_ed.cc:553 +msgid "Audio Hardware does monitoring" +msgstr "Ljudhårdvaran sköter medhörning" + +#: gtk2_ardour/ardour_ui_ed.cc:438 +msgid "Tape Machine mode" +msgstr "Bandmaskinläge" + +#: gtk2_ardour/editor_actions.cc:64 +msgid "Misc Options" +msgstr "Diverse inställningar" + +#: gtk2_ardour/ardour_ui_ed.cc:446 +msgid "Create marker at xrun location" +msgstr "Skapa markör vid xrun-förekomst" + +#: gtk2_ardour/ardour_ui_ed.cc:455 +msgid "Rubberbanding Snaps to Grid" +msgstr "Gummibandning fäster mot rutnätet" + +#: gtk2_ardour/ardour_ui_ed.cc:456 +msgid "Auto-analyse new audio" +msgstr "Autoanalysera nya ljud" + +#: gtk2_ardour/editor_actions.cc:689 +msgid "Import to Region List" +msgstr "Importera till regionslistan" + +#: gtk2_ardour/mixer_strip.cc:984 +msgid "Protect against denormals" +msgstr "Skydda mot denormals" + +#: gtk2_ardour/option_editor.cc:1242 +msgid "Keyboard layout" +msgstr "Tangentbordslayout" + +#: gtk2_ardour/option_editor.cc:275 +msgid "Font Scaling" +msgstr "Typsnittsskalning" + +#: gtk2_ardour/option_editor.cc:97 +msgid "Add new MIDI port" +msgstr "Lägg till ny MIDI-port" + + +#: gtk2_ardour/editor.cc:1779 gtk2_ardour/editor.cc:1948 +msgid "Spectral Analysis" +msgstr "Spektralanalys" + +#: gtk2_ardour/editor.cc:1793 +msgid "Glue to Bars&Beats" +msgstr "Klistra mot takt&slag" + +#: gtk2_ardour/analysis_window.cc:46 +msgid "Signal source" +msgstr "Signalkälla" + +#: gtk2_ardour/analysis_window.cc:47 +msgid "Selected ranges" +msgstr "Valda omfång" + +#: gtk2_ardour/analysis_window.cc:48 +msgid "Selected regions" +msgstr "Valda regioner" + +#: gtk2_ardour/analysis_window.cc:50 +msgid "Display model" +msgstr "Visningsmodell" + +#: gtk2_ardour/analysis_window.cc:51 +msgid "Composite graphs for each track" +msgstr "Sammansatt graf för varje spår" + +#: gtk2_ardour/analysis_window.cc:52 +msgid "Composite graph of all tracks" +msgstr "Sammansatt graf för alla spår" + +#: gtk2_ardour/analysis_window.cc:54 +msgid "Show frequency power range" +msgstr "Visa frekvenskraftsomfång" + +#: gtk2_ardour/analysis_window.cc:55 +msgid "Normalize values" +msgstr "Normalisera värden" + +#: gtk2_ardour/analysis_window.cc:59 gtk2_ardour/analysis_window.cc:60 +msgid "FFT analysis window" +msgstr "FFT-analysfönster" + +#: gtk2_ardour/analysis_window.cc:135 +msgid "Re-analyze data" +msgstr "Återanalysera data" + +#: gtk2_ardour/ardour_ui_ed.cc:195 +msgid "Window" +msgstr "Fönster" + +#: gtk2_ardour/ardour_ui_dependents.cc:74 +msgid "Setup Editor" +msgstr "Förbereder redigeraren..." + +#: gtk2_ardour/ardour_ui_dependents.cc:76 +msgid "Setup Mixer" +msgstr "Förbereder mixern..." + +#: gtk2_ardour/ardour_ui_dependents.cc:81 +msgid "Reload Session History" +msgstr "Laddar sessionshistoriken..." + +#: gtk2_ardour/editor.cc:4571 +msgid "Please wait while Ardour loads visual data" +msgstr "Vänta medan Ardour laddar visuell data..." + +#: gtk2_ardour/editor_actions.cc:368 +msgid "Toggle Opaque" +msgstr "Växla genomskinligt" + +#: gtk2_ardour/editor_actions.cc:570 +msgid "Fit Selected Tracks" +msgstr "Rym valda spår" + +#: gtk2_ardour/editor_actions.cc:299 +msgid "Zoom to Region (W&H)" +msgstr "Zooma till region (bredd & höjd)" + +#: gtk2_ardour/editor_actions.cc:76 +msgid "Views" +msgstr "Visningslägen" + + +#: gtk2_ardour/editor_actions.cc:196 +msgid "Save View 1" +msgstr "Spara läge 1" + +#: gtk2_ardour/editor_actions.cc:198 +msgid "Goto View 1" +msgstr "Använd läge 1" + +#: gtk2_ardour/editor_actions.cc:200 +msgid "Save View 2" +msgstr "Spara läge 2" + +#: gtk2_ardour/editor_actions.cc:202 +msgid "Goto View 2" +msgstr "Använd läge 2 " + +#: gtk2_ardour/editor_actions.cc:204 +msgid "Save View 3" +msgstr "Spara läge 3" + +#: gtk2_ardour/editor_actions.cc:206 +msgid "Goto View 3" +msgstr "Använd läge 3" + +#: gtk2_ardour/editor_actions.cc:208 +msgid "Save View 4" +msgstr "Spara läge 4" + +#: gtk2_ardour/editor_actions.cc:210 +msgid "Goto View 4" +msgstr "Använd läge 4" + +#: gtk2_ardour/editor_actions.cc:212 +msgid "Save View 5" +msgstr "Spara läge 5" + +#: gtk2_ardour/editor_actions.cc:214 +msgid "Goto View 5" +msgstr "Använd läge 5" + +#: gtk2_ardour/editor_actions.cc:216 +msgid "Save View 6" +msgstr "Spara läge 6" + +#: gtk2_ardour/editor_actions.cc:218 +msgid "Goto View 6" +msgstr "Använd läge 6" + +#: gtk2_ardour/editor_actions.cc:220 +msgid "Save View 7" +msgstr "Spara läge 7" + +#: gtk2_ardour/editor_actions.cc:222 +msgid "Goto View 7" +msgstr "Använd läge 7" + +#: gtk2_ardour/editor_actions.cc:224 +msgid "Save View 8" +msgstr "Spara läge 8" + +#: gtk2_ardour/editor_actions.cc:226 +msgid "Goto View 8" +msgstr "Använd läge 8" + +#: gtk2_ardour/editor_actions.cc:228 +msgid "Save View 9" +msgstr "Spara läge 9" + +#: gtk2_ardour/editor_actions.cc:230 +msgid "Goto View 9" +msgstr "Använd läge 9" + +#: gtk2_ardour/editor_actions.cc:232 +msgid "Save View 10" +msgstr "Spara läge 10" + +#: gtk2_ardour/editor_actions.cc:234 +msgid "Goto View 10" +msgstr "Använd läge 10" + +#: gtk2_ardour/editor_actions.cc:236 +msgid "Save View 11" +msgstr "Spara läge 11" + +#: gtk2_ardour/editor_actions.cc:238 +msgid "Goto View 11" +msgstr "Använd läge 11" + +#: gtk2_ardour/editor_actions.cc:240 +msgid "Save View 12" +msgstr "Spara läge 12" + +#: gtk2_ardour/editor_actions.cc:242 +msgid "Goto View 12" +msgstr "Använd läge 12" + +#: gtk2_ardour/ardour_ui_ed.cc:462 +msgid "Name New Markers" +msgstr "Namnge nya markörer" + +#: gtk2_ardour/editor_ops.cc:1900 +msgid "Name New Location Marker" +msgstr "Namnge ny platsmarkör" + +#: gtk2_ardour/sfdb_ui.cc:513 +msgid "Search Freesound" +msgstr "Sök i Freesound" + +#: gtk2_ardour/sfdb_ui.cc:480 +msgid "User:" +msgstr "Användarnamn:" + +#: gtk2_ardour/sfdb_ui.cc:484 +msgid "Password:" +msgstr "Lösenord:" + +#: gtk2_ardour/sfdb_ui.cc:400 gtk2_ardour/sfdb_ui.cc:789 +msgid "Start Downloading" +msgstr "Ladda ner" + +#: gtk2_ardour/redirect_box.cc:1190 +msgid "New Plugin" +msgstr "Nytt insticksprogram" + +#: gtk2_ardour/plugin_selector.cc:100 +msgid "Plugins to be connected" +msgstr "Insticksprogram att ansluta" + +#: gtk2_ardour/plugin_selector.cc:156 +msgid "Insert Plugin(s)" +msgstr "Infoga" + +#: gtk2_ardour/plugin_selector.cc:501 +msgid "Favorites" +msgstr "Favoriter" + +#: gtk2_ardour/plugin_selector.cc:502 +msgid "Plugin Manager" +msgstr "Insticksprogram" + +#: gtk2_ardour/plugin_selector.cc:77 +msgid "Fav" +msgstr "" + +#: gtk2_ardour/plugin_selector.cc:78 +msgid "Available Plugins" +msgstr "Tillgängliga insticksprogram" + +#: gtk2_ardour/plugin_selector.cc:80 +msgid "Category" +msgstr "Kategori" + +#: gtk2_ardour/plugin_selector.cc:81 +msgid "Creator" +msgstr "Upphovsperson" + +#: gtk2_ardour/plugin_selector.cc:51 gtk2_ardour/plugin_selector.cc:209 +msgid "Name contains" +msgstr "Namn innehåller" + +#: gtk2_ardour/plugin_selector.cc:52 gtk2_ardour/plugin_selector.cc:211 +msgid "Type contains" +msgstr "Typ innehåller" + +#: gtk2_ardour/plugin_selector.cc:53 gtk2_ardour/plugin_selector.cc:213 +msgid "Author contains" +msgstr "Upphovsperson innehåller" + +#: gtk2_ardour/plugin_selector.cc:54 gtk2_ardour/plugin_selector.cc:215 +msgid "Library contains" +msgstr "Bibliotek innehåller" + +#: gtk2_ardour/plugin_selector.cc:55 gtk2_ardour/plugin_selector.cc:203 +#: gtk2_ardour/plugin_selector.cc:451 +msgid "Favorites only" +msgstr "Endast favoriter" +>>>>>>> .merge-right.r3622 diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc index 9ce28d0aa6..370bb7548b 100644 --- a/gtk2_ardour/processor_box.cc +++ b/gtk2_ardour/processor_box.cc @@ -19,6 +19,7 @@ #include #include +#include #include @@ -46,6 +47,7 @@ #include #include #include +#include #include "ardour_ui.h" #include "ardour_dialog.h" @@ -57,15 +59,14 @@ #include "mixer_ui.h" #include "actions.h" #include "plugin_ui.h" -#include "send_ui.h" #include "io_selector.h" #include "utils.h" #include "gui_thread.h" #include "i18n.h" -#ifdef HAVE_AUDIOUNIT -#include "au_pluginui.h" +#ifdef HAVE_AUDIOUNITS +class AUPluginUI; #endif using namespace sigc; @@ -93,8 +94,8 @@ ProcessorBox::ProcessorBox (Placement pcmnt, Session& sess, boost::shared_ptrset_sizing(TREE_VIEW_COLUMN_FIXED); processor_display.get_column(0)->set_fixed_width(48); - processor_display.set_enable_search (false); - processor_display.add_object_drag (columns.processor.index(), "redirects"); + processor_display.add_object_drag (columns.processor.index(), "processors"); processor_display.signal_object_drop.connect (mem_fun (*this, &ProcessorBox::object_drop)); TreeViewColumn* name_col = processor_display.get_column(0); @@ -153,10 +153,6 @@ ProcessorBox::ProcessorBox (Placement pcmnt, Session& sess, boost::shared_ptr* ptr) { - if (type != "redirects" || cnt == 0 || !ptr) { + if (type != "processors" || cnt == 0 || !ptr) { return; } @@ -210,12 +206,14 @@ void ProcessorBox::remove_processor_gui (boost::shared_ptr processor) { boost::shared_ptr send; - boost::shared_ptr port_processor; + boost::shared_ptr port_insert; + + if ((port_insert = boost::dynamic_pointer_cast (processor)) != 0) { + + PortInsertUI *io_selector = reinterpret_cast (port_insert->get_gui()); + port_insert->set_gui (0); + delete io_selector; - if ((port_processor = boost::dynamic_pointer_cast (processor)) != 0) { - PortInsertUI *io_selector = reinterpret_cast (port_processor->get_gui()); - port_processor->set_gui (0); - delete io_selector; } else if ((send = boost::dynamic_pointer_cast (processor)) != 0) { SendUIWindow *sui = reinterpret_cast (send->get_gui()); send->set_gui (0); @@ -256,6 +254,12 @@ ProcessorBox::show_processor_menu (gint arg) processor_menu = build_processor_menu (); } + Gtk::MenuItem* plugin_menu_item = dynamic_cast(ActionManager::get_widget("/processormenu/newplugin")); + + if (plugin_menu_item) { + plugin_menu_item->set_submenu (_plugin_selector.plugin_menu()); + } + paste_action->set_sensitive (!_rr_selection.processors.empty()); processor_menu->popup (1, arg); @@ -304,7 +308,7 @@ ProcessorBox::processor_button_press_event (GdkEventButton *ev) } else if (processor && ev->button == 1 && selected) { // this is purely informational but necessary - InsertSelected (processor); // emit + ProcessorSelected (processor); // emit } return ret; @@ -340,6 +344,8 @@ ProcessorBox::processor_button_release_event (GdkEventButton *ev) } else if (processor && (ev->button == 2) && (Keyboard::no_modifier_keys_pressed (ev) && ((ev->state & Gdk::BUTTON2_MASK) == Gdk::BUTTON2_MASK))) { + /* button2-click with no modifiers */ + processor->set_active (!processor->active()); ret = true; @@ -352,7 +358,6 @@ Menu * ProcessorBox::build_processor_menu () { processor_menu = dynamic_cast(ActionManager::get_widget("/processormenu") ); - assert(processor_menu != 0); processor_menu->set_name ("ArdourContextMenu"); show_all_children(); @@ -382,26 +387,26 @@ ProcessorBox::deselect_all_processors () void ProcessorBox::choose_plugin () { - sigc::connection newplug_connection = _plugin_selector.PluginCreated.connect (mem_fun(*this,&ProcessorBox::processor_plugin_chosen)); - _plugin_selector.show_all(); - _plugin_selector.run (); - newplug_connection.disconnect(); + _plugin_selector.set_interested_object (*this); } void -ProcessorBox::processor_plugin_chosen (boost::shared_ptr plugin) +ProcessorBox::use_plugins (const SelectedPlugins& plugins) { - if (plugin) { + for (SelectedPlugins::const_iterator p = plugins.begin(); p != plugins.end(); ++p) { - boost::shared_ptr processor (new PluginInsert (_session, plugin, _placement)); + boost::shared_ptr processor (new PluginInsert (_session, *p, _placement)); + + Route::ProcessorStreams err_streams; - Route::ProcessorStreams err; - - if (_route->add_processor (processor, &err)) { - weird_plugin_dialog (*plugin, err, _route); + if (_route->add_processor (processor, &err_streams)) { + weird_plugin_dialog (**p, err_streams, _route); // XXX SHAREDPTR delete plugin here .. do we even need to care? } else { - processor->set_active(true); + + if (Profile->get_sae()) { + processor->set_active (true); + } processor->ActiveChanged.connect (bind (mem_fun (*this, &ProcessorBox::show_processor_active), boost::weak_ptr(processor))); } } @@ -471,7 +476,7 @@ ProcessorBox::weird_plugin_dialog (Plugin& p, Route::ProcessorStreams streams, b } void -ProcessorBox::choose_processor () +ProcessorBox::choose_insert () { boost::shared_ptr processor (new PortInsert (_session, _placement)); processor->ActiveChanged.connect (bind (mem_fun(*this, &ProcessorBox::show_processor_active), boost::weak_ptr(processor))); @@ -494,35 +499,54 @@ ProcessorBox::choose_send () outs = _route->n_outputs(); } - send->io()->ensure_io (ChanCount::ZERO, outs, false, this); + /* XXX need processor lock on route */ - SendUIWindow* gui = new SendUIWindow (send, _session); + try { + send->io()->ensure_io (ChanCount::ZERO, outs, false, this); + } catch (AudioEngine::PortRegistrationFailure& err) { + error << string_compose (_("Cannot set up new send: %1"), err.what()) << endmsg; + return; + } /* let the user adjust the output setup (number and connections) before passing it along to the Route */ - gui->show_all (); - gui->present (); + IOSelectorWindow *ios = new IOSelectorWindow (_session, send->io(), false, true); - /* pass shared_ptr, it will go out of scope when the GUI is deleted */ - /* also, connect it *before* existing handlers so that its definitely executed */ + ios->show_all (); - gui->signal_delete_event().connect (bind (mem_fun(*this, &ProcessorBox::send_io_finished), send, gui), false); + boost::shared_ptr r = boost::static_pointer_cast(send); + + ios->selector().Finished.connect (bind (mem_fun(*this, &ProcessorBox::send_io_finished), boost::weak_ptr(r), ios)); } -bool -ProcessorBox::send_io_finished (GdkEventAny* ev, boost::shared_ptr send, SendUIWindow* sui) +void +ProcessorBox::send_io_finished (IOSelector::Result r, boost::weak_ptr weak_processor, IOSelectorWindow* ios) { - _route->add_processor (send); - delete sui; - return false; + boost::shared_ptr processor (weak_processor.lock()); + + if (!processor) { + return; + } + + switch (r) { + case IOSelector::Cancelled: + // processor will go away when all shared_ptrs to it vanish + break; + + case IOSelector::Accepted: + _route->add_processor (processor); + break; + } + + delete_when_idle (ios); } void ProcessorBox::redisplay_processors () { - ENSURE_GUI_THREAD(mem_fun(*this, &ProcessorBox::redisplay_processors)); + ENSURE_GUI_THREAD (mem_fun(*this, &ProcessorBox::redisplay_processors)); if (no_processor_redisplay) { return; @@ -535,15 +559,15 @@ ProcessorBox::redisplay_processors () processor_active_connections.clear (); processor_name_connections.clear (); - void (ProcessorBox::*pmf)(boost::shared_ptr) = &ProcessorBox::add_processor_to_display; - _route->foreach_processor (this, pmf); + void (ProcessorBox::*method)(boost::shared_ptr) = &ProcessorBox::add_processor_to_display; + _route->foreach_processor (this, method); switch (_placement) { case PreFader: - build_processor_tooltip(processor_eventbox, _("Pre-fader processors, sends & plugins:")); + build_processor_tooltip(processor_eventbox, _("Pre-fader inserts, sends & plugins:")); break; case PostFader: - build_processor_tooltip(processor_eventbox, _("Post-fader processors, sends & plugins:")); + build_processor_tooltip(processor_eventbox, _("Post-fader inserts, sends & plugins:")); break; } } @@ -629,11 +653,7 @@ ProcessorBox::build_processor_tooltip (EventBox& box, string start) for(Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter) { Gtk::TreeModel::Row row = *iter; tip += '\n'; - - /* don't use the column text, since it may be narrowed */ - - boost::shared_ptr i = row[columns.processor]; - tip += i->name(); + tip += row[columns.text]; } ARDOUR_UI::instance()->tooltips().set_tip (box, tip); } @@ -648,14 +668,14 @@ ProcessorBox::show_processor_name (boost::weak_ptr processor) void ProcessorBox::show_processor_active (boost::weak_ptr weak_processor) { - ENSURE_GUI_THREAD(bind (mem_fun(*this, &ProcessorBox::show_processor_active), weak_processor)); - boost::shared_ptr processor (weak_processor.lock()); if (!processor) { return; } + ENSURE_GUI_THREAD(bind (mem_fun(*this, &ProcessorBox::show_processor_active), weak_processor)); + Gtk::TreeModel::Children children = model->children(); Gtk::TreeModel::Children::iterator iter = children.begin(); @@ -693,8 +713,8 @@ ProcessorBox::compute_processor_sort_keys () Gtk::TreeModel::Children children = model->children(); for (Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter) { - boost::shared_ptr i = (*iter)[columns.processor]; - i->set_sort_key (sort_key); + boost::shared_ptr r = (*iter)[columns.processor]; + r->set_sort_key (sort_key); sort_key++; } @@ -966,13 +986,13 @@ ProcessorBox::get_selected_processors (vector >& pr } void -ProcessorBox::for_selected_processors (void (ProcessorBox::*pmf)(boost::shared_ptr)) +ProcessorBox::for_selected_processors (void (ProcessorBox::*method)(boost::shared_ptr)) { vector pathlist = processor_display.get_selection()->get_selected_rows(); for (vector::iterator iter = pathlist.begin(); iter != pathlist.end(); ++iter) { boost::shared_ptr processor = (*(model->get_iter(*iter)))[columns.processor]; - (this->*pmf)(processor); + (this->*method)(processor); } } @@ -999,16 +1019,6 @@ ProcessorBox::all_processors_active (bool state) _route->all_processors_active (_placement, state); } -void -ProcessorBox::all_plugins_active (bool state) -{ - if (state) { - // XXX not implemented - } else { - _route->disable_plugins (_placement); - } -} - void ProcessorBox::ab_plugins () { @@ -1016,6 +1026,7 @@ ProcessorBox::ab_plugins () ab_direction = !ab_direction; } + void ProcessorBox::clear_processors () { @@ -1054,8 +1065,9 @@ void ProcessorBox::edit_processor (boost::shared_ptr processor) { boost::shared_ptr send; - boost::shared_ptr plugin_processor; - boost::shared_ptr port_processor; + boost::shared_ptr plugin_insert; + boost::shared_ptr port_insert; + Window* gidget = 0; if (boost::dynamic_pointer_cast(_route) != 0) { @@ -1070,6 +1082,8 @@ ProcessorBox::edit_processor (boost::shared_ptr processor) return; } + boost::shared_ptr send = boost::dynamic_pointer_cast (processor); + SendUIWindow *send_ui; if (send->get_gui() == 0) { @@ -1086,100 +1100,64 @@ ProcessorBox::edit_processor (boost::shared_ptr processor) send_ui = reinterpret_cast (send->get_gui()); } - if (send_ui->is_visible()) { - send_ui->get_window()->raise (); + gidget = send_ui; + + } else if ((plugin_insert = boost::dynamic_pointer_cast (processor)) != 0) { + + PluginUIWindow *plugin_ui; + + /* these are both allowed to be null */ + + Container* toplevel = get_toplevel(); + Window* win = dynamic_cast(toplevel); + + if (plugin_insert->get_gui() == 0) { + + plugin_ui = new PluginUIWindow (win, plugin_insert); + + WindowTitle title(Glib::get_application_name()); + title += generate_processor_title (plugin_insert); + plugin_ui->set_title (title.get_string()); + + plugin_insert->set_gui (plugin_ui); + + // change window title when route name is changed + _route->NameChanged.connect (bind (mem_fun(*this, &ProcessorBox::route_name_changed), plugin_ui, boost::weak_ptr (plugin_insert))); + } else { - send_ui->show_all (); - send_ui->present (); + plugin_ui = reinterpret_cast (plugin_insert->get_gui()); + plugin_ui->set_parent (win); } - } else if ((plugin_processor = boost::dynamic_pointer_cast (processor)) != 0) { - - ARDOUR::PluginType type = plugin_processor->type(); - - if (type == ARDOUR::LADSPA || type == ARDOUR::VST) { - - PluginUIWindow *plugin_ui; - - /* these are both allowed to be null */ - - Container* toplevel = get_toplevel(); - Window* win = dynamic_cast(toplevel); - - if (plugin_processor->get_gui() == 0) { - - plugin_ui = new PluginUIWindow (win, plugin_processor); - - WindowTitle title(Glib::get_application_name()); - title += generate_processor_title (plugin_processor); - plugin_ui->set_title (title.get_string()); - - plugin_processor->set_gui (plugin_ui); - - // change window title when route name is changed - _route->NameChanged.connect (bind (mem_fun(*this, &ProcessorBox::route_name_changed), plugin_ui, boost::weak_ptr (plugin_processor))); - - } else { - plugin_ui = reinterpret_cast (plugin_processor->get_gui()); - } - - if (plugin_ui->is_visible()) { - plugin_ui->get_window()->raise (); - } else { - plugin_ui->show_all (); - plugin_ui->present (); - } -#ifdef HAVE_AUDIOUNIT - } else if (type == ARDOUR::AudioUnit) { - AUPluginUI* plugin_ui; - if (plugin_processor->get_gui() == 0) { - plugin_ui = new AUPluginUI (plugin_processor); - } else { - plugin_ui = reinterpret_cast (plugin_processor->get_gui()); - } - - plugin_ui = new PluginUIWindow (plugin_insert); - - // plugin_ui->set_keep_above (true); - - WindowTitle title(Glib::get_application_name()); - title += generate_redirect_title (plugin_insert); - plugin_ui->set_title (title.get_string()); - - plugin_insert->set_gui (plugin_ui); - - // change window title when route name is changed - _route->name_changed.connect (bind (mem_fun(*this, &RedirectBox::route_name_changed), plugin_ui, boost::weak_ptr (plugin_insert))); -#endif - - } else { - warning << "Unsupported plugin sent to ProcessorBox::edit_processor()" << endmsg; - return; - } - - } else if ((port_processor = boost::dynamic_pointer_cast (processor)) != 0) { - + gidget = plugin_ui; + + } else if ((port_insert = boost::dynamic_pointer_cast (processor)) != 0) { + if (!_session.engine().connected()) { MessageDialog msg ( _("Not connected to JACK - no I/O changes are possible")); msg.run (); return; } - + PortInsertWindow *io_selector; - - if (port_processor->get_gui() == 0) { - io_selector = new PortInsertWindow (_session, port_processor); - port_processor->set_gui (io_selector); - + + if (port_insert->get_gui() == 0) { + io_selector = new PortInsertWindow (_session, port_insert); + port_insert->set_gui (io_selector); + } else { - io_selector = reinterpret_cast (port_processor->get_gui()); + io_selector = reinterpret_cast (port_insert->get_gui()); } + + gidget = io_selector; + } - if (io_selector->is_visible()) { - io_selector->get_window()->raise (); + if (gidget) { + if (gidget->is_visible()) { + gidget->get_window()->raise (); } else { - io_selector->show_all (); - io_selector->present (); + gidget->show_all (); + gidget->present (); } } } @@ -1208,9 +1186,9 @@ ProcessorBox::register_actions () Glib::RefPtr act; /* new stuff */ - ActionManager::register_action (popup_act_grp, X_("newplugin"), _("New Plugin ..."), sigc::ptr_fun (ProcessorBox::rb_choose_plugin)); + ActionManager::register_action (popup_act_grp, X_("newplugin"), _("New Plugin"), sigc::ptr_fun (ProcessorBox::rb_choose_plugin)); - act = ActionManager::register_action (popup_act_grp, X_("newinsert"), _("New Insert"), sigc::ptr_fun (ProcessorBox::rb_choose_processor)); + act = ActionManager::register_action (popup_act_grp, X_("newinsert"), _("New Insert"), sigc::ptr_fun (ProcessorBox::rb_choose_insert)); ActionManager::jack_sensitive_actions.push_back (act); act = ActionManager::register_action (popup_act_grp, X_("newsend"), _("New Send ..."), sigc::ptr_fun (ProcessorBox::rb_choose_send)); ActionManager::jack_sensitive_actions.push_back (act); @@ -1240,9 +1218,6 @@ ProcessorBox::register_actions () ActionManager::register_action (popup_act_grp, X_("activate_all"), _("Activate all"), sigc::ptr_fun (ProcessorBox::rb_activate_all)); ActionManager::register_action (popup_act_grp, X_("deactivate_all"), _("Deactivate all"), sigc::ptr_fun (ProcessorBox::rb_deactivate_all)); - ActionManager::register_action (popup_act_grp, X_("a_b_plugins"), _("A/B plugins"), sigc::ptr_fun (ProcessorBox::rb_ab_plugins)); - ActionManager::register_action (popup_act_grp, X_("deactivate_plugins"), _("Deactivate plugins"), sigc::ptr_fun (ProcessorBox::rb_deactivate_plugins)); - /* show editors */ act = ActionManager::register_action (popup_act_grp, X_("edit"), _("Edit"), sigc::ptr_fun (ProcessorBox::rb_edit)); ActionManager::plugin_selection_sensitive_actions.push_back(act); @@ -1262,12 +1237,12 @@ ProcessorBox::rb_choose_plugin () } void -ProcessorBox::rb_choose_processor () +ProcessorBox::rb_choose_insert () { if (_current_processor_box == 0) { return; } - _current_processor_box->choose_processor (); + _current_processor_box->choose_insert (); } void @@ -1395,27 +1370,6 @@ ProcessorBox::rb_deactivate_all () _current_processor_box->all_processors_active (false); } -void -ProcessorBox::rb_deactivate_plugins () -{ - if (_current_processor_box == 0) { - return; - } - _current_processor_box->all_plugins_active (false); -} - - -void -ProcessorBox::rb_ab_plugins () -{ - if (_current_processor_box == 0) { - return; - } - - _current_processor_box->ab_plugins (); -} - - void ProcessorBox::rb_edit () { @@ -1430,8 +1384,8 @@ void ProcessorBox::route_name_changed (PluginUIWindow* plugin_ui, boost::weak_ptr wpi) { ENSURE_GUI_THREAD(bind (mem_fun (*this, &ProcessorBox::route_name_changed), plugin_ui, wpi)); + boost::shared_ptr pi (wpi.lock()); - if (pi) { WindowTitle title(Glib::get_application_name()); diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h index b6bb3ae3d7..5d3eb731ca 100644 --- a/gtk2_ardour/processor_box.h +++ b/gtk2_ardour/processor_box.h @@ -37,24 +37,26 @@ #include #include #include +#include +#include #include -#include #include +#include "plugin_interest.h" #include "route_ui.h" #include "io_selector.h" +#include "send_ui.h" #include "enums.h" class MotionController; class PluginSelector; class PluginUIWindow; class RouteRedirectSelection; -class SendUIWindow; namespace ARDOUR { - class Bundle; - class Processor; + class Connection; + class Insert; class Plugin; class PluginInsert; class PortInsert; @@ -63,8 +65,7 @@ namespace ARDOUR { class Session; } - -class ProcessorBox : public Gtk::HBox +class ProcessorBox : public Gtk::HBox, public PluginInterestedObject { public: ProcessorBox (ARDOUR::Placement, ARDOUR::Session&, @@ -78,10 +79,11 @@ class ProcessorBox : public Gtk::HBox void select_all_processors (); void deselect_all_processors (); void select_all_plugins (); + void select_all_inserts (); void select_all_sends (); - sigc::signal > InsertSelected; - sigc::signal > InsertUnselected; + sigc::signal > ProcessorSelected; + sigc::signal > ProcessorUnselected; static void register_actions(); @@ -107,9 +109,9 @@ class ProcessorBox : public Gtk::HBox add (processor); add (color); } - Gtk::TreeModelColumn text; + Gtk::TreeModelColumn text; Gtk::TreeModelColumn > processor; - Gtk::TreeModelColumn color; + Gtk::TreeModelColumn color; }; ModelColumns columns; @@ -122,7 +124,7 @@ class ProcessorBox : public Gtk::HBox static Gdk::Color* inactive_processor_color; Gtk::EventBox processor_eventbox; - //Gtk::HBox processor_hpacker; + Gtk::HBox processor_hpacker; Gtkmm2ext::DnDTreeView > processor_display; Gtk::ScrolledWindow processor_scroller; @@ -143,10 +145,10 @@ class ProcessorBox : public Gtk::HBox void show_processor_menu (gint arg); void choose_send (); - bool send_io_finished (GdkEventAny*,boost::shared_ptr, SendUIWindow*); - void choose_processor (); + void send_io_finished (IOSelector::Result, boost::weak_ptr, IOSelectorWindow*); + void choose_insert (); void choose_plugin (); - void processor_plugin_chosen (boost::shared_ptr); + void use_plugins (const SelectedPlugins&); bool no_processor_redisplay; bool ignore_delete; @@ -164,8 +166,8 @@ class ProcessorBox : public Gtk::HBox void processors_reordered (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator&, int*); void compute_processor_sort_keys (); - vector processor_active_connections; - vector processor_name_connections; + std::vector processor_active_connections; + std::vector processor_name_connections; bool processor_drag_in_progress; void processor_drag_begin (GdkDragContext*); @@ -204,7 +206,7 @@ class ProcessorBox : public Gtk::HBox static bool leave_box (GdkEventCrossing*, ProcessorBox*); static void rb_choose_plugin (); - static void rb_choose_processor (); + static void rb_choose_insert (); static void rb_choose_send (); static void rb_clear (); static void rb_cut (); @@ -218,9 +220,8 @@ class ProcessorBox : public Gtk::HBox static void rb_deactivate (); static void rb_activate_all (); static void rb_deactivate_all (); - static void rb_edit (); static void rb_ab_plugins (); - static void rb_deactivate_plugins (); + static void rb_edit (); void route_name_changed (PluginUIWindow* plugin_ui, boost::weak_ptr pi); std::string generate_processor_title (boost::shared_ptr pi); diff --git a/gtk2_ardour/public_editor.cc b/gtk2_ardour/public_editor.cc index 6797119a1f..399c71caa9 100644 --- a/gtk2_ardour/public_editor.cc +++ b/gtk2_ardour/public_editor.cc @@ -22,13 +22,16 @@ PublicEditor* PublicEditor::_instance = 0; -/** PublicEditor constructor */ +const int PublicEditor::window_border_width = 12; +const int PublicEditor::container_border_width = 12; +const int PublicEditor::vertical_spacing = 6; +const int PublicEditor::horizontal_spacing = 6; + PublicEditor::PublicEditor () : Window (Gtk::WINDOW_TOPLEVEL) { } -/** PublicEditor destructor */ PublicEditor::~PublicEditor() { } diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index e6f576352a..9994f422d4 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -117,14 +117,15 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway virtual void set_snap_threshold (double t) = 0; /** Snap a value according to the current snap setting. */ - virtual void snap_to (nframes_t& first, int32_t direction = 0, bool for_mark = false) = 0; + virtual void snap_to (nframes64_t& first, int32_t direction = 0, bool for_mark = false) = 0; /** Get the current snap value in beats */ - virtual double snap_length_beats (nframes_t start) = 0; + virtual double snap_length_beats (nframes64_t start) = 0; /** Undo some transactions. * @param n Number of transactions to undo. */ + virtual void undo (uint32_t n = 1) = 0; /** Redo some transactions. @@ -188,8 +189,12 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway virtual void toggle_playback (bool with_abort) = 0; virtual void transition_to_rolling (bool fwd) = 0; - virtual nframes_t unit_to_frame (double unit) const = 0; - virtual double frame_to_unit (nframes_t frame) const = 0; + virtual nframes64_t unit_to_frame (double unit) const = 0; + // XXX remove me when libardour goes nframes64_t + double frame_to_unit (nframes_t frame) const { + return frame_to_unit ((nframes64_t) frame); + } + virtual double frame_to_unit (nframes64_t frame) const = 0; virtual double frame_to_unit (double frame) const = 0; virtual nframes64_t pixel_to_frame (double pixel) const = 0; virtual gulong frame_to_pixel (nframes64_t frame) const = 0; @@ -225,7 +230,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway virtual void select_all_tracks () = 0; virtual void set_selected_track (TimeAxisView&, Selection::Operation op = Selection::Set, bool no_remove = false) = 0; virtual void set_selected_mixer_strip (TimeAxisView&) = 0; - virtual void hide_track_in_display (TimeAxisView& tv) = 0; + virtual void hide_track_in_display (TimeAxisView& tv, bool temporary = false) = 0; virtual void show_track_in_display (TimeAxisView& tv) = 0; /** Set whether the editor should follow the playhead. @@ -244,22 +249,24 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway virtual void ensure_float (Gtk::Window&) = 0; virtual void show_window () = 0; virtual TrackViewList* get_valid_views (TimeAxisView*, ARDOUR::RouteGroup* grp = 0) = 0; - virtual nframes_t leftmost_position () const = 0; - virtual nframes_t current_page_frames () const = 0; + virtual nframes64_t leftmost_position() const = 0; + virtual nframes64_t current_page_frames() const = 0; virtual void temporal_zoom_step (bool coarser) = 0; virtual void scroll_tracks_down_line () = 0; virtual void scroll_tracks_up_line () = 0; virtual bool new_regionviews_display_gain () = 0; virtual void prepare_for_cleanup () = 0; - virtual void reset_x_origin (nframes_t frame) = 0; + virtual void finish_cleanup () = 0; + virtual void reset_x_origin (nframes64_t frame) = 0; virtual void remove_last_capture () = 0; virtual void maximise_editing_space () = 0; 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::AnalysisFeatureList&, bool can_ferret) = 0; - virtual void mouse_add_new_marker (nframes_t where, bool is_cd=false, bool is_xrun=false) = 0; + virtual void mouse_add_new_marker (nframes64_t where, bool is_cd=false, bool is_xrun=false) = 0; virtual void foreach_time_axis_view (sigc::slot) = 0; + virtual void add_to_idle_resize (TimeAxisView*,uint32_t) = 0; #ifdef WITH_CMT virtual void add_imageframe_time_axis(const std::string & track_name, void*) = 0; @@ -277,7 +284,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway sigc::signal ZoomChanged; sigc::signal Resized; sigc::signal Realized; - sigc::signal UpdateAllTransportClocks; + sigc::signal UpdateAllTransportClocks; Glib::RefPtr editor_actions; @@ -320,6 +327,15 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway virtual bool canvas_markerview_end_handle_event(GdkEvent* event, ArdourCanvas::Item*,MarkerView*) = 0; #endif + virtual void queue_draw_resize_line (int at) = 0; + virtual void start_resize_line_ops () = 0; + virtual void end_resize_line_ops () = 0; + + static const int window_border_width; + static const int container_border_width; + static const int vertical_spacing; + static const int horizontal_spacing; + /// Singleton instance, set up by Editor::Editor() static PublicEditor* _instance; diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc index fff7243f53..27f9c87819 100644 --- a/gtk2_ardour/region_view.cc +++ b/gtk2_ardour/region_view.cc @@ -64,7 +64,8 @@ RegionView::RegionView (ArdourCanvas::Group* parent, boost::shared_ptr r, double spu, Gdk::Color& basic_color) - : TimeAxisViewItem (r->name(), *parent, tv, spu, basic_color, r->position(), r->length(), + : TimeAxisViewItem (r->name(), *parent, tv, spu, basic_color, r->position(), r->length(), false, + TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText| TimeAxisViewItem::ShowNameHighlight| TimeAxisViewItem::ShowFrame)) @@ -87,11 +88,10 @@ RegionView::RegionView (const RegionView& other) /* derived concrete type will call init () */ _region = other._region; - editor = 0; current_visible_sync_position = other.current_visible_sync_position; valid = false; - _enable_display = false; _pixel_width = other._pixel_width; + _height = other._height; } RegionView::RegionView (const RegionView& other, boost::shared_ptr other_region) @@ -104,7 +104,6 @@ RegionView::RegionView (const RegionView& other, boost::shared_ptr other /* derived concrete type will call init () */ _region = other_region; - editor = other.editor; current_visible_sync_position = other.current_visible_sync_position; valid = false; _pixel_width = other._pixel_width; @@ -116,8 +115,9 @@ RegionView::RegionView (ArdourCanvas::Group* parent, boost::shared_ptr r, double spu, Gdk::Color& basic_color, + bool recording, TimeAxisViewItem::Visibility visibility) - : TimeAxisViewItem (r->name(), *parent, tv, spu, basic_color, r->position(), r->length(), visibility) + : TimeAxisViewItem (r->name(), *parent, tv, spu, basic_color, r->position(), r->length(), recording, visibility) , _region (r) , sync_mark(0) , sync_line(0) @@ -134,10 +134,11 @@ RegionView::RegionView (ArdourCanvas::Group* parent, void RegionView::init (Gdk::Color& basic_color, bool wfd) { - valid = true; - _enable_display = false; - in_destructor = false; - wait_for_data = wfd; + editor = 0; + valid = true; + in_destructor = false; + _height = 0; + wait_for_data = wfd; sync_mark = 0; sync_line = 0; sync_mark = 0; @@ -145,7 +146,10 @@ RegionView::init (Gdk::Color& basic_color, bool wfd) compute_colors (basic_color); - name_highlight->set_data ("regionview", this); + if (name_highlight) { + name_highlight->set_data ("regionview", this); + name_highlight->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_name_highlight_event), name_highlight, this)); + } if (name_text) { name_text->set_data ("regionview", this); @@ -154,17 +158,16 @@ RegionView::init (Gdk::Color& basic_color, bool wfd) if (wfd) _enable_display = true; - set_y_position_and_height (0, trackview.height - 2); + set_height (trackview.current_height()); _region->StateChanged.connect (mem_fun(*this, &RegionView::region_changed)); group->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_event), group, this)); - name_highlight->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_name_highlight_event), name_highlight, this)); set_colors (); ColorsChanged.connect (mem_fun (*this, &RegionView::color_handler)); - // set_pango_fontsize(); + /* XXX sync mark drag? */ } @@ -517,7 +520,7 @@ RegionView::region_sync_changed () points.clear (); points.push_back (Gnome::Art::Point (offset, 0)); - points.push_back (Gnome::Art::Point (offset, trackview.height - NAME_HIGHLIGHT_SIZE)); + points.push_back (Gnome::Art::Point (offset, trackview.current_height() - NAME_HIGHLIGHT_SIZE)); sync_line->property_points().set_value (points); sync_line->show (); diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h index 19d13ccf03..579b6e5594 100644 --- a/gtk2_ardour/region_view.h +++ b/gtk2_ardour/region_view.h @@ -101,6 +101,7 @@ class RegionView : public TimeAxisViewItem boost::shared_ptr, double samples_per_unit, Gdk::Color& basic_color, + bool recording, TimeAxisViewItem::Visibility); virtual void region_resized (ARDOUR::Change); diff --git a/gtk2_ardour/rhythm_ferret.cc b/gtk2_ardour/rhythm_ferret.cc index 63440e7ab1..4a4f3d4ec4 100644 --- a/gtk2_ardour/rhythm_ferret.cc +++ b/gtk2_ardour/rhythm_ferret.cc @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -32,6 +33,17 @@ static const gchar * _analysis_mode_strings[] = { 0 }; +static const gchar * _onset_function_strings[] = { + N_("Energy Based"), + N_("Spectral Difference"), + N_("High-Frequency Content"), + N_("Complex Domain"), + N_("Phase Deviation"), + N_("Kullback-Liebler"), + N_("Modified Kullback-Liebler"), + 0 +}; + RhythmFerret::RhythmFerret (PublicEditor& e) : ArdourDialog (_("Rhythm Ferret")) , editor (e) @@ -50,6 +62,13 @@ RhythmFerret::RhythmFerret (PublicEditor& e) , sensitivity_scale (sensitivity_adjustment) , sensitivity_label (_("Sensitivity")) , analyze_button (_("Analyze")) + , onset_function_label (_("Detection function")) + , peak_picker_threshold_adjustment (0.3, 0.0, 1.0, 0.01, 0.1) + , peak_picker_threshold_scale (peak_picker_threshold_adjustment) + , peak_picker_label (_("Peak Threshold")) + , silence_threshold_adjustment (-90.0, -120.0, 0.0, 1, 10) + , silence_threshold_scale (silence_threshold_adjustment) + , silence_label (_("Silent Threshold (dB)")) , trigger_gap_adjustment (3, 0, 100, 1, 10) , trigger_gap_spinner (trigger_gap_adjustment) , trigger_gap_label (_("Trigger gap (msecs)")) @@ -78,6 +97,14 @@ RhythmFerret::RhythmFerret (PublicEditor& e) analysis_mode_strings = I18N (_analysis_mode_strings); Gtkmm2ext::set_popdown_strings (analysis_mode_selector, analysis_mode_strings); analysis_mode_selector.set_active_text (analysis_mode_strings.front()); + analysis_mode_selector.signal_changed().connect (mem_fun (*this, &RhythmFerret::analysis_mode_changed)); + + onset_function_strings = I18N (_onset_function_strings); + Gtkmm2ext::set_popdown_strings (onset_detection_function_selector, onset_function_strings); + /* Onset plugin uses complex domain as default function + XXX there should be a non-hacky way to set this + */ + onset_detection_function_selector.set_active_text (onset_function_strings[3]); box = manage (new HBox); box->set_spacing (6); @@ -85,17 +112,7 @@ RhythmFerret::RhythmFerret (PublicEditor& e) box->pack_start (analysis_mode_selector, true, true); ferret_packer.pack_start (*box, false, false); - box = manage (new HBox); - box->set_spacing (6); - box->pack_start (detection_threshold_label, false, false); - box->pack_start (detection_threshold_scale, true, true); - ferret_packer.pack_start (*box, false, false); - - box = manage (new HBox); - box->set_spacing (6); - box->pack_start (sensitivity_label, false, false); - box->pack_start (sensitivity_scale, true, true); - ferret_packer.pack_start (*box, false, false); + ferret_packer.pack_start (analysis_packer, false, false); box = manage (new HBox); box->set_spacing (6); @@ -107,6 +124,38 @@ RhythmFerret::RhythmFerret (PublicEditor& e) analyze_button.signal_clicked().connect (mem_fun (*this, &RhythmFerret::run_analysis)); + box = manage (new HBox); + box->set_spacing (6); + box->pack_start (detection_threshold_label, false, false); + box->pack_start (detection_threshold_scale, true, true); + perc_onset_packer.pack_start (*box, false, false); + + box = manage (new HBox); + box->set_spacing (6); + box->pack_start (sensitivity_label, false, false); + box->pack_start (sensitivity_scale, true, true); + perc_onset_packer.pack_start (*box, false, false); + + box = manage (new HBox); + box->set_spacing (6); + box->pack_start (onset_function_label, false, false); + box->pack_start (onset_detection_function_selector, true, true); + note_onset_packer.pack_start (*box, false, false); + + box = manage (new HBox); + box->set_spacing (6); + box->pack_start (peak_picker_label, false, false); + box->pack_start (peak_picker_threshold_scale, true, true); + note_onset_packer.pack_start (*box, false, false); + + box = manage (new HBox); + box->set_spacing (6); + box->pack_start (silence_label, false, false); + box->pack_start (silence_threshold_scale, true, true); + note_onset_packer.pack_start (*box, false, false); + + analysis_mode_changed (); + ferret_frame.add (ferret_packer); logo = manage (new Gtk::Image (::get_icon (X_("ferret_02")))); @@ -137,12 +186,30 @@ RhythmFerret::~RhythmFerret() } } +void +RhythmFerret::analysis_mode_changed () +{ + analysis_packer.children().clear (); + + switch (get_analysis_mode()) { + case PercussionOnset: + analysis_packer.pack_start (perc_onset_packer); + break; + + case NoteOnset: + analysis_packer.pack_start (note_onset_packer); + break; + } + + analysis_packer.show_all (); +} + RhythmFerret::AnalysisMode RhythmFerret::get_analysis_mode () const { string str = analysis_mode_selector.get_active_text (); - if (str == _(_analysis_mode_strings[(int) NoteOnset])) { + if (str == analysis_mode_strings[(int) NoteOnset]) { return NoteOnset; } @@ -184,6 +251,9 @@ RhythmFerret::run_analysis () case PercussionOnset: run_percussion_onset_analysis (rd, (*i)->region()->position(), current_results); break; + case NoteOnset: + run_note_onset_analysis (rd, (*i)->region()->position(), current_results); + break; default: break; } @@ -232,6 +302,67 @@ RhythmFerret::run_percussion_onset_analysis (boost::shared_ptr readabl return 0; } +int +RhythmFerret::get_note_onset_function () +{ + string txt = onset_detection_function_selector.get_active_text(); + + for (int n = 0; _onset_function_strings[n]; ++n) { + /* compare translated versions */ + if (txt == onset_function_strings[n]) { + return n; + } + } + fatal << string_compose (_("programming error: %1 (%2)"), X_("illegal note onset function string"), txt) + << endmsg; + /*NOTREACHED*/ + return -1; +} + +int +RhythmFerret::run_note_onset_analysis (boost::shared_ptr readable, nframes64_t offset, AnalysisFeatureList& results) +{ + try { + OnsetDetector t (session->frame_rate()); + + for (uint32_t i = 0; i < readable->n_channels(); ++i) { + + AnalysisFeatureList these_results; + + t.reset (); + + t.set_function (get_note_onset_function()); + t.set_silence_threshold (silence_threshold_adjustment.get_value()); + t.set_peak_threshold (peak_picker_threshold_adjustment.get_value()); + + if (t.run ("", readable.get(), i, these_results)) { + continue; + } + + /* translate all transients to give absolute position */ + + 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 (); + } + + } catch (failed_constructor& err) { + error << "Could not load note onset detection plugin" << endmsg; + return -1; + } + + if (!results.empty()) { + OnsetDetector::cleanup_onsets (results, session->frame_rate(), trigger_gap_adjustment.get_value()); + } + + return 0; +} + void RhythmFerret::do_action () { @@ -277,6 +408,7 @@ RhythmFerret::do_split_action () i = tmp; } + session->commit_reversible_command (); } diff --git a/gtk2_ardour/rhythm_ferret.h b/gtk2_ardour/rhythm_ferret.h index 2ddb2a4ffd..91c10695ad 100644 --- a/gtk2_ardour/rhythm_ferret.h +++ b/gtk2_ardour/rhythm_ferret.h @@ -71,6 +71,9 @@ class RhythmFerret : public ArdourDialog { Gtk::VBox ferret_packer; Gtk::ComboBoxText analysis_mode_selector; Gtk::Label analysis_mode_label; + + /* transient detection widgets */ + Gtk::Adjustment detection_threshold_adjustment; Gtk::HScale detection_threshold_scale; Gtk::Label detection_threshold_label; @@ -78,22 +81,44 @@ class RhythmFerret : public ArdourDialog { Gtk::HScale sensitivity_scale; Gtk::Label sensitivity_label; Gtk::Button analyze_button; + Gtk::VBox perc_onset_packer; + + /* onset detection widgets */ + + Gtk::ComboBoxText onset_detection_function_selector; + Gtk::Label onset_function_label; + Gtk::Adjustment peak_picker_threshold_adjustment; + Gtk::HScale peak_picker_threshold_scale; + Gtk::Label peak_picker_label; + Gtk::Adjustment silence_threshold_adjustment; + Gtk::HScale silence_threshold_scale; + Gtk::Label silence_label; + Gtk::VBox note_onset_packer; + + /* generic stuff */ + Gtk::Adjustment trigger_gap_adjustment; Gtk::SpinButton trigger_gap_spinner; Gtk::Label trigger_gap_label; + Gtk::VBox analysis_packer; + Gtk::Label operation_clarification_label; Gtk::Button action_button; std::vector analysis_mode_strings; + std::vector onset_function_strings; ARDOUR::AnalysisFeatureList current_results; AnalysisMode get_analysis_mode () const; Action get_action() const; + void analysis_mode_changed (); + int get_note_onset_function (); void run_analysis (); int run_percussion_onset_analysis (boost::shared_ptr region, nframes64_t offset, ARDOUR::AnalysisFeatureList& results); + int run_note_onset_analysis (boost::shared_ptr region, nframes64_t offset, ARDOUR::AnalysisFeatureList& results); void do_action (); void do_split_action (); diff --git a/gtk2_ardour/route_params_ui.cc b/gtk2_ardour/route_params_ui.cc index 497e99ba61..f39d41def5 100644 --- a/gtk2_ardour/route_params_ui.cc +++ b/gtk2_ardour/route_params_ui.cc @@ -235,10 +235,10 @@ RouteParams_UI::setup_processor_boxes() pre_redir_hpane.pack1 (*pre_insert_box); post_redir_hpane.pack1 (*post_insert_box); - pre_insert_box->InsertSelected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PreFader)); - pre_insert_box->InsertUnselected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PreFader)); - post_insert_box->InsertSelected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PostFader)); - post_insert_box->InsertUnselected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PostFader)); + pre_insert_box->ProcessorSelected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PreFader)); + pre_insert_box->ProcessorUnselected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PreFader)); + post_insert_box->ProcessorSelected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PostFader)); + post_insert_box->ProcessorUnselected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PostFader)); pre_redir_hpane.show_all(); post_redir_hpane.show_all(); diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index a5619b8ae9..82777944f4 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -87,11 +87,12 @@ using namespace std; Glib::RefPtr RouteTimeAxisView::slider; -int +void RouteTimeAxisView::setup_slider_pix () { - slider = ::get_icon ("fader_belt_h"); - return 0; + if ((slider = ::get_icon ("fader_belt_h")) == 0) { + throw failed_constructor (); + } } RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::shared_ptr rt, Canvas& canvas) @@ -105,18 +106,12 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh size_button (_("h")), // height automation_button (_("a")), visual_button (_("v")), - lm (rt, sess), - underlay_xml_node (0), - gain_slider (0), - gain_adjustment (0.781787, 0.0, 1.0, 0.01, 0.1) + gm (rt, sess, slider, true) { - if (slider == 0) { - setup_slider_pix (); - } + gm.get_level_meter().set_no_show_all(); + gm.get_level_meter().setup_meters(50); - lm.set_no_show_all(); - lm.setup_meters(50); _has_state = true; playlist_menu = 0; playlist_action_menu = 0; @@ -127,8 +122,6 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh destructive_track_mode_item = 0; normal_track_mode_item = 0; - gain_slider = manage (new HSliderController (slider, &gain_adjustment, *_route->gain_control().get(), false)); - ignore_toggle = false; edit_group_button.set_name ("TrackGroupButton"); @@ -175,7 +168,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh } - controls_hbox.pack_start(lm, false, false); + controls_hbox.pack_start(gm.get_level_meter(), false, false); _route->meter_change.connect (mem_fun(*this, &RouteTimeAxisView::meter_changed)); _route->input_changed.connect (mem_fun(*this, &RouteTimeAxisView::io_changed)); _route->output_changed.connect (mem_fun(*this, &RouteTimeAxisView::io_changed)); @@ -184,7 +177,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh controls_table.attach (*solo_button, 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0); controls_table.attach (edit_group_button, 7, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0); - controls_table.attach (*gain_slider, 0, 5, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 0, 0); + controls_table.attach (gm.get_gain_slider(), 0, 5, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 0, 0); ARDOUR_UI::instance()->tooltips().set_tip(*solo_button,_("Solo")); ARDOUR_UI::instance()->tooltips().set_tip(*mute_button,_("Mute")); @@ -239,14 +232,8 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh editor.ZoomChanged.connect (mem_fun(*this, &RouteTimeAxisView::reset_samples_per_unit)); ColorsChanged.connect (mem_fun (*this, &RouteTimeAxisView::color_handler)); - gain_slider->signal_button_press_event().connect (mem_fun(*this, &RouteTimeAxisView::start_gain_touch)); - gain_slider->signal_button_release_event().connect (mem_fun(*this, &RouteTimeAxisView::end_gain_touch)); - gain_slider->set_name ("TrackGainFader"); - - gain_adjustment.signal_value_changed().connect (mem_fun(*this, &RouteTimeAxisView::gain_adjusted)); - _route->gain_control()->Changed.connect (mem_fun(*this, &RouteTimeAxisView::gain_changed)); - - gain_slider->show_all(); + gm.get_gain_slider().signal_scroll_event().connect(mem_fun(*this, &RouteTimeAxisView::controls_ebox_scroll), false); + gm.get_gain_slider().set_name ("TrackGainFader"); } RouteTimeAxisView::~RouteTimeAxisView () @@ -285,6 +272,7 @@ RouteTimeAxisView::post_construct () /* map current state of the route */ update_diskstream_display (); + subplugin_menu.items().clear (); _route->foreach_processor (this, &RouteTimeAxisView::add_processor_to_subplugin_menu); _route->foreach_processor (this, &RouteTimeAxisView::add_existing_processor_automation_curves); @@ -306,69 +294,6 @@ RouteTimeAxisView::playlist_modified () { } -void -RouteTimeAxisView::set_state (const XMLNode& node) -{ - const XMLProperty *prop; - - TimeAxisView::set_state (node); - - if ((prop = node.property ("shown_editor")) != 0) { - if (prop->value() == "no") { - _marked_for_display = false; - } else { - _marked_for_display = true; - } - } else { - _marked_for_display = true; - } - - XMLNodeList nlist = node.children(); - XMLNodeConstIterator niter; - XMLNode *child_node; - - _show_automation.clear(); - - for (niter = nlist.begin(); niter != nlist.end(); ++niter) { - child_node = *niter; - - if (child_node->name() == AutomationTimeAxisView::state_node_name) { - XMLProperty* prop = child_node->property ("automation-id"); - if (!prop) - continue; - - Parameter param(prop->value()); - if (!param) - continue; - - bool show = false; - - prop = child_node->property ("shown"); - - if (prop && prop->value() == "yes") { - show = true; - _show_automation.insert(param); - } - - if (_automation_tracks.find(param) == _automation_tracks.end()) { - create_automation_child(param, show); - } - } - else if (child_node->name() == "Underlays") { - underlay_xml_node = child_node; - - /* Wait for all gui tracks to be loaded as underlays are cross referencing tracks*/ - Glib::signal_idle().connect(mem_fun(*this, &RouteTimeAxisView::set_underlay_state)); - } - } -} - -XMLNode* -RouteTimeAxisView::get_automation_child_xml_node (Parameter param) -{ - return RouteUI::get_automation_child_xml_node (param); -} - gint RouteTimeAxisView::edit_click (GdkEventButton *ev) { @@ -632,6 +557,7 @@ RouteTimeAxisView::build_display_menu () route_active_menu_item->set_active (_route->active()); items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Hide"), mem_fun(*this, &RouteTimeAxisView::hide_click))); items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route))); } @@ -768,7 +694,7 @@ RouteTimeAxisView::show_timestretch (nframes_t start, nframes_t end) x1 = start / editor.get_current_zoom(); x2 = (end - 1) / editor.get_current_zoom(); - y2 = height - 2; + y2 = current_height() - 2; timestretch_rect->property_x1() = x1; timestretch_rect->property_y1() = 1.0; @@ -807,55 +733,30 @@ RouteTimeAxisView::show_selection (TimeSelection& ts) } void -RouteTimeAxisView::set_height (TrackHeight h) +RouteTimeAxisView::set_height (uint32_t h) { - int gmlen = (height_to_pixels (h)) - 5; - bool height_changed = (height == 0) || (h != height_style); - lm.setup_meters (gmlen); + int gmlen = h - 5; + bool height_changed = (height == 0) || (h != height); + gm.get_level_meter().setup_meters (gmlen); + TimeAxisView::set_height (h); ensure_xml_node (); if (_view) { - _view->set_height ((double) height); + _view->set_height ((double) current_height()); } - switch (height_style) { - case Largest: - xml_node->add_property ("track_height", "largest"); - break; + char buf[32]; + snprintf (buf, sizeof (buf), "%u", height); + xml_node->add_property ("height", buf); - case Large: - xml_node->add_property ("track_height", "large"); - break; - - case Larger: - xml_node->add_property ("track_height", "larger"); - break; - - case Normal: - xml_node->add_property ("track_height", "normal"); - break; - - case Smaller: - xml_node->add_property ("track_height", "smaller"); - break; - - case Small: - xml_node->add_property ("track_height", "small"); - break; - } - - switch (height_style) { - case Largest: - case Large: - case Larger: - case Normal: + if (height >= hNormal) { reset_meter(); show_name_entry (); hide_name_label (); - gain_slider->show(); + gm.get_gain_slider().show(); mute_button->show(); solo_button->show(); if (rec_enable_button) @@ -870,14 +771,14 @@ RouteTimeAxisView::set_height (TrackHeight h) if (is_track() && track()->mode() == ARDOUR::Normal) { playlist_button.show(); } - break; - case Smaller: + } else if (height >= hSmaller) { + reset_meter(); show_name_entry (); hide_name_label (); - gain_slider->hide(); + gm.get_gain_slider().hide(); mute_button->show(); solo_button->show(); if (rec_enable_button) @@ -892,13 +793,13 @@ RouteTimeAxisView::set_height (TrackHeight h) if (is_track() && track()->mode() == ARDOUR::Normal) { playlist_button.hide (); } - break; - case Small: + } else { + hide_name_entry (); show_name_label (); - - gain_slider->hide(); + + gm.get_gain_slider().hide(); mute_button->hide(); solo_button->hide(); if (rec_enable_button) @@ -911,7 +812,6 @@ RouteTimeAxisView::set_height (TrackHeight h) automation_button.hide (); playlist_button.hide (); name_label.set_text (_route->name()); - break; } if (height_changed) { @@ -1630,7 +1530,7 @@ RouteTimeAxisView::automation_track_hidden (Parameter param) ran->menu_item->set_active (false); } - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */ } @@ -1664,10 +1564,9 @@ RouteTimeAxisView::show_all_automation () no_redraw = false; - /* Redraw */ - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */ } void @@ -1699,8 +1598,8 @@ RouteTimeAxisView::show_existing_automation () } no_redraw = false; - - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + + _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */ } void @@ -1728,7 +1627,7 @@ RouteTimeAxisView::hide_all_automation () _show_automation.clear(); no_redraw = false; - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */ } @@ -1869,7 +1768,7 @@ RouteTimeAxisView::processor_automation_track_hidden (RouteTimeAxisView::Process i->mark_automation_visible (pan->what, false); - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */ } void @@ -1902,7 +1801,7 @@ RouteTimeAxisView::add_automation_child(Parameter param, boost::shared_ptrHiding.connect (bind (mem_fun (*this, &RouteTimeAxisView::automation_track_hidden), param)); bool hideit = (!show); - + XMLNode* node; if ((node = track->get_state_node()) != 0) { @@ -1918,8 +1817,11 @@ RouteTimeAxisView::add_automation_child(Parameter param, boost::shared_ptrhide (); } else { - _show_automation.insert(param); - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + _show_automation.insert (param); + + if (!no_redraw) { + _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */ + } } build_display_menu(); @@ -2041,7 +1943,7 @@ RouteTimeAxisView::processor_menu_item_toggled (RouteTimeAxisView::ProcessorAuto /* now trigger a redisplay */ - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + _route->gui_changed ("visible_tracks", (void *) 0); /* EMIT_SIGNAL */ } } @@ -2079,7 +1981,7 @@ RouteTimeAxisView::processors_changed () /* change in visibility was possible */ - _route->gui_changed ("track_height", this); + _route->gui_changed ("visible_tracks", this); } boost::shared_ptr @@ -2131,14 +2033,14 @@ RouteTimeAxisView::automation_child(ARDOUR::Parameter param) void RouteTimeAxisView::fast_update () { - lm.update_meters (); + gm.get_level_meter().update_meters (); } void RouteTimeAxisView::hide_meter () { clear_meter (); - lm.hide_meters (); + gm.get_level_meter().hide_meters (); } void @@ -2151,7 +2053,7 @@ void RouteTimeAxisView::reset_meter () { if (Config->get_show_track_meters()) { - lm.setup_meters (height-5); + gm.get_level_meter().setup_meters (height-5); } else { hide_meter (); } @@ -2160,7 +2062,7 @@ RouteTimeAxisView::reset_meter () void RouteTimeAxisView::clear_meter () { - lm.clear_meters (); + gm.get_level_meter().clear_meters (); } void @@ -2290,36 +2192,3 @@ RouteTimeAxisView::remove_underlay(StreamView* v) } } -gint -RouteTimeAxisView::start_gain_touch (GdkEventButton* ev) -{ - _route->gain_control()->list()->start_touch (); - return FALSE; -} - -gint -RouteTimeAxisView::end_gain_touch (GdkEventButton* ev) -{ - _route->gain_control()->list()->stop_touch (); - return FALSE; -} - -void -RouteTimeAxisView::gain_adjusted () -{ - _route->set_gain (slider_position_to_gain (gain_adjustment.get_value()), this); -} - -void -RouteTimeAxisView::gain_changed () -{ - Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &RouteTimeAxisView::effective_gain_display)); -} - -void -RouteTimeAxisView::effective_gain_display () -{ - gfloat value = gain_to_slider_position (_route->effective_gain()); - gain_adjustment.set_value (value); -} - diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h index e318451832..230ea45b86 100644 --- a/gtk2_ardour/route_time_axis.h +++ b/gtk2_ardour/route_time_axis.h @@ -40,7 +40,7 @@ #include "enums.h" #include "time_axis_view.h" #include "canvas.h" -#include "level_meter.h" +#include "gain_meter.h" namespace ARDOUR { @@ -74,7 +74,7 @@ public: void show_selection (TimeSelection&); void set_samples_per_unit (double); - void set_height (TimeAxisView::TrackHeight); + void set_height (uint32_t h); void show_timestretch (nframes_t start, nframes_t end); void hide_timestretch (); void selection_click (GdkEventButton*); @@ -117,6 +117,10 @@ public: virtual void create_automation_child (ARDOUR::Parameter param, bool show) = 0; + /* make sure we get the right version of this */ + + XMLNode* get_automation_child_xml_node (ARDOUR::Parameter param) { return RouteUI::get_automation_child_xml_node (param); } + typedef map AutomationTracks; AutomationTracks automation_tracks() { return _automation_tracks; } @@ -134,7 +138,9 @@ public: void clear_meter (); void io_changed (ARDOUR::IOChange, void *); void meter_changed (void *); - void effective_gain_display (); + void effective_gain_display () { gm.effective_gain_display(); } + + static void setup_slider_pix (); protected: friend class StreamView; @@ -297,11 +303,9 @@ protected: void post_construct (); - void set_state (const XMLNode&); - - XMLNode* get_automation_child_xml_node (ARDOUR::Parameter param); + GainMeterBase gm; - LevelMeter lm; + static Glib::RefPtr slider; XMLNode* underlay_xml_node; bool set_underlay_state(); @@ -310,16 +314,6 @@ protected: UnderlayList _underlay_streams; typedef list UnderlayMirrorList; UnderlayMirrorList _underlay_mirrors; - - Gtkmm2ext::HSliderController *gain_slider; - Gtk::Adjustment gain_adjustment; - static Glib::RefPtr slider; - static int setup_slider_pix (); - void gain_adjusted(); - - gint start_gain_touch (GdkEventButton*); - gint end_gain_touch (GdkEventButton*); - void gain_changed (); }; #endif /* __ardour_route_time_axis_h__ */ diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index 9c88bec37c..4d1d92ac5a 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -81,10 +81,10 @@ RouteUI::RouteUI (boost::shared_ptr rt, ARDOUR::Session& sess, co _route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed)); - mute_button = manage (new BindableToggleButton (*_route->mute_control().get(), m_name )); + mute_button = manage (new BindableToggleButton (_route->mute_control(), m_name )); mute_button->set_self_managed (true); - solo_button = manage (new BindableToggleButton (*_route->solo_control().get(), s_name )); + solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name )); solo_button->set_self_managed (true); mute_button->set_name ("MuteButton"); @@ -105,7 +105,7 @@ RouteUI::RouteUI (boost::shared_ptr rt, ARDOUR::Session& sess, co _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed)); - rec_enable_button = manage (new BindableToggleButton (*t->rec_enable_control().get(), r_name )); + rec_enable_button = manage (new BindableToggleButton (t->rec_enable_control(), r_name )); rec_enable_button->set_name ("RecordEnableButton"); rec_enable_button->set_self_managed (true); diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h index 20ac152f83..aecf351f3a 100644 --- a/gtk2_ardour/route_ui.h +++ b/gtk2_ardour/route_ui.h @@ -124,10 +124,6 @@ class RouteUI : public virtual AxisView int set_color_from_route (); - sigc::connection blink_connection; - - void rec_enable_button_blink (bool onoff, ARDOUR::AudioDiskstream *, Gtk::Widget *w); - void remove_this_route (); static gint idle_remove_this_route (RouteUI *); diff --git a/gtk2_ardour/send_ui.cc b/gtk2_ardour/send_ui.cc index c91068f97c..90ff3de717 100644 --- a/gtk2_ardour/send_ui.cc +++ b/gtk2_ardour/send_ui.cc @@ -44,7 +44,7 @@ SendUI::SendUI (boost::shared_ptr s, Session& se) vbox.pack_start (hbox, false, false, false); vbox.pack_start (panners, false,false); - io = new IOSelector (se, s->io(), false); + io = manage (new IOSelector (se, s->io(), false)); pack_start (vbox, false, false); @@ -70,7 +70,7 @@ SendUI::SendUI (boost::shared_ptr s, Session& se) SendUI::~SendUI () { _send->set_metering (false); - + /* XXX not clear that we need to do this */ screen_update_connection.disconnect(); @@ -121,8 +121,8 @@ SendUIWindow::SendUIWindow (boost::shared_ptr s, Session& ss) add (vpacker); set_name ("SendUIWindow"); - - s->GoingAway.connect (mem_fun (*this, &SendUIWindow::send_going_away)); + + going_away_connection = s->GoingAway.connect (mem_fun (*this, &SendUIWindow::send_going_away)); signal_delete_event().connect (bind (ptr_fun (just_hide_it), reinterpret_cast (this))); @@ -138,5 +138,6 @@ SendUIWindow::send_going_away () { ENSURE_GUI_THREAD (mem_fun (*this, &SendUIWindow::send_going_away)); delete_when_idle (this); + going_away_connection.disconnect (); } diff --git a/gtk2_ardour/send_ui.h b/gtk2_ardour/send_ui.h index 0cd4b1a265..5a7298c515 100644 --- a/gtk2_ardour/send_ui.h +++ b/gtk2_ardour/send_ui.h @@ -42,6 +42,8 @@ class SendUI : public Gtk::HBox IOSelector* io; + boost::shared_ptr& send() { return _send; } + private: boost::shared_ptr _send; ARDOUR::Session& _session; @@ -70,6 +72,7 @@ class SendUIWindow : public Gtk::Window Gtk::HBox hpacker; void send_going_away (); + sigc::connection going_away_connection; }; #endif /* __ardour_gtk_send_ui_h__ */ diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc index b7b853ebec..77c7f59afc 100644 --- a/gtk2_ardour/sfdb_ui.cc +++ b/gtk2_ardour/sfdb_ui.cc @@ -404,16 +404,19 @@ SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::S found_list_view (found_list), freesound_search_btn (_("Start Downloading")), freesound_list_view (freesound_list) - { resetting_ourselves = false; gm = 0; + resetting_ourselves = false; + gm = 0; + if (ARDOUR::Profile->get_sae()) { chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops"); chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files"); } + //add the file chooser { chooser.set_border_width (12); @@ -426,14 +429,14 @@ SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::S matchall_filter.add_pattern ("*.*"); matchall_filter.set_name (_("All files")); - + chooser.add_filter (audio_filter); chooser.add_filter (midi_filter); chooser.add_filter (matchall_filter); chooser.set_select_multiple (true); chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview)); chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated)); - + if (!persistent_folder.empty()) { chooser.set_current_folder (persistent_folder); } @@ -445,11 +448,6 @@ SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::S VBox* vbox; HBox* hbox; - hpacker.set_spacing (6); - hpacker.pack_start (notebook, true, true); - hpacker.pack_start (preview, false, false); - - get_vbox()->pack_start (hpacker, true, true); hbox = manage(new HBox); hbox->pack_start (found_entry); @@ -474,7 +472,6 @@ SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::S notebook.append_page (*vbox, _("Search Tags")); } - //add freesound search #ifdef FREESOUND @@ -483,12 +480,6 @@ SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::S HBox* passbox; Label* label; - hpacker.set_spacing (6); - hpacker.pack_start (notebook, true, true); - hpacker.pack_start (preview, false, false); - - get_vbox()->pack_start (hpacker, true, true); - passbox = manage(new HBox); passbox->set_border_width (12); passbox->set_spacing (6); @@ -522,10 +513,8 @@ SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::S //freesound_list_view.get_selection()->set_mode (SELECTION_MULTIPLE); freesound_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::freesound_list_view_activated)); - freesound_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked)); freesound_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::freesound_search_clicked)); - notebook.append_page (*vbox, _("Search Freesound")); } #endif @@ -1083,11 +1072,9 @@ SoundFileOmega::check_info (const vector& paths, bool& same_size, bool& for (vector::const_iterator i = paths.begin(); i != paths.end(); ++i) { if (AudioFileSource::get_soundfile_info (*i, info, errmsg)) { - if (info.channels > 1) { multichannel = true; } - if (sz == 0) { sz = info.length; } else { diff --git a/gtk2_ardour/sfdb_ui.h b/gtk2_ardour/sfdb_ui.h index a0be66493c..24cb08cc1b 100644 --- a/gtk2_ardour/sfdb_ui.h +++ b/gtk2_ardour/sfdb_ui.h @@ -150,6 +150,7 @@ class SoundFileBrowser : public ArdourDialog Gtk::FileFilter audio_filter; Gtk::FileFilter midi_filter; + Gtk::FileFilter custom_filter; Gtk::FileFilter matchall_filter; Gtk::HBox hpacker; diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc index 46cb078c63..0f52f07939 100644 --- a/gtk2_ardour/streamview.cc +++ b/gtk2_ardour/streamview.cc @@ -66,7 +66,7 @@ StreamView::StreamView (RouteTimeAxisView& tv, ArdourCanvas::Group* group) canvas_rect->property_x1() = 0.0; canvas_rect->property_y1() = 0.0; canvas_rect->property_x2() = _trackview.editor.frame_to_pixel (max_frames); - canvas_rect->property_y2() = (double) tv.height; + canvas_rect->property_y2() = (double) tv.current_height(); canvas_rect->property_outline_what() = (guint32) (0x2|0x8); // outline RHS and bottom // (Fill/Outline colours set in derived classes) diff --git a/gtk2_ardour/streamview.h b/gtk2_ardour/streamview.h index cb7a3332cd..7cb5830dcb 100644 --- a/gtk2_ardour/streamview.h +++ b/gtk2_ardour/streamview.h @@ -112,7 +112,7 @@ protected: void update_rec_box (); //virtual void update_rec_regions () = 0; - virtual RegionView* add_region_view_internal (boost::shared_ptr, bool wait_for_data) = 0; + virtual RegionView* add_region_view_internal (boost::shared_ptr, bool wait_for_waves, bool recording = false) = 0; virtual void remove_region_view (boost::weak_ptr ); //void remove_rec_region (boost::shared_ptr); (unused) diff --git a/gtk2_ardour/tape_region_view.cc b/gtk2_ardour/tape_region_view.cc index 9791d0a7aa..21bc41800e 100644 --- a/gtk2_ardour/tape_region_view.cc +++ b/gtk2_ardour/tape_region_view.cc @@ -53,7 +53,7 @@ TapeAudioRegionView::TapeAudioRegionView (ArdourCanvas::Group *parent, RouteTime double spu, Gdk::Color& basic_color) - : AudioRegionView (parent, tv, r, spu, basic_color, + : AudioRegionView (parent, tv, r, spu, basic_color, false, TimeAxisViewItem::Visibility ((r->position() != 0) ? default_tape_visibility : TimeAxisViewItem::Visibility (default_tape_visibility|TimeAxisViewItem::HideFrameLeft))) { diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc index 3259ac8a28..0973fb9c93 100644 --- a/gtk2_ardour/time_axis_view.cc +++ b/gtk2_ardour/time_axis_view.cc @@ -74,7 +74,6 @@ bool TimeAxisView::need_size_info = true; TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisView* rent, Canvas& canvas) : AxisView (sess), editor (ed), - height_style(Small), y_position(0), order(0), controls_table (2, 8) @@ -105,6 +104,7 @@ TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisVie _has_state = false; last_name_entry_key_press_event = 0; name_packing = NamePackingBits (0); + resize_drag_start = -1; /* Create the standard LHS Controls @@ -140,7 +140,23 @@ TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisVie controls_table.show_all (); controls_table.set_no_show_all (); + resizer.set_size_request (10, 10); + resizer.set_name ("ResizeHandle"); + resizer.signal_expose_event().connect (mem_fun (*this, &TimeAxisView::resizer_expose)); + resizer.signal_button_press_event().connect (mem_fun (*this, &TimeAxisView::resizer_button_press)); + resizer.signal_button_release_event().connect (mem_fun (*this, &TimeAxisView::resizer_button_release)); + resizer.signal_motion_notify_event().connect (mem_fun (*this, &TimeAxisView::resizer_motion)); + resizer.set_events (Gdk::BUTTON_PRESS_MASK| + Gdk::BUTTON_RELEASE_MASK| + Gdk::POINTER_MOTION_MASK| + Gdk::SCROLL_MASK); + + resizer_box.pack_start (resizer, false, false); + resizer.show (); + resizer_box.show(); + controls_vbox.pack_start (controls_table, false, false); + controls_vbox.pack_end (resizer_box, false, true); controls_vbox.show (); //controls_ebox.set_name ("TimeAxisViewControlsBaseUnselected"); @@ -238,9 +254,9 @@ TimeAxisView::show_at (double y, int& nth, VBox *parent) _hidden = false; /* height in pixels depends on _order, so update it now we've changed _order */ - set_height (height_style); + set_height (height); - effective_height = height; + effective_height = current_height(); /* now show children */ @@ -267,6 +283,9 @@ TimeAxisView::controls_ebox_scroll (GdkEventScroll* ev) if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) { step_height (true); return true; + } else if (Keyboard::no_modifiers_active (ev->state)) { + editor.scroll_tracks_up_line(); + return true; } break; @@ -274,6 +293,9 @@ TimeAxisView::controls_ebox_scroll (GdkEventScroll* ev) if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) { step_height (false); return true; + } else if (Keyboard::no_modifiers_active (ev->state)) { + editor.scroll_tracks_down_line(); + return true; } break; @@ -338,39 +360,21 @@ TimeAxisView::hide () void TimeAxisView::step_height (bool bigger) { - - if (height == hLargest) { - if (!bigger) set_height (Large); - return; - } - if (height == hLarge) { - if (bigger) set_height (Largest); - else set_height (Larger); - return; - } - if (height == hLarger) { - if (bigger) set_height (Large); - else set_height (Normal); - return; - } - if (height == hNormal) { - if (bigger) set_height (Larger); - else set_height (Smaller); - return; - } - if (height == hSmaller) { - if (bigger) set_height (Normal); - else set_height (Small); - return; - } - if (height == hSmall) { - if (bigger) set_height (Smaller); - return; - } + static const uint32_t step = 20; + + if (bigger) { + set_height (height + step); + } else { + if (height > step) { + set_height (std::max (height - step, hSmall)); + } else if (height != hSmall) { + set_height (hSmall); + } + } } void -TimeAxisView::set_heights (TrackHeight h) +TimeAxisView::set_heights (uint32_t h) { TrackSelection& ts (editor.get_selection().tracks); @@ -380,27 +384,20 @@ TimeAxisView::set_heights (TrackHeight h) } void -TimeAxisView::set_height (TrackHeight h) +TimeAxisView::set_height(uint32_t h) { - height_style = h; - set_height_pixels (height_to_pixels (h)); + height = h; for (list::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { (*i)->set_height (); } -} -void -TimeAxisView::set_height_pixels (uint32_t h) -{ - height = h; - controls_hbox.set_size_request (-1, height + ((order == 0) ? 1 : 0)); - //cerr << "TimeAxisView::set_height_pixels() called h = " << h << endl;//DEBUG if (canvas_item_visible (selection_group)) { /* resize the selection rect */ show_selection (editor.get_selection().time); } - + + reshow_feature_lines (); } bool @@ -440,8 +437,11 @@ TimeAxisView::name_entry_key_release (GdkEventKey* ev) } } - if ((*i)->height_style == Small) { - (*i)->set_height(Smaller); + + /* resize to show editable name display */ + + if ((*i)->current_height() >= hSmall && (*i)->current_height() < hNormal) { + (*i)->set_height (hSmaller); } (*i)->name_entry.grab_focus(); @@ -549,7 +549,6 @@ TimeAxisView::conditionally_add_to_selection () Selection& s (editor.get_selection()); if (!s.selected (this)) { - cerr << "set selected track\n"; editor.set_selected_track (*this, Selection::Set); } } @@ -617,6 +616,8 @@ TimeAxisView::set_selected (bool yn) (*i)->set_selected (false); } } + + resizer.queue_draw (); } void @@ -628,12 +629,12 @@ TimeAxisView::build_size_menu () size_menu->set_name ("ArdourContextMenu"); MenuList& items = size_menu->items(); - items.push_back (MenuElem (_("Largest"), bind (mem_fun (*this, &TimeAxisView::set_heights), Largest))); - items.push_back (MenuElem (_("Large"), bind (mem_fun (*this, &TimeAxisView::set_heights), Large))); - items.push_back (MenuElem (_("Larger"), bind (mem_fun (*this, &TimeAxisView::set_heights), Larger))); - items.push_back (MenuElem (_("Normal"), bind (mem_fun (*this, &TimeAxisView::set_heights), Normal))); - items.push_back (MenuElem (_("Smaller"), bind (mem_fun (*this, &TimeAxisView::set_heights),Smaller))); - items.push_back (MenuElem (_("Small"), bind (mem_fun (*this, &TimeAxisView::set_heights), Small))); + items.push_back (MenuElem (_("Largest"), bind (mem_fun (*this, &TimeAxisView::set_heights), hLargest))); + items.push_back (MenuElem (_("Large"), bind (mem_fun (*this, &TimeAxisView::set_heights), hLarge))); + items.push_back (MenuElem (_("Larger"), bind (mem_fun (*this, &TimeAxisView::set_heights), hLarger))); + items.push_back (MenuElem (_("Normal"), bind (mem_fun (*this, &TimeAxisView::set_heights), hNormal))); + items.push_back (MenuElem (_("Smaller"), bind (mem_fun (*this, &TimeAxisView::set_heights),hSmaller))); + items.push_back (MenuElem (_("Small"), bind (mem_fun (*this, &TimeAxisView::set_heights), hSmall))); } void @@ -716,7 +717,7 @@ TimeAxisView::show_selection (TimeSelection& ts) x1 = editor.frame_to_unit (start); x2 = editor.frame_to_unit (start + cnt - 1); - y2 = height; + y2 = current_height(); rect->rect->property_x1() = x1; rect->rect->property_y1() = 1.0; @@ -936,7 +937,7 @@ TimeAxisView::touched (double top, double bot) y_position is the "origin" or "top" of the track. */ - double mybot = y_position + height; + double mybot = y_position + current_height(); return ((y_position <= bot && y_position >= top) || ((mybot <= bot) && (top < mybot)) || @@ -969,68 +970,69 @@ TimeAxisView::get_parent_with_state () return parent->get_parent_with_state (); } -void + +XMLNode& +TimeAxisView::get_state () +{ + XMLNode* node = new XMLNode ("TAV-" + name()); + char buf[32]; + + snprintf (buf, sizeof(buf), "%u", height); + node->add_property ("height", buf); + node->add_property ("marked_for_display", (_marked_for_display ? "1" : "0")); + return *node; +} + +int TimeAxisView::set_state (const XMLNode& node) { const XMLProperty *prop; + if ((prop = node.property ("marked_for_display")) != 0) { + _marked_for_display = (prop->value() == "1"); + } + if ((prop = node.property ("track_height")) != 0) { if (prop->value() == "largest") { - set_height (Largest); + set_height (hLargest); } else if (prop->value() == "large") { - set_height (Large); + set_height (hLarge); } else if (prop->value() == "larger") { - set_height (Larger); + set_height (hLarger); } else if (prop->value() == "normal") { - set_height (Normal); + set_height (hNormal); } else if (prop->value() == "smaller") { - set_height (Smaller); + set_height (hSmaller); } else if (prop->value() == "small") { - set_height (Small); + set_height (hSmall); } else { error << string_compose(_("unknown track height name \"%1\" in XML GUI information"), prop->value()) << endmsg; set_height (Normal); } + } else if ((prop = node.property ("height")) != 0) { + + set_height (atoi (prop->value())); + } else { - set_height (Normal); + + set_height (hNormal); } + + return 0; } void TimeAxisView::reset_height() { - set_height_pixels (height); + set_height (height); for (Children::iterator i = children.begin(); i != children.end(); ++i) { - (*i)->set_height_pixels ((TrackHeight)(*i)->height); + (*i)->set_height ((*i)->height); } } -uint32_t -TimeAxisView::height_to_pixels (TrackHeight h) -{ - switch (h) { - case Largest: - return hLargest; - case Large: - return hLarge; - case Larger: - return hLarger; - case Normal: - return hNormal; - case Smaller: - return hSmaller; - case Small: - return hSmall; - } - - // what is wrong with gcc ? - - return hNormal; -} - void TimeAxisView::compute_controls_size_info () { @@ -1039,7 +1041,8 @@ TimeAxisView::compute_controls_size_info () Gtk::Table one_row_table (1, 8); Button* buttons[5]; const int border_width = 2; - const int extra_height = (2 * border_width) + 2; // 2 pixels for the controls frame + const int extra_height = (2 * border_width) + 2 // 2 pixels for the controls frame + + 10; // resizer button window.add (one_row_table); @@ -1213,8 +1216,6 @@ TimeAxisView::reshow_feature_lines () while (feature_lines.size()< analysis_features.size()) { ArdourCanvas::SimpleLine* l = new ArdourCanvas::SimpleLine (*canvas_display); l->property_color_rgba() = (guint) ARDOUR_UI::config()->canvasvar_ZeroLine.get(); - l->property_y1() = 0; - l->property_y2() = height; feature_lines.push_back (l); } @@ -1230,7 +1231,90 @@ TimeAxisView::reshow_feature_lines () for (i = analysis_features.begin(), l = feature_lines.begin(); i != analysis_features.end() && l != feature_lines.end(); ++i, ++l) { (*l)->property_x1() = editor.frame_to_pixel (*i); (*l)->property_x2() = editor.frame_to_pixel (*i); + (*l)->property_y1() = 0; + (*l)->property_y2() = current_height(); (*l)->show (); } } +bool +TimeAxisView::resizer_button_press (GdkEventButton* event) +{ + resize_drag_start = event->y_root; + resize_idle_target = current_height(); + editor.start_resize_line_ops (); + return true; +} + +bool +TimeAxisView::resizer_button_release (GdkEventButton* ev) +{ + resize_drag_start = -1; + editor.end_resize_line_ops (); + return true; +} + +void +TimeAxisView::idle_resize (uint32_t h) +{ + set_height (h); +} + +bool +TimeAxisView::resizer_motion (GdkEventMotion* ev) +{ + if (resize_drag_start < 0) { + return true; + } + + int32_t delta = (int32_t) floor (resize_drag_start - ev->y_root); + + resize_idle_target = std::max (resize_idle_target - delta, (int) hSmall); + editor.add_to_idle_resize (this, resize_idle_target); + + resize_drag_start = ev->y_root; + + return true; +} + +bool +TimeAxisView::resizer_expose (GdkEventExpose* event) +{ + int w, h, x, y, d; + Glib::RefPtr win (resizer.get_window()); + Glib::RefPtr dark (resizer.get_style()->get_fg_gc (STATE_NORMAL)); + Glib::RefPtr light (resizer.get_style()->get_bg_gc (STATE_NORMAL)); + + win->draw_rectangle (controls_ebox.get_style()->get_bg_gc(STATE_NORMAL), + true, + event->area.x, + event->area.y, + event->area.width, + event->area.height); + + win->get_geometry (x, y, w, h, d); + + /* handle/line #1 */ + + win->draw_line (dark, 0, 0, w - 2, 0); + win->draw_point (dark, 0, 1); + win->draw_line (light, 1, 1, w - 1, 1); + win->draw_point (light, w - 1, 0); + + /* handle/line #2 */ + + win->draw_line (dark, 0, 4, w - 2, 4); + win->draw_point (dark, 0, 5); + win->draw_line (light, 1, 5, w - 1, 5); + win->draw_point (light, w - 1, 4); + + /* handle/line #3 */ + + win->draw_line (dark, 0, 8, w - 2, 8); + win->draw_point (dark, 0, 9); + win->draw_line (light, 1, 9, w - 1, 9); + win->draw_point (light, w - 1, 8); + + return true; +} + diff --git a/gtk2_ardour/time_axis_view.h b/gtk2_ardour/time_axis_view.h index 96db8aba93..ae4d035af8 100644 --- a/gtk2_ardour/time_axis_view.h +++ b/gtk2_ardour/time_axis_view.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -32,6 +33,8 @@ #include +#include + #include #include #include @@ -69,7 +72,7 @@ class GhostRegion; * This class provides the basic LHS controls and display methods. This should be * extended to create functional time-axis based views. */ -class TimeAxisView : public virtual AxisView +class TimeAxisView : public virtual AxisView, public PBD::Stateful { private: enum NamePackingBits { @@ -78,15 +81,6 @@ class TimeAxisView : public virtual AxisView }; public: - enum TrackHeight { - Largest, - Large, - Larger, - Normal, - Smaller, - Small - }; - static uint32_t hLargest; static uint32_t hLarge; static uint32_t hLarger; @@ -94,23 +88,24 @@ class TimeAxisView : public virtual AxisView static uint32_t hSmaller; static uint32_t hSmall; - static uint32_t height_to_pixels (TrackHeight); - TimeAxisView(ARDOUR::Session& sess, PublicEditor& ed, TimeAxisView* parent, ArdourCanvas::Canvas& canvas); virtual ~TimeAxisView (); + XMLNode& get_state (void); + int set_state (const XMLNode&); + /* public data: XXX create accessor/mutators for these ?? */ PublicEditor& editor; - TrackHeight height_style; - uint32_t height; /* in canvas units */ - uint32_t effective_height; /* in canvas units */ - double y_position; - int order; + uint32_t effective_height; /* in canvas units */ + double y_position; + int order; - ArdourCanvas::Group *canvas_display; - Gtk::VBox *control_parent; + uint32_t current_height() const { return height; } + + ArdourCanvas::Group *canvas_display; + Gtk::VBox *control_parent; /* The Standard LHS Controls */ Gtk::Frame controls_frame; @@ -119,10 +114,21 @@ class TimeAxisView : public virtual AxisView Gtk::Table controls_table; Gtk::EventBox controls_ebox; Gtk::VBox controls_vbox; + Gtk::DrawingArea resizer; + Gtk::HBox resizer_box; Gtk::HBox name_hbox; Gtk::Frame name_frame; Gtkmm2ext::FocusEntry name_entry; - + + bool resizer_button_press (GdkEventButton*); + bool resizer_button_release (GdkEventButton*); + bool resizer_motion (GdkEventMotion*); + bool resizer_expose (GdkEventExpose*); + + double resize_drag_start; + int32_t resize_idle_target; + void idle_resize (uint32_t); + void hide_name_label (); void hide_name_entry (); void show_name_label (); @@ -152,7 +158,7 @@ class TimeAxisView : public virtual AxisView virtual void entered () {} virtual void exited () {} - virtual void set_height (TrackHeight h); + virtual void set_height (uint32_t h); void reset_height(); /** @@ -222,9 +228,6 @@ class TimeAxisView : public virtual AxisView void set_parent (TimeAxisView& p); bool has_state () const; - virtual void set_state (const XMLNode&); - virtual XMLNode* get_state_node () { return 0; } - /* call this on the parent */ virtual XMLNode* get_automation_child_xml_node (ARDOUR::Parameter param) { return 0; } @@ -232,6 +235,7 @@ class TimeAxisView : public virtual AxisView typedef std::vector > Children; protected: + uint32_t height; /* in canvas units */ string controls_base_unselected_name; string controls_base_selected_name; @@ -327,10 +331,11 @@ class TimeAxisView : public virtual AxisView static void compute_controls_size_info (); static bool need_size_info; - void set_heights (TrackHeight); - void set_height_pixels (uint32_t h); + void set_heights (uint32_t h); void color_handler (); - list feature_lines; + + + std::list feature_lines; ARDOUR::AnalysisFeatureList analysis_features; void reshow_feature_lines (); diff --git a/gtk2_ardour/time_axis_view_item.cc b/gtk2_ardour/time_axis_view_item.cc index f4316efd87..fa520f4ca1 100644 --- a/gtk2_ardour/time_axis_view_item.cc +++ b/gtk2_ardour/time_axis_view_item.cc @@ -70,9 +70,9 @@ double TimeAxisViewItem::NAME_HIGHLIGHT_THRESH; * @param duration the duration of this item */ TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group& parent, TimeAxisView& tv, double spu, Gdk::Color& base_color, - nframes_t start, nframes_t duration, + nframes_t start, nframes_t duration, bool recording, Visibility vis) - : trackview (tv) + : trackview (tv), _recregion(recording) { if (!have_name_font) { @@ -151,7 +151,7 @@ TimeAxisViewItem::init (const string& it_name, double spu, Gdk::Color& base_colo vestigial_frame->property_x1() = (double) 0.0; vestigial_frame->property_y1() = (double) 1.0; vestigial_frame->property_x2() = 2.0; - vestigial_frame->property_y2() = (double) trackview.height; + vestigial_frame->property_y2() = (double) trackview.current_height(); vestigial_frame->property_outline_what() = 0xF; vestigial_frame->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_VestigialFrame.get(); vestigial_frame->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_VestigialFrame.get(); @@ -162,7 +162,7 @@ TimeAxisViewItem::init (const string& it_name, double spu, Gdk::Color& base_colo frame->property_x1() = (double) 0.0; frame->property_y1() = (double) 1.0; frame->property_x2() = (double) trackview.editor.frame_to_pixel(duration); - frame->property_y2() = (double) trackview.height; + frame->property_y2() = (double) trackview.current_height(); frame->property_outline_what() = 0xF; frame->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_TimeAxisFrame.get(); frame->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TimeAxisFrame.get(); @@ -198,8 +198,8 @@ TimeAxisViewItem::init (const string& it_name, double spu, Gdk::Color& base_colo name_highlight->property_x1() = (double) 1.0; name_highlight->property_x2() = (double) (trackview.editor.frame_to_pixel(item_duration)) - 1; } - name_highlight->property_y1() = (double) (trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE); - name_highlight->property_y2() = (double) (trackview.height - 1); + name_highlight->property_y1() = (double) (trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE); + name_highlight->property_y2() = (double) (trackview.current_height() - 1); name_highlight->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_NameHighlightFill.get(); name_highlight->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_NameHighlightOutline.get(); @@ -212,10 +212,10 @@ TimeAxisViewItem::init (const string& it_name, double spu, Gdk::Color& base_colo if (visibility & ShowNameText) { name_text = new ArdourCanvas::Text (*group); name_text->property_x() = (double) TimeAxisViewItem::NAME_X_OFFSET; - /* trackview.height is the bottom of the trackview. subtract 1 to get back to the bottom of the highlight, + /* trackview.current_height() is the bottom of the trackview. subtract 1 to get back to the bottom of the highlight, then NAME_Y_OFFSET to position the text in the vertical center of the highlight */ - name_text->property_y() = (double) trackview.height - 1.0 - TimeAxisViewItem::NAME_Y_OFFSET; + name_text->property_y() = (double) trackview.current_height() - 1.0 - TimeAxisViewItem::NAME_Y_OFFSET; name_text->property_font_desc() = *NAME_FONT; name_text->property_anchor() = Gtk::ANCHOR_NW; @@ -804,8 +804,13 @@ TimeAxisViewItem::set_frame_color() UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_SelectedFrameBase.get(), &r, &g, &b, &a); frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, a); } else { - UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_FrameBase.get(), &r, &g, &b, &a); - frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, a); + if (_recregion) { + UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_RecordingRect.get(), &r, &g, &b, &a); + frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, a); + } else { + UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_FrameBase.get(), &r, &g, &b, &a); + frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, fill_opacity ? fill_opacity : a); + } } } } @@ -1049,3 +1054,4 @@ TimeAxisViewItem::idle_remove_this_item(TimeAxisViewItem* item, void* src) item = 0; return false; } + diff --git a/gtk2_ardour/time_axis_view_item.h b/gtk2_ardour/time_axis_view_item.h index 18d6638738..02becad3e7 100644 --- a/gtk2_ardour/time_axis_view_item.h +++ b/gtk2_ardour/time_axis_view_item.h @@ -201,8 +201,8 @@ class TimeAxisViewItem : public Selectable */ void set_name_text(const Glib::ustring& new_name) ; - virtual void set_y_position_and_height(double y, double h) ; - + void set_y_position_and_height (double, double); + /** * */ @@ -291,6 +291,7 @@ class TimeAxisViewItem : public Selectable * the destructor, this allows us to capture the source of the deletion * event */ + sigc::signal ItemRemoved ; /** Emitted when the name/Id of this item is changed */ @@ -311,8 +312,6 @@ class TimeAxisViewItem : public Selectable /** Emitted when the mionimum item duration is changed */ sigc::signal MinDurationChanged ; - protected: - enum Visibility { ShowFrame = 0x1, ShowNameHighlight = 0x2, @@ -323,7 +322,7 @@ class TimeAxisViewItem : public Selectable HideFrameTB = 0x40, FullWidthNameHighlight = 0x80 }; - + protected: /** * Constructs a new TimeAxisViewItem. * @@ -336,7 +335,7 @@ class TimeAxisViewItem : public Selectable * @param duration the duration of this item */ TimeAxisViewItem(const std::string & it_name, ArdourCanvas::Group& parent, TimeAxisView& tv, double spu, Gdk::Color& base_color, - nframes_t start, nframes_t duration, Visibility v = Visibility (0)); + nframes_t start, nframes_t duration, bool recording = false, Visibility v = Visibility (0)); TimeAxisViewItem (const TimeAxisViewItem& other); @@ -462,6 +461,8 @@ class TimeAxisViewItem : public Selectable std::map name_text_size_cache; Visibility visibility; + bool _recregion; + }; /* class TimeAxisViewItem */ diff --git a/gtk2_ardour/ui_config.cc b/gtk2_ardour/ui_config.cc index 6ebedaa129..37a0ade3fe 100644 --- a/gtk2_ardour/ui_config.cc +++ b/gtk2_ardour/ui_config.cc @@ -20,6 +20,8 @@ #include #include /* for snprintf, grrr */ +#include + #include #include #include @@ -148,12 +150,10 @@ UIConfiguration::save_state() { XMLTree tree; - try - { + try { sys::create_directories (user_config_directory ()); } - catch (const sys::filesystem_error& ex) - { + catch (const sys::filesystem_error& ex) { error << "Could not create user configuration directory" << endmsg; return -1; } diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc index a52969268a..9008f8b8cd 100644 --- a/gtk2_ardour/utils.cc +++ b/gtk2_ardour/utils.cc @@ -36,6 +36,7 @@ #include #include +#include #include @@ -469,39 +470,10 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) it does allow. */ - int fakekey = GDK_VoidSymbol; - int ret = false; + uint32_t fakekey = ev->keyval; - switch (ev->keyval) { - case GDK_Tab: - case GDK_ISO_Left_Tab: - fakekey = GDK_nabla; - break; - - case GDK_Up: - fakekey = GDK_uparrow; - break; - - case GDK_Down: - fakekey = GDK_downarrow; - break; - - case GDK_Right: - fakekey = GDK_rightarrow; - break; - - case GDK_Left: - fakekey = GDK_leftarrow; - break; - - default: - break; - } - - if (fakekey != GDK_VoidSymbol) { - ret = gtk_accel_groups_activate(G_OBJECT(win), fakekey, GdkModifierType(ev->state)); - - if (ret) { + if (possibly_translate_keyval_to_make_legal_accelerator (fakekey)) { + if (gtk_accel_groups_activate(G_OBJECT(win), fakekey, GdkModifierType(ev->state))) { return true; } @@ -590,18 +562,30 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) Glib::RefPtr get_xpm (std::string name) { - SearchPath spath(ARDOUR::ardour_search_path()); - spath += ARDOUR::system_data_search_path(); + if (!xpm_map[name]) { - spath.add_subdirectory_to_paths("pixmaps"); + SearchPath spath(ARDOUR::ardour_search_path()); + spath += ARDOUR::system_data_search_path(); + + spath.add_subdirectory_to_paths("pixmaps"); + + sys::path data_file_path; + + if (!find_file_in_search_path (spath, name, data_file_path)) { + fatal << string_compose (_("cannot find XPM file for %1"), name) << endmsg; + /*NOTREACHED*/ + } - sys::path data_file_path; + try { + xpm_map[name] = Gdk::Pixbuf::create_from_file (data_file_path.to_string()); + } - if(!find_file_in_search_path (spath, name, data_file_path)) { - fatal << string_compose (_("cannot find XPM file for %1"), name) << endmsg; + catch(const Glib::Error& e) { + warning << "Caught Glib::Error: " << e.what() << endmsg; + } } - return Gdk::Pixbuf::create_from_file (data_file_path.to_string()); + return xpm_map[name]; } Glib::RefPtr @@ -738,3 +722,42 @@ reset_dpi () DPIReset();//Emit Signal } +bool +possibly_translate_keyval_to_make_legal_accelerator (uint32_t& keyval) +{ + int fakekey = GDK_VoidSymbol; + + switch (keyval) { + case GDK_Tab: + case GDK_ISO_Left_Tab: + fakekey = GDK_nabla; + break; + + case GDK_Up: + fakekey = GDK_uparrow; + break; + + case GDK_Down: + fakekey = GDK_downarrow; + break; + + case GDK_Right: + fakekey = GDK_rightarrow; + break; + + case GDK_Left: + fakekey = GDK_leftarrow; + break; + + default: + break; + } + + if (fakekey != GDK_VoidSymbol) { + keyval = fakekey; + return true; + } + + return false; +} + diff --git a/gtk2_ardour/utils.h b/gtk2_ardour/utils.h index 4cf8fc371b..29c6bda403 100644 --- a/gtk2_ardour/utils.h +++ b/gtk2_ardour/utils.h @@ -76,6 +76,7 @@ bool canvas_item_visible (ArdourCanvas::Item* item); void set_color (Gdk::Color&, int); bool key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev); +bool possibly_translate_keyval_to_make_legal_accelerator (uint32_t& keyval); Glib::RefPtr get_xpm (std::string); Glib::RefPtr get_icon (const char*); diff --git a/gtk2_ardour/visual_time_axis.cc b/gtk2_ardour/visual_time_axis.cc index 83b95bb5d2..8a707183cd 100644 --- a/gtk2_ardour/visual_time_axis.cc +++ b/gtk2_ardour/visual_time_axis.cc @@ -101,7 +101,7 @@ VisualTimeAxis::VisualTimeAxis(const string & name, PublicEditor& ed, ARDOUR::Se hide_button.unset_flags(Gtk::CAN_FOCUS) ; visual_button.unset_flags(Gtk::CAN_FOCUS) ; - set_height(Normal) ; + set_height (hNormal) ; } /** @@ -144,39 +144,25 @@ VisualTimeAxis::name() const /** * Sets the height of this TrackView to one of the defined TrackHeghts * - * @param h the TrackHeight value to set + * @param h */ void -VisualTimeAxis::set_height(TrackHeight h) +VisualTimeAxis::set_height(uint32_t h) { - TimeAxisView::set_height(h) ; + TimeAxisView::set_height(h); - switch (height) - { - case Largest: - case Large: - case Larger: - case Normal: - { - hide_name_label (); - show_name_entry (); - other_button_hbox.show_all() ; - break; - } - case Smaller: - { - hide_name_label (); - show_name_entry (); - other_button_hbox.hide_all() ; - break; - } - case Small: - { - hide_name_entry (); - show_name_label (); - other_button_hbox.hide_all() ; - } - break; + if (h >= hNormal) { + hide_name_label (); + show_name_entry (); + other_button_hbox.show_all() ; + } else if (h >= hSmaller) { + hide_name_label (); + show_name_entry (); + other_button_hbox.hide_all() ; + } else if (h >= hSmall) { + hide_name_entry (); + show_name_label (); + other_button_hbox.hide_all() ; } } diff --git a/gtk2_ardour/visual_time_axis.h b/gtk2_ardour/visual_time_axis.h index 6d1396bc54..a0dfe654de 100644 --- a/gtk2_ardour/visual_time_axis.h +++ b/gtk2_ardour/visual_time_axis.h @@ -93,9 +93,9 @@ class VisualTimeAxis : public TimeAxisView /** * Sets the height of this TrackView to one of the defined TrackHeghts * - * @param h the TrackHeight value to set + * @param h the number of pixels to set the height to */ - virtual void set_height (TrackHeight h); + virtual void set_height (uint32_t); //---------------------------------------------------------------------------------------// // Selection Methods diff --git a/libs/appleutility/CAAudioUnit.cpp b/libs/appleutility/CAAudioUnit.cpp index 9244877d29..aaf57f233d 100644 --- a/libs/appleutility/CAAudioUnit.cpp +++ b/libs/appleutility/CAAudioUnit.cpp @@ -328,6 +328,46 @@ bool CAAudioUnit::CanDo ( int inChannelsIn, return ValidateChannelPair (inChannelsIn, inChannelsOut, info.mChanInfo, (dataSize / sizeof (AUChannelInfo))); } +int CAAudioUnit::GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt) +{ + // this is the default assumption of an audio effect unit + Boolean* isWritable = 0; + UInt32 dataSize = 0; + // lets see if the unit has any channel restrictions + OSStatus result = AudioUnitGetPropertyInfo (AU(), + kAudioUnitProperty_SupportedNumChannels, + kAudioUnitScope_Global, 0, + &dataSize, isWritable); //don't care if this is writable + + // if this property is NOT implemented an FX unit + // is expected to deal with same channel valance in and out + + if (result) + { + if (Comp().Desc().IsEffect()) + { + return 1; + } + else + { + // the au should either really tell us about this + // or we will assume the worst + return -1; + } + } + + *chaninfo = (AUChannelInfo*) malloc (dataSize); + cnt = dataSize / sizeof (AUChannelInfo); + + result = GetProperty (kAudioUnitProperty_SupportedNumChannels, + kAudioUnitScope_Global, 0, + *chaninfo, &dataSize); + + if (result) { return -1; } + return 0; +} + + bool CAAudioUnit::ValidateChannelPair (int inChannelsIn, int inChannelsOut, const AUChannelInfo * info, diff --git a/libs/appleutility/CAAudioUnit.h b/libs/appleutility/CAAudioUnit.h index 6bc31bf30b..810b81be2f 100644 --- a/libs/appleutility/CAAudioUnit.h +++ b/libs/appleutility/CAAudioUnit.h @@ -218,6 +218,7 @@ public: bool HasChannelLayouts (AudioUnitScope inScope, AudioUnitElement inEl) const; + int GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt); bool GetChannelLayouts (AudioUnitScope inScope, AudioUnitElement inEl, ChannelTagVector &outChannelVector) const; diff --git a/libs/appleutility/SConscript b/libs/appleutility/SConscript index bddca04032..c4f65ec81e 100644 --- a/libs/appleutility/SConscript +++ b/libs/appleutility/SConscript @@ -7,7 +7,7 @@ import glob appleutility_files = glob.glob('*.cpp') Import('env install_prefix') -appleutility = env.Copy() +appleutility = env.Clone() appleutility.Append(LINKFLAGS='-framework AudioToolbox') appleutility.Append(LINKFLAGS='-framework AudioUnit') diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index 44f4718384..ca6fc0553e 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -6,7 +6,7 @@ import glob Import('env final_prefix install_prefix final_config_prefix libraries i18n') -ardour = env.Copy() +ardour = env.Clone() # # this defines the version number of libardour @@ -95,6 +95,7 @@ mtc_slave.cc midi_clock_slave.cc named_selection.cc note.cc +onset_detector.cc panner.cc parameter.cc pcm_utils.cc @@ -357,7 +358,7 @@ env['BUILDERS']['SharedAsmObject'] = Builder (action = '$CXX -c -fPIC $SOURCE -o always_sse_objects = [] -sse_env = ardour.Copy() +sse_env = ardour.Clone() sse_env.Append (CXXFLAGS="-msse") if env['FPU_OPTIMIZATION']: diff --git a/libs/ardour/ardour/ardour.h b/libs/ardour/ardour/ardour.h index fecd0fcf4e..fd873f9a6f 100644 --- a/libs/ardour/ardour/ardour.h +++ b/libs/ardour/ardour/ardour.h @@ -32,6 +32,8 @@ #include #include +// #include need this to inline jack_get_microseconds + namespace MIDI { class MachineControl; class Port; @@ -57,7 +59,12 @@ namespace ARDOUR { const layer_t max_layer = UCHAR_MAX; microseconds_t get_microseconds (); - +/* { + JACK has exported this functionality for a long time now + but inlining this causes problems + return (microseconds_t) jack_get_time(); + } +*/ Change new_change (); extern Change StartChanged; diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h index 3546545329..fe7dcb58ff 100644 --- a/libs/ardour/ardour/audio_track.h +++ b/libs/ardour/ardour/audio_track.h @@ -58,8 +58,8 @@ class AudioTrack : public Track void freeze (InterThreadInfo&); void unfreeze (); - void bounce (InterThreadInfo&); - void bounce_range (nframes_t start, nframes_t end, InterThreadInfo&); + boost::shared_ptr bounce (InterThreadInfo&); + boost::shared_ptr bounce_range (nframes_t start, nframes_t end, InterThreadInfo&); int set_state(const XMLNode& node); diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h index dc9a52d5d3..497954092f 100644 --- a/libs/ardour/ardour/audio_unit.h +++ b/libs/ardour/ardour/audio_unit.h @@ -100,11 +100,12 @@ class AUPlugin : public ARDOUR::Plugin bool has_editor () const; - bool fixed_io() const { return false; } - int32_t can_support_input_configuration (int32_t in); - int32_t compute_output_streams (int32_t nplugins); - uint32_t output_streams() const; - uint32_t input_streams() const; + bool reconfigurable_io() const { return true; } + bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; + int32_t count_for_configuration (const ChanCount& in, ChanCount out) const; + bool configure_io (ChanCount in, ChanCount& out); + ChanCount output_streams() const; + ChanCount input_streams() const; boost::shared_ptr get_au () { return unit; } boost::shared_ptr get_comp () const { return comp; } @@ -118,18 +119,19 @@ class AUPlugin : public ARDOUR::Plugin boost::shared_ptr comp; boost::shared_ptr unit; - AudioStreamBasicDescription streamFormat; bool initialized; - int format_set; + int32_t input_channels; + int32_t output_channels; + std::vector > io_configs; AudioBufferList* buffers; UInt32 global_elements; UInt32 output_elements; UInt32 input_elements; - int set_output_format (); - int set_input_format (); - int set_stream_format (int scope, uint32_t cnt); + int set_output_format (AudioStreamBasicDescription&); + int set_input_format (AudioStreamBasicDescription&); + int set_stream_format (int scope, uint32_t cnt, AudioStreamBasicDescription&); int _set_block_size (nframes_t nframes); void discover_parameters (); @@ -142,10 +144,15 @@ class AUPlugin : public ARDOUR::Plugin std::vector descriptors; void init (); + }; typedef boost::shared_ptr AUPluginPtr; +struct AUPluginCachedInfo { + std::vector > io_configs; +}; + class AUPluginInfo : public PluginInfo { public: AUPluginInfo (boost::shared_ptr); @@ -153,16 +160,29 @@ class AUPluginInfo : public PluginInfo { PluginPtr load (Session& session); + AUPluginCachedInfo cache; + static PluginInfoList discover (); static void get_names (CAComponentDescription&, std::string& name, Glib::ustring& maker); static std::string stringify_descriptor (const CAComponentDescription&); + static int load_cached_info (); + private: boost::shared_ptr descriptor; + UInt32 version; static void discover_music (PluginInfoList&); static void discover_fx (PluginInfoList&); static void discover_by_description (PluginInfoList&, CAComponentDescription&); + static Glib::ustring au_cache_path (); + + typedef std::map CachedInfoMap; + static CachedInfoMap cached_info; + + static bool cached_io_configuration (const std::string&, UInt32, CAComponent&, AUPluginCachedInfo&, const std::string& name); + static void add_cached_info (const std::string&, AUPluginCachedInfo&); + static void save_cached_info (); }; typedef boost::shared_ptr AUPluginInfoPtr; diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index e1d5e50cc2..89abc6669a 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -130,13 +130,13 @@ class AudioEngine : public sigc::trackable const char ** get_ports (const std::string& port_name_pattern, const std::string& type_name_pattern, uint32_t flags); - uint32_t n_physical_outputs () const; - uint32_t n_physical_inputs () const; - bool can_request_hardware_monitoring (); - void get_physical_outputs (std::vector&); - void get_physical_inputs (std::vector&); + uint32_t n_physical_outputs (DataType type) const; + uint32_t n_physical_inputs (DataType type) const; + + void get_physical_outputs (DataType type, std::vector&); + void get_physical_inputs (DataType type, std::vector&); std::string get_nth_physical_output (DataType type, uint32_t n) { return get_nth_physical (type, n, JackPortIsInput); @@ -152,7 +152,7 @@ class AudioEngine : public sigc::trackable /** Caller may not delete the object pointed to by the return value */ - Port *get_port_by_name (const std::string& name, bool keep = true) const; + Port *get_port_by_name (const std::string& name, bool keep = true); enum TransportState { TransportStopped = JackTransportStopped, @@ -204,27 +204,28 @@ class AudioEngine : public sigc::trackable std::string make_port_name_non_relative (std::string); private: - ARDOUR::Session *session; - jack_client_t *_jack; - std::string jack_client_name; - mutable Glib::Mutex _process_lock; - Glib::Cond session_removed; - bool session_remove_pending; - bool _running; - bool _has_run; - nframes_t _buffer_size; - nframes_t _frame_rate; + ARDOUR::Session* session; + jack_client_t* _jack; + std::string jack_client_name; + Glib::Mutex _process_lock; + Glib::Cond session_removed; + bool session_remove_pending; + bool _running; + bool _has_run; + nframes_t _buffer_size; + nframes_t _frame_rate; /// number of frames between each check for changes in monitor input - nframes_t monitor_check_interval; + nframes_t monitor_check_interval; /// time of the last monitor check in frames - nframes_t last_monitor_check; + nframes_t last_monitor_check; /// the number of frames processed since start() was called - nframes_t _processed_frames; - bool _freewheeling; - bool _freewheel_thread_registered; - sigc::slot freewheel_action; - bool reconnect_on_halt; - int _usecs_per_cycle; + nframes_t _processed_frames; + bool _freewheeling; + bool _freewheel_pending; + bool _freewheel_thread_registered; + sigc::slot freewheel_action; + bool reconnect_on_halt; + int _usecs_per_cycle; SerializedRCUManager ports; diff --git a/libs/ardour/ardour/auto_bundle.h b/libs/ardour/ardour/auto_bundle.h index 685a083e8d..9df26a449b 100644 --- a/libs/ardour/ardour/auto_bundle.h +++ b/libs/ardour/ardour/auto_bundle.h @@ -32,7 +32,7 @@ class AutoBundle : public Bundle { AutoBundle (bool i = true); AutoBundle (std::string const &, bool i = true); - uint32_t nchannels () const; + ChanCount nchannels () const; const PortList& channel_ports (uint32_t) const; void set_channels (uint32_t); diff --git a/libs/ardour/ardour/buffer.h b/libs/ardour/ardour/buffer.h index fd94360226..72df6c7fd6 100644 --- a/libs/ardour/ardour/buffer.h +++ b/libs/ardour/ardour/buffer.h @@ -21,8 +21,10 @@ #include #include +#include #include #include + #include #include #include diff --git a/libs/ardour/ardour/bundle.h b/libs/ardour/ardour/bundle.h index ba92063b30..46ba13152e 100644 --- a/libs/ardour/ardour/bundle.h +++ b/libs/ardour/ardour/bundle.h @@ -22,7 +22,9 @@ #include #include + #include "ardour/data_type.h" +#include "ardour/chan_count.h" namespace ARDOUR { @@ -37,12 +39,13 @@ class Bundle { Bundle () : _type (DataType::AUDIO) {} Bundle (bool i) : _type (DataType::AUDIO), _ports_are_inputs (i) {} Bundle (std::string const & n, bool i = true) : _name (n), _type (DataType::AUDIO), _ports_are_inputs (i) {} + virtual ~Bundle() {} /** * @return Number of channels that this Bundle has. */ - virtual uint32_t nchannels () const = 0; + virtual ChanCount nchannels () const = 0; virtual const PortList& channel_ports (uint32_t) const = 0; void set_name (std::string const & n) { diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h index 7a7a2ce419..1f455dc308 100644 --- a/libs/ardour/ardour/configuration_vars.h +++ b/libs/ardour/ardour/configuration_vars.h @@ -124,6 +124,7 @@ CONFIG_VARIABLE (bool, quieten_at_speed, "quieten-at-speed", true) CONFIG_VARIABLE (bool, primary_clock_delta_edit_cursor, "primary-clock-delta-edit-cursor", false) CONFIG_VARIABLE (bool, secondary_clock_delta_edit_cursor, "secondary-clock-delta-edit-cursor", false) CONFIG_VARIABLE (bool, show_track_meters, "show-track-meters", true) +CONFIG_VARIABLE (bool, locate_while_waiting_for_sync, "locate-while-waiting-for-sync", false) /* timecode and sync */ @@ -159,6 +160,7 @@ CONFIG_VARIABLE (bool, only_copy_imported_files, "only-copy-imported-files", tru CONFIG_VARIABLE (std::string, keyboard_layout, "keyboard-layout", "ansi") CONFIG_VARIABLE (std::string, default_bindings, "default-bindings", "ardour") CONFIG_VARIABLE (bool, default_narrow_ms, "default-narrow_ms", false) +CONFIG_VARIABLE (bool, name_new_markers, "name-new-markers", false) CONFIG_VARIABLE (bool, rubberbanding_snaps_to_grid, "rubberbanding-snaps-to-grid", false) CONFIG_VARIABLE (long, font_scale, "font-scale", 102400) diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index 83b6378dae..b44e131d8a 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -368,6 +368,7 @@ class IO : public Automatable, public Latent int create_ports (const XMLNode&); int make_connections (const XMLNode&); + boost::shared_ptr find_possible_bundle (const string &desired_name, const string &default_name, const string &connection_type_name); void setup_peak_meters (); void meter (); diff --git a/libs/ardour/ardour/meter.h b/libs/ardour/ardour/meter.h index e19c0a51ca..112f306ccb 100644 --- a/libs/ardour/ardour/meter.h +++ b/libs/ardour/ardour/meter.h @@ -40,6 +40,7 @@ public: void reset (); void reset_max (); + bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const { return true; } bool configure_io (ChanCount in, ChanCount out); /** Compute peaks */ diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 500502ac4b..6e4677df22 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -65,8 +65,8 @@ public: void freeze (InterThreadInfo&); void unfreeze (); - void bounce (InterThreadInfo&); - void bounce_range (nframes_t start, nframes_t end, InterThreadInfo&); + boost::shared_ptr bounce (InterThreadInfo&); + boost::shared_ptr bounce_range (nframes_t start, nframes_t end, InterThreadInfo&); int set_state(const XMLNode& node); diff --git a/libs/ardour/ardour/onset_detector.h b/libs/ardour/ardour/onset_detector.h new file mode 100644 index 0000000000..9243653d94 --- /dev/null +++ b/libs/ardour/ardour/onset_detector.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2008 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_onset_detector_h__ +#define __ardour_onset_detector_h__ + +#include + +namespace ARDOUR { + +class AudioSource; +class Session; + +class OnsetDetector : public AudioAnalyser +{ + + public: + OnsetDetector (float sample_rate); + ~OnsetDetector(); + + static std::string operational_identifier(); + + void set_silence_threshold (float); + void set_peak_threshold (float); + void set_function (int); + + int run (const std::string& path, Readable*, uint32_t channel, AnalysisFeatureList& results); + + static void cleanup_onsets (AnalysisFeatureList&, float sr, float gap_msecs); + + protected: + AnalysisFeatureList* current_results; + int use_features (Vamp::Plugin::FeatureSet&, std::ostream*); + + static std::string _op_id; +}; + +} /* namespace */ + +#endif /* __ardour_audioanalyser_h__ */ diff --git a/libs/ardour/ardour/osc.h b/libs/ardour/ardour/osc.h index 3f1ce03445..d7c2f4bd85 100644 --- a/libs/ardour/ardour/osc.h +++ b/libs/ardour/ardour/osc.h @@ -54,12 +54,13 @@ class OSC : public BasicUI, public sigc::trackable lo_server _osc_server; lo_server _osc_unix_server; std::string _osc_unix_socket_path; - std::string _osc_url_file; + std::string _osc_url_file; pthread_t _osc_thread; int _request_pipe[2]; static void * _osc_receiver(void * arg); void osc_receiver(); + void send(); // This should accept an OSC payload bool init_osc_thread (); void terminate_osc_thread (); @@ -69,6 +70,11 @@ class OSC : public BasicUI, public sigc::trackable void session_going_away (); + // Handlers for "Application Hook" signals + void session_loaded( ARDOUR::Session& ); + void session_exported( std::string, std::string ); + // end "Application Hook" handles + std::string get_server_url (); std::string get_unix_server_url (); @@ -101,18 +107,19 @@ class OSC : public BasicUI, public sigc::trackable PATH_CALLBACK(rec_enable_toggle); PATH_CALLBACK(toggle_all_rec_enables); -#define PATH_CALLBACK1(name,type) \ +#define PATH_CALLBACK1(name,type,optional) \ static int _ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { \ return static_cast(user_data)->cb_ ## name (path, types, argv, argc, data); \ } \ int cb_ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data) { \ - if (argc > 0) { \ - name (argv[0]->type); \ - }\ - return 0; \ + if (argc > 0) { \ + name (optional argv[0]->type); \ + } \ + return 0; \ } - PATH_CALLBACK1(set_transport_speed,f); + PATH_CALLBACK1(set_transport_speed,f,); + PATH_CALLBACK1(access_action,s,&); }; } diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h index 73f89f1a91..fec044e885 100644 --- a/libs/ardour/ardour/plugin.h +++ b/libs/ardour/ardour/plugin.h @@ -145,6 +145,33 @@ class Plugin : public PBD::StatefulDestructible, public Latent virtual bool has_editor() const = 0; + sigc::signal ParameterChanged; + + /* NOTE: this block of virtual methods looks like the interface + to a Processor, but Plugin does not inherit from Processor. + It is therefore not required that these precisely match + the interface, but it is likely that they will evolve together. + */ + + /* this returns true if the plugin can change its inputs or outputs on demand. + LADSPA, LV2 and VST plugins cannot do this. AudioUnits can. + */ + + virtual bool reconfigurable_io() const { return false; } + + /* this is only called if reconfigurable_io() returns true */ + virtual bool configure_io (ChanCount in, ChanCount out) { return true; } + + /* specific types of plugins can overload this. As of September 2008, only + AUPlugin does this. + */ + virtual bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const { return false; } + virtual ChanCount output_streams() const; + virtual ChanCount input_streams() const; + + PBD::Controllable *get_nth_control (uint32_t, bool do_not_create = false); + void make_nth_control (uint32_t, const XMLNode&); + PluginInfoPtr get_info() { return _info; } void set_info (const PluginInfoPtr inf) { _info = inf; } diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h index 42c53c487c..c19d113256 100644 --- a/libs/ardour/ardour/plugin_insert.h +++ b/libs/ardour/ardour/plugin_insert.h @@ -69,13 +69,12 @@ class PluginInsert : public Processor bool set_count (uint32_t num); uint32_t get_count () const { return _plugins.size(); } - virtual bool can_support_input_configuration (ChanCount in) const; - virtual ChanCount output_for_input_configuration (ChanCount in) const; - virtual bool configure_io (ChanCount in, ChanCount out); + bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; + bool configure_io (ChanCount in, ChanCount out); bool is_generator() const; - void set_parameter (Parameter param, float val); + void set_parameter (Parameter param, float val); float get_parameter (Parameter param); float default_parameter_value (Parameter param); diff --git a/libs/ardour/ardour/plugin_manager.h b/libs/ardour/ardour/plugin_manager.h index 892c8bd75a..858decd0e5 100644 --- a/libs/ardour/ardour/plugin_manager.h +++ b/libs/ardour/ardour/plugin_manager.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -54,7 +55,31 @@ class PluginManager { static PluginManager* the_manager() { return _manager; } + void load_favorites (); + void save_favorites (); + void add_favorite (ARDOUR::PluginType type, std::string unique_id); + void remove_favorite (ARDOUR::PluginType type, std::string unique_id); + bool is_a_favorite_plugin (const PluginInfoPtr&); + private: + struct FavoritePlugin { + ARDOUR::PluginType type; + std::string unique_id; + + FavoritePlugin (ARDOUR::PluginType t, std::string id) + : type (t), unique_id (id) {} + + bool operator==(const FavoritePlugin& other) const { + return other.type == type && other.unique_id == unique_id; + } + + bool operator<(const FavoritePlugin& other) const { + return other.type < type || other.unique_id < unique_id; + } + }; + typedef std::set FavoritePluginList; + FavoritePluginList favorites; + ARDOUR::PluginInfoList _vst_plugin_info; ARDOUR::PluginInfoList _ladspa_plugin_info; ARDOUR::PluginInfoList _lv2_plugin_info; diff --git a/libs/ardour/ardour/port.h b/libs/ardour/ardour/port.h index 93c34da16d..084022541d 100644 --- a/libs/ardour/ardour/port.h +++ b/libs/ardour/ardour/port.h @@ -23,7 +23,7 @@ #include #include #include - +#include #include #include #include diff --git a/libs/ardour/ardour/port_insert.h b/libs/ardour/ardour/port_insert.h index 1743040bf5..72f02ff9c7 100644 --- a/libs/ardour/ardour/port_insert.h +++ b/libs/ardour/ardour/port_insert.h @@ -58,9 +58,8 @@ class PortInsert : public IOProcessor ChanCount output_streams() const; ChanCount input_streams() const; - virtual bool can_support_input_configuration (ChanCount in) const; - virtual ChanCount output_for_input_configuration (ChanCount in) const; - virtual bool configure_io (ChanCount in, ChanCount out); + bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const { return true; } + bool configure_io (ChanCount in, ChanCount out); uint32_t bit_slot() const { return bitslot; } diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h index d3e95e8ebf..8c4ac8dfe5 100644 --- a/libs/ardour/ardour/processor.h +++ b/libs/ardour/ardour/processor.h @@ -80,7 +80,7 @@ class Processor : public Automatable, public Latent virtual void activate () { _active = true; ActiveChanged.emit(); } virtual void deactivate () { _active = false; ActiveChanged.emit(); } - virtual bool configure_io (ChanCount in, ChanCount out) { _configured_input = in; return (_configured = true); } + virtual bool configure_io (ChanCount in, ChanCount out); /* Derived classes should override these, or processor appears as an in-place pass-through */ @@ -91,8 +91,7 @@ class Processor : public Automatable, public Latent * and write to their output parameter */ virtual bool is_out_of_place () const { return false; } - virtual bool can_support_input_configuration (ChanCount in) const { return true; } - virtual ChanCount output_for_input_configuration (ChanCount in) const { return in; } + virtual bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const = 0; virtual ChanCount output_streams() const { return _configured_input; } virtual ChanCount input_streams () const { return _configured_input; } diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index c7c0b77102..fb98cb57a7 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -359,8 +359,8 @@ class Route : public IO void input_change_handler (IOChange, void *src); void output_change_handler (IOChange, void *src); - int reset_plugin_counts (ProcessorStreams*); /* locked */ - int _reset_plugin_counts (ProcessorStreams*); /* unlocked */ + int reset_processor_counts (ProcessorStreams*); /* locked */ + int _reset_processor_counts (ProcessorStreams*); /* unlocked */ /* processor I/O channels and plugin count handling */ @@ -372,8 +372,8 @@ class Route : public IO ProcessorCount (boost::shared_ptr ins) : processor(ins) {} }; - int32_t apply_some_plugin_counts (std::list& iclist); - bool check_some_plugin_counts (std::list& iclist, ChanCount required_inputs, ProcessorStreams* err_streams); + int32_t apply_some_processor_counts (std::list& iclist); + bool check_some_processor_counts (std::list& iclist, ChanCount required_inputs, ProcessorStreams* err_streams); void set_deferred_state (); void add_processor_from_xml (const XMLNode&); diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h index 1ee8bbceca..d5078bd7df 100644 --- a/libs/ardour/ardour/send.h +++ b/libs/ardour/ardour/send.h @@ -57,16 +57,17 @@ class Send : public IOProcessor int set_state(const XMLNode& node); uint32_t pans_required() const { return _configured_input.n_audio(); } + void expect_inputs (const ChanCount&); - virtual bool can_support_input_configuration (ChanCount in) const; - virtual ChanCount output_for_input_configuration (ChanCount in) const; - virtual bool configure_io (ChanCount in, ChanCount out); + bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; + bool configure_io (ChanCount in, ChanCount out); static uint32_t how_many_sends(); private: bool _metering; - uint32_t bitslot; + ChanCount expected_inputs; + uint32_t bitslot; }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 00cbc9922e..08315c3010 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -434,15 +434,18 @@ class Session : public PBD::StatefulDestructible nframes_t worst_input_latency () const { return _worst_input_latency; } nframes_t worst_track_latency () const { return _worst_track_latency; } - int save_state (string snapshot_name, bool pending = false); - int restore_state (string snapshot_name); - int save_template (string template_name); - int save_history (string snapshot_name = ""); - int restore_history (string snapshot_name); - void remove_state (string snapshot_name); - void rename_state (string old_name, string new_name); + int save_state (std::string snapshot_name, bool pending = false); + int restore_state (std::string snapshot_name); + int save_template (std::string template_name); + int save_history (std::string snapshot_name = ""); + int restore_history (std::string snapshot_name); + void remove_state (std::string snapshot_name); + void rename_state (std::string old_name, std::string new_name); void remove_pending_capture_state (); + static int rename_template (std::string old_name, std::string new_name); + static int delete_template (std::string name); + sigc::signal StateSaved; sigc::signal StateReady; @@ -579,7 +582,7 @@ class Session : public PBD::StatefulDestructible sigc::signal >& > RegionsAdded; sigc::signal > RegionRemoved; - int region_name (string& result, string base = string(""), bool newlevel = false) const; + int region_name (string& result, string base = string(""), bool newlevel = false); string new_region_name (string); string path_from_region_name (DataType type, string name, string identifier); @@ -616,9 +619,11 @@ class Session : public PBD::StatefulDestructible SlaveSource post_export_slave; nframes_t post_export_position; - int start_export (ARDOUR::ExportSpecification&); - int stop_export (ARDOUR::ExportSpecification&); - void finalize_audio_export (); + int pre_export (); + int start_export (ARDOUR::ExportSpecification&); + int stop_export (ARDOUR::ExportSpecification&); + void finalize_export (); + static sigc::signal Exported; void add_source (boost::shared_ptr); void remove_source (boost::weak_ptr); @@ -706,9 +711,8 @@ class Session : public PBD::StatefulDestructible /* flattening stuff */ - int write_one_audio_track (AudioTrack&, nframes_t start, nframes_t cnt, bool overwrite, - vector >&, InterThreadInfo& wot); - + boost::shared_ptr write_one_track (AudioTrack&, nframes_t start, nframes_t end, bool overwrite, vector >&, + InterThreadInfo& wot); int freeze (InterThreadInfo&); /* session-wide solo/mute/rec-enable */ @@ -910,7 +914,7 @@ class Session : public PBD::StatefulDestructible void reset_playback_load_min (); void reset_capture_load_min (); - float read_data_rate () const; + float read_data_rate () const; // in usec float write_data_rate () const; /* ranges */ @@ -1072,6 +1076,7 @@ class Session : public PBD::StatefulDestructible void set_slave_source (SlaveSource); bool _exporting; + int prepare_to_export (ARDOUR::ExportSpecification&); void prepare_diskstreams (); @@ -1393,6 +1398,7 @@ class Session : public PBD::StatefulDestructible void set_play_loop (bool yn); void overwrite_some_buffers (Diskstream*); void flush_all_inserts (); + int micro_locate (nframes_t distance); void locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false); void start_locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false); void force_locate (nframes_t frame, bool with_roll = false); @@ -1457,6 +1463,9 @@ class Session : public PBD::StatefulDestructible /* REGION MANAGEMENT */ + std::map region_name_map; + void update_region_name_map (boost::shared_ptr); + mutable Glib::Mutex region_lock; typedef map > RegionList; RegionList regions; diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index 4d5545c0dc..fedd83ba68 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -76,8 +76,8 @@ class Track : public Route virtual void freeze (InterThreadInfo&) = 0; virtual void unfreeze () = 0; - virtual void bounce (InterThreadInfo&) = 0; - virtual void bounce_range (nframes_t start, nframes_t end, InterThreadInfo&) = 0; + virtual boost::shared_ptr bounce (InterThreadInfo&) = 0; + virtual boost::shared_ptr bounce_range (nframes_t start, nframes_t end, InterThreadInfo&) = 0; XMLNode& get_state(); XMLNode& get_template(); diff --git a/libs/ardour/ardour/user_bundle.h b/libs/ardour/ardour/user_bundle.h index 954e93d5d1..c33ddeaed9 100644 --- a/libs/ardour/ardour/user_bundle.h +++ b/libs/ardour/ardour/user_bundle.h @@ -35,7 +35,7 @@ class UserBundle : public Bundle, public PBD::Stateful { UserBundle (std::string const &); UserBundle (XMLNode const &, bool); - uint32_t nchannels () const; + ChanCount nchannels () const; const ARDOUR::PortList& channel_ports (uint32_t) const; void add_channel (); diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 091e1df30f..2953c9e074 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -399,7 +399,7 @@ AudioDiskstream::check_record_status (nframes_t transport_frame, nframes_t nfram /* if per-track or global rec-enable turned on while the other was already on, we've started recording */ if (((change & track_rec_enabled) && record_enabled() && (!(change & global_rec_enabled) && can_record)) || - (((change & global_rec_enabled) && can_record && (!(change & track_rec_enabled) && record_enabled())))) { + ((change & global_rec_enabled) && can_record && (!(change & track_rec_enabled) && record_enabled()))) { /* starting to record: compute first+last frames */ @@ -524,7 +524,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_ commit_should_unlock = false; - if (!_io->active()) { + if (!_io || !_io->active()) { _processed = true; return 0; } @@ -835,7 +835,7 @@ AudioDiskstream::commit (nframes_t nframes) { bool need_butler = false; - if (!_io->active()) { + if (!_io || !_io->active()) { return false; } diff --git a/libs/ardour/audio_library.cc b/libs/ardour/audio_library.cc index a35846ab29..cd473d933f 100644 --- a/libs/ardour/audio_library.cc +++ b/libs/ardour/audio_library.cc @@ -22,6 +22,7 @@ #include #include +#include #include @@ -52,6 +53,7 @@ AudioLibrary::AudioLibrary () // workaround for possible bug in raptor that crashes when saving to a // non-existant file. + touch_file(sfdb_file_path.to_string()); lrdf_read_file(src.c_str()); diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 53f918ec4e..cd05e5fc86 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -743,21 +743,18 @@ AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes return 0; } -void +boost::shared_ptr AudioTrack::bounce (InterThreadInfo& itt) { vector > srcs; - _session.write_one_audio_track (*this, 0, _session.current_end_frame(), false, srcs, itt); - itt.done = true; + return _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), false, srcs, itt); } - -void +boost::shared_ptr AudioTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt) { vector > srcs; - _session.write_one_audio_track (*this, start, end, false, srcs, itt); - itt.done = true; + return _session.write_one_track (*this, start, end, false, srcs, itt); } void @@ -798,7 +795,9 @@ AudioTrack::freeze (InterThreadInfo& itt) return; } - if (_session.write_one_audio_track (*this, _session.current_start_frame(), _session.current_end_frame(), true, srcs, itt)) { + boost::shared_ptr res; + + if ((res = _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), true, srcs, itt)) == 0) { return; } diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc index b941bc10bb..4862ddcd12 100644 --- a/libs/ardour/audio_unit.cc +++ b/libs/ardour/audio_unit.cc @@ -24,7 +24,10 @@ #include #include +#include +#include +#include #include #include #include @@ -43,6 +46,8 @@ using namespace std; using namespace PBD; using namespace ARDOUR; +AUPluginInfo::CachedInfoMap AUPluginInfo::cached_info; + static OSStatus _render_callback(void *userData, AudioUnitRenderActionFlags *ioActionFlags, @@ -120,28 +125,12 @@ AUPlugin::init () unit->GetElementCount (kAudioUnitScope_Input, input_elements); unit->GetElementCount (kAudioUnitScope_Output, output_elements); - // set up the basic stream format. these fields do not change - - streamFormat.mSampleRate = _session.frame_rate(); - streamFormat.mFormatID = kAudioFormatLinearPCM; - streamFormat.mFormatFlags = kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked|kAudioFormatFlagIsNonInterleaved; + /* these keep track of *configured* channel set up, + not potential set ups. + */ -#ifdef __LITTLE_ENDIAN__ - /* relax */ -#else - streamFormat.mFormatFlags |= kAudioFormatFlagIsBigEndian; -#endif - - streamFormat.mBitsPerChannel = 32; - streamFormat.mFramesPerPacket = 1; - - // subject to later modification as we discover channel counts - - streamFormat.mBytesPerPacket = 4; - streamFormat.mBytesPerFrame = 4; - streamFormat.mChannelsPerFrame = 1; - - format_set = 0; + input_channels = -1; + output_channels = -1; if (_set_block_size (_session.get_block_size())) { error << _("AUPlugin: cannot set processing block size") << endmsg; @@ -396,42 +385,233 @@ AUPlugin::_set_block_size (nframes_t nframes) return 0; } -int32_t -AUPlugin::can_support_input_configuration (int32_t in) -{ - streamFormat.mChannelsPerFrame = in; +int32_t +AUPlugin::configure_io (ChanCount in, ChanCount out) +{ + AudioStreamBasicDescription streamFormat; + + streamFormat.mSampleRate = _session.frame_rate(); + streamFormat.mFormatID = kAudioFormatLinearPCM; + streamFormat.mFormatFlags = kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked|kAudioFormatFlagIsNonInterleaved; + +#ifdef __LITTLE_ENDIAN__ + /* relax */ +#else + streamFormat.mFormatFlags |= kAudioFormatFlagIsBigEndian; +#endif + + streamFormat.mBitsPerChannel = 32; + streamFormat.mFramesPerPacket = 1; + /* apple says that for non-interleaved data, these values always refer to a single channel. */ streamFormat.mBytesPerPacket = 4; streamFormat.mBytesPerFrame = 4; - if (set_input_format () == 0) { - return 1; - } else { + streamFormat.mChannelsPerFrame = in.n_audio(); + + if (set_input_format (streamFormat) != 0) { return -1; } + + streamFormat.mChannelsPerFrame = out.n_audio(); + + if (set_output_format (streamFormat) != 0) { + return -1; + } + + return Plugin::configure_io (in, out); } -int -AUPlugin::set_input_format () +bool +AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out) { - return set_stream_format (kAudioUnitScope_Input, input_elements); + int32_t ret = count_for_configuration (in, out); + return ret >= 0; } -int -AUPlugin::set_output_format () +int32_t +AUPlugin::count_for_configuration(ChanCount cin, ChanCount& out) const { - return set_stream_format (kAudioUnitScope_Output, output_elements); + // XXX as of May 13th 2008, AU plugin support returns a count of either 1 or -1. We never + // attempt to multiply-instantiate plugins to meet io configurations. + + int32_t plugcnt = -1; + AUPluginInfoPtr pinfo = boost::dynamic_pointer_cast(get_info()); + int32_t in = cin.n_audio(); /* XXX handle MIDI one day ??? */ + + vector >& io_configs = pinfo->cache.io_configs; + + for (vector >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) { + + int32_t possible_in = i->first; + int32_t possible_out = i->second; + + if (possible_out == 0) { + warning << string_compose (_("AU %1 has zero outputs - configuration ignored"), name()) << endmsg; + continue; + } + + if (possible_in == 0) { + + /* instrument plugin, always legal but throws away inputs ... + */ + + if (possible_out == -1) { + /* out much match in (UNLIKELY!!) */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out == -2) { + /* any configuration possible, pick matching */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out.set (DataType::AUDIO, -possible_out); + plugcnt = 1; + } else { + /* exact number of outputs */ + out.set (DataType::AUDIO, possible_out); + plugcnt = 1; + } + } + + if (possible_in == -1) { + + /* wildcard for input */ + + if (possible_out == -1) { + /* out much match in */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out == -2) { + /* any configuration possible, pick matching */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out.set (DataType::AUDIO, -possible_out); + plugcnt = 1; + } else { + /* exact number of outputs */ + out.set (DataType::AUDIO, possible_out); + plugcnt = 1; + } + } + + if (possible_in == -2) { + + if (possible_out == -1) { + /* any configuration possible, pick matching */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out == -2) { + error << string_compose (_("AU plugin %1 has illegal IO configuration (-2,-2)"), name()) + << endmsg; + plugcnt = -1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out.set (DataType::AUDIO, -possible_out); + plugcnt = 1; + } else { + /* exact number of outputs */ + out.set (DataType::AUDIO, possible_out); + plugcnt = 1; + } + } + + if (possible_in < -2) { + + /* explicit variable number of inputs */ + + if (in > -possible_in) { + /* request is too large */ + plugcnt = -1; + } + + if (possible_out == -1) { + /* out must match in */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out == -2) { + error << string_compose (_("AU plugin %1 has illegal IO configuration (-2,-2)"), name()) + << endmsg; + plugcnt = -1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out.set (DataType::AUDIO, -possible_out); + plugcnt = 1; + } else { + /* exact number of outputs */ + out.set (DataType::AUDIO, possible_out); + plugcnt = 1; + } + } + + if (possible_in == in) { + + /* exact number of inputs ... must match obviously */ + + if (possible_out == -1) { + /* out must match in */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out == -2) { + /* any output configuration, pick matching */ + out.set (DataType::AUDIO, in); + plugcnt = -1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out.set (DataType::AUDIO, -possible_out); + plugcnt = 1; + } else { + /* exact number of outputs */ + out.set (DataType::AUDIO, possible_out); + plugcnt = 1; + } + } + + } + + /* no fit */ + return plugcnt; } int -AUPlugin::set_stream_format (int scope, uint32_t cnt) +AUPlugin::set_input_format (AudioStreamBasicDescription& fmt) +{ + return set_stream_format (kAudioUnitScope_Input, input_elements, fmt); +} + +int +AUPlugin::set_output_format (AudioStreamBasicDescription& fmt) +{ + if (set_stream_format (kAudioUnitScope_Output, output_elements, fmt) != 0) { + return -1; + } + + if (buffers) { + free (buffers); + buffers = 0; + } + + buffers = (AudioBufferList *) malloc (offsetof(AudioBufferList, mBuffers) + + fmt.mChannelsPerFrame * sizeof(AudioBuffer)); + + Glib::Mutex::Lock em (_session.engine().process_lock()); + IO::PortCountChanged (ChanCount (DataType::AUDIO, fmt.mChannelsPerFrame)); + + return 0; +} + +int +AUPlugin::set_stream_format (int scope, uint32_t cnt, AudioStreamBasicDescription& fmt) { OSErr result; for (uint32_t i = 0; i < cnt; ++i) { - if ((result = unit->SetFormat (scope, i, streamFormat)) != 0) { + if ((result = unit->SetFormat (scope, i, fmt)) != 0) { error << string_compose (_("AUPlugin: could not set stream format for %1/%2 (err = %3)"), (scope == kAudioUnitScope_Input ? "input" : "output"), i, result) << endmsg; return -1; @@ -439,60 +619,44 @@ AUPlugin::set_stream_format (int scope, uint32_t cnt) } if (scope == kAudioUnitScope_Input) { - format_set |= 0x1; + input_channels = fmt.mChannelsPerFrame; } else { - format_set |= 0x2; + output_channels = fmt.mChannelsPerFrame; } return 0; } -int32_t -AUPlugin::compute_output_streams (int32_t nplugins) -{ - /* we will never replicate AU plugins - either they can do the I/O we need - or not. thus, we can ignore nplugins entirely. - */ - - if (set_output_format() == 0) { - if (buffers) { - free (buffers); - buffers = 0; - } - - buffers = (AudioBufferList *) malloc (offsetof(AudioBufferList, mBuffers) + - streamFormat.mChannelsPerFrame * sizeof(AudioBuffer)); - - Glib::Mutex::Lock em (_session.engine().process_lock()); - IO::MoreOutputs (streamFormat.mChannelsPerFrame); - - return streamFormat.mChannelsPerFrame; - } else { - return -1; - } -} - -uint32_t -AUPlugin::output_streams() const -{ - if (!(format_set & 0x2)) { - warning << string_compose (_("AUPlugin: %1 output_streams() called without any format set!"), name()) << endmsg; - return 1; - } - - return streamFormat.mChannelsPerFrame; -} - - -uint32_t +ChanCount AUPlugin::input_streams() const { - if (!(format_set & 0x1)) { - warning << _("AUPlugin: input_streams() called without any format set!") << endmsg; - return 1; + ChanCount in; + + if (input_channels < 0) { + warning << string_compose (_("AUPlugin: %1 input_streams() called without any format set!"), name()) << endmsg; + in.set_audio (1); + } else { + in.set_audio (input_channels); } - return streamFormat.mChannelsPerFrame; + + return in; +} + + +ChanCount +AUPlugin::output_streams() const +{ + ChanCount out; + + if (output_channels < 0) { + warning << string_compose (_("AUPlugin: %1 output_streams() called without any format set!"), name()) << endmsg; + out.set_audio (1); + } else { + out.set_audio (output_channels); + } + + return out; } OSStatus @@ -679,13 +843,25 @@ AUPluginInfo::load (Session& session) } catch (failed_constructor &err) { - return PluginPtr ((Plugin*) 0); + return PluginPtr (); } } +Glib::ustring +AUPluginInfo::au_cache_path () +{ + return Glib::build_filename (ARDOUR::get_user_ardour_path(), "au_cache"); +} + PluginInfoList AUPluginInfo::discover () { + XMLTree tree; + + if (!Glib::file_test (au_cache_path(), Glib::FILE_TEST_EXISTS)) { + ARDOUR::BootMessage (_("Discovering AudioUnit plugins (could take some time ...)")); + } + PluginInfoList plugs; discover_fx (plugs); @@ -839,17 +1015,211 @@ AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescrip info->type = ARDOUR::AudioUnit; info->unique_id = stringify_descriptor (*info->descriptor); - /* mark the plugin as having flexible i/o */ - - info->n_inputs = -1; - info->n_outputs = -1; + /* XXX not sure of the best way to handle plugin versioning yet + */ - plugs.push_back (info); + CAComponent cacomp (*info->descriptor); + + if (cacomp.GetResourceVersion (info->version) != noErr) { + info->version = 0; + } + + if (cached_io_configuration (info->unique_id, info->version, cacomp, info->cache, info->name)) { + + /* here we have to map apple's wildcard system to a simple pair + of values. + */ + + info->n_inputs = ChanCount (DataType::AUDIO, info->cache.io_configs.front().first); + info->n_outputs = ChanCount (DataType::AUDIO, info->cache.io_configs.front().second); + + if (info->cache.io_configs.size() > 1) { + cerr << "ODD: variable IO config for " << info->unique_id << endl; + } + + plugs.push_back (info); + + } else { + error << string_compose (_("Cannot get I/O configuration info for AU %1"), info->name) << endmsg; + } comp = FindNextComponent (comp, &desc); } } +bool +AUPluginInfo::cached_io_configuration (const std::string& unique_id, + UInt32 version, + CAComponent& comp, + AUPluginCachedInfo& cinfo, + const std::string& name) +{ + std::string id; + char buf[32]; + + /* concatenate unique ID with version to provide a key for cached info lookup. + this ensures we don't get stale information, or should if plugin developers + follow Apple "guidelines". + */ + + snprintf (buf, sizeof (buf), "%u", version); + id = unique_id; + id += '/'; + id += buf; + + CachedInfoMap::iterator cim = cached_info.find (id); + + if (cim != cached_info.end()) { + cinfo = cim->second; + return true; + } + + CAAudioUnit unit; + AUChannelInfo* channel_info; + UInt32 cnt; + int ret; + + ARDOUR::BootMessage (string_compose (_("Checking AudioUnit: %1"), name)); + + if (CAAudioUnit::Open (comp, unit) != noErr) { + return false; + } + + if ((ret = unit.GetChannelInfo (&channel_info, cnt)) < 0) { + return false; + } + + if (ret > 0) { + /* no explicit info available */ + + cinfo.io_configs.push_back (pair (-1, -1)); + + } else { + + /* store each configuration */ + + for (uint32_t n = 0; n < cnt; ++n) { + cinfo.io_configs.push_back (pair (channel_info[n].inChannels, + channel_info[n].outChannels)); + } + + free (channel_info); + } + + add_cached_info (id, cinfo); + save_cached_info (); + + return true; +} + +void +AUPluginInfo::add_cached_info (const std::string& id, AUPluginCachedInfo& cinfo) +{ + cached_info[id] = cinfo; +} + +void +AUPluginInfo::save_cached_info () +{ + XMLNode* node; + + node = new XMLNode (X_("AudioUnitPluginCache")); + + for (map::iterator i = cached_info.begin(); i != cached_info.end(); ++i) { + XMLNode* parent = new XMLNode (X_("plugin")); + parent->add_property ("id", i->first); + node->add_child_nocopy (*parent); + + for (vector >::iterator j = i->second.io_configs.begin(); j != i->second.io_configs.end(); ++j) { + + XMLNode* child = new XMLNode (X_("io")); + char buf[32]; + + snprintf (buf, sizeof (buf), "%d", j->first); + child->add_property (X_("in"), buf); + snprintf (buf, sizeof (buf), "%d", j->second); + child->add_property (X_("out"), buf); + parent->add_child_nocopy (*child); + } + + } + + Glib::ustring path = au_cache_path (); + XMLTree tree; + + tree.set_root (node); + + if (!tree.write (path)) { + error << string_compose (_("could not save AU cache to %1"), path) << endmsg; + unlink (path.c_str()); + } +} + +int +AUPluginInfo::load_cached_info () +{ + Glib::ustring path = au_cache_path (); + XMLTree tree; + + if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) { + return 0; + } + + tree.read (path); + const XMLNode* root (tree.root()); + + if (root->name() != X_("AudioUnitPluginCache")) { + return -1; + } + + cached_info.clear (); + + const XMLNodeList children = root->children(); + + for (XMLNodeConstIterator iter = children.begin(); iter != children.end(); ++iter) { + + const XMLNode* child = *iter; + + if (child->name() == X_("plugin")) { + + const XMLNode* gchild; + const XMLNodeList gchildren = child->children(); + const XMLProperty* prop = child->property (X_("id")); + + if (!prop) { + continue; + } + + std::string id = prop->value(); + + for (XMLNodeConstIterator giter = gchildren.begin(); giter != gchildren.end(); giter++) { + + gchild = *giter; + + if (gchild->name() == X_("io")) { + + int in; + int out; + const XMLProperty* iprop; + const XMLProperty* oprop; + + if (((iprop = gchild->property (X_("in"))) != 0) && + ((oprop = gchild->property (X_("out"))) != 0)) { + in = atoi (iprop->value()); + out = atoi (iprop->value()); + + AUPluginCachedInfo cinfo; + cinfo.io_configs.push_back (pair (in, out)); + add_cached_info (id, cinfo); + } + } + } + } + } + + return 0; +} + void AUPluginInfo::get_names (CAComponentDescription& comp_desc, std::string& name, Glib::ustring& maker) { diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index a3f5eb9fd1..76c0de9b24 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -70,13 +70,12 @@ AudioEngine::AudioEngine (string client_name) last_monitor_check = 0; monitor_check_interval = max_frames; _processed_frames = 0; - _freewheeling = false; _usecs_per_cycle = 0; _jack = 0; _frame_rate = 0; _buffer_size = 0; - _freewheeling = false; _freewheel_thread_registered = false; + _freewheeling = false; m_meter_thread = 0; g_atomic_int_set (&m_meter_exit, 0); @@ -84,6 +83,7 @@ AudioEngine::AudioEngine (string client_name) if (connect_to_jack (client_name)) { throw NoBackendAvailable (); } + Port::set_engine (this); } @@ -331,8 +331,6 @@ AudioEngine::process_callback (nframes_t nframes) if (_freewheeling) { /* emit the Freewheel signal and stop freewheeling in the event of trouble */ if (Freewheel (nframes)) { - cerr << "Freewheeling returned non-zero!\n"; - _freewheeling = false; jack_set_freewheel (_jack, false); } @@ -847,7 +845,7 @@ AudioEngine::frames_per_cycle () * Note this can return NULL, it will NOT create a port if it is not found (any more). */ Port * -AudioEngine::get_port_by_name (const string& portname, bool keep) const +AudioEngine::get_port_by_name (const string& portname, bool keep) { Glib::Mutex::Lock lm (_process_lock); @@ -923,7 +921,7 @@ AudioEngine::can_request_hardware_monitoring () uint32_t -AudioEngine::n_physical_outputs () const +AudioEngine::n_physical_outputs (DataType type) const { const char ** ports; uint32_t i = 0; @@ -932,7 +930,7 @@ AudioEngine::n_physical_outputs () const return 0; } - if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == 0) { + if ((ports = jack_get_ports (_jack, NULL, type.to_jack_type(), JackPortIsPhysical|JackPortIsInput)) == 0) { return 0; } @@ -943,7 +941,7 @@ AudioEngine::n_physical_outputs () const } uint32_t -AudioEngine::n_physical_inputs () const +AudioEngine::n_physical_inputs (DataType type) const { const char ** ports; uint32_t i = 0; @@ -952,7 +950,7 @@ AudioEngine::n_physical_inputs () const return 0; } - if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsOutput)) == 0) { + if ((ports = jack_get_ports (_jack, NULL, type.to_jack_type(), JackPortIsPhysical|JackPortIsOutput)) == 0) { return 0; } @@ -964,7 +962,7 @@ AudioEngine::n_physical_inputs () const } void -AudioEngine::get_physical_inputs (vector& ins) +AudioEngine::get_physical_inputs (DataType type, vector& ins) { const char ** ports; uint32_t i = 0; @@ -973,7 +971,7 @@ AudioEngine::get_physical_inputs (vector& ins) return; } - if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsOutput)) == 0) { + if ((ports = jack_get_ports (_jack, NULL, type.to_jack_type(), JackPortIsPhysical|JackPortIsOutput)) == 0) { return; } @@ -986,7 +984,7 @@ AudioEngine::get_physical_inputs (vector& ins) } void -AudioEngine::get_physical_outputs (vector& outs) +AudioEngine::get_physical_outputs (DataType type, vector& outs) { const char ** ports; uint32_t i = 0; @@ -995,7 +993,7 @@ AudioEngine::get_physical_outputs (vector& outs) return; } - if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == 0) { + if ((ports = jack_get_ports (_jack, NULL, type.to_jack_type(), JackPortIsPhysical|JackPortIsInput)) == 0) { return; } @@ -1123,11 +1121,18 @@ AudioEngine::freewheel (bool onoff) { if (_jack) { - if (onoff) { - _freewheel_thread_registered = false; - } + if (onoff != _freewheeling) { - return jack_set_freewheel (_jack, onoff); + if (onoff) { + _freewheel_thread_registered = false; + } + + return jack_set_freewheel (_jack, onoff); + + } else { + /* already doing what has been asked for */ + return 0; + } } else { return -1; diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index f5f04eac6d..cbf2e44c5f 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -1243,6 +1243,15 @@ AudioRegion::speed_mismatch (float sr) const void AudioRegion::source_offset_changed () { + /* XXX this fixes a crash that should not occur. It does occur + becauses regions are not being deleted when a session + is unloaded. That bug must be fixed. + */ + + if (_sources.empty()) { + return; + } + boost::shared_ptr afs = boost::dynamic_pointer_cast(_sources.front()); if (afs && afs->destructive()) { diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc index 01dea08d3e..8e68b31587 100644 --- a/libs/ardour/audiosource.cc +++ b/libs/ardour/audiosource.cc @@ -214,7 +214,7 @@ AudioSource::initialize_peakfile (bool newfile, ustring audio_path) /* we found it in the peaks dir, so check it out */ - if (statbuf.st_size == 0 || (statbuf.st_size < ((length() / _FPP) * sizeof (PeakData)))) { + if (statbuf.st_size == 0 || ((nframes_t) statbuf.st_size < ((length() / _FPP) * sizeof (PeakData)))) { // empty _peaks_built = false; } else { diff --git a/libs/ardour/auto_bundle.cc b/libs/ardour/auto_bundle.cc index 9da32bbb7a..fc70768601 100644 --- a/libs/ardour/auto_bundle.cc +++ b/libs/ardour/auto_bundle.cc @@ -13,17 +13,17 @@ ARDOUR::AutoBundle::AutoBundle (std::string const & n, bool i) } -uint32_t +ARDOUR::ChanCount ARDOUR::AutoBundle::nchannels () const { Glib::Mutex::Lock lm (_ports_mutex); - return _ports.size (); + return ChanCount (type(), _ports.size ()); } const ARDOUR::PortList& ARDOUR::AutoBundle::channel_ports (uint32_t c) const { - assert (c < nchannels()); + assert (c < nchannels().get (type())); Glib::Mutex::Lock lm (_ports_mutex); return _ports[c]; @@ -39,7 +39,7 @@ ARDOUR::AutoBundle::set_channels (uint32_t n) void ARDOUR::AutoBundle::set_port (uint32_t c, std::string const & p) { - assert (c < nchannels ()); + assert (c < nchannels ().get (type())); Glib::Mutex::Lock lm (_ports_mutex); _ports[c].resize (1); diff --git a/libs/ardour/configuration.cc b/libs/ardour/configuration.cc index b164d418ab..56dfd99f02 100644 --- a/libs/ardour/configuration.cc +++ b/libs/ardour/configuration.cc @@ -22,6 +22,7 @@ #include #include /* for g_stat() */ +#include #include #include diff --git a/libs/ardour/crossfade.cc b/libs/ardour/crossfade.cc index f3dfa28165..213e7504b0 100644 --- a/libs/ardour/crossfade.cc +++ b/libs/ardour/crossfade.cc @@ -84,7 +84,6 @@ Crossfade::Crossfade (boost::shared_ptr in, boost::shared_ptr