X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fardour_ui.cc;h=7e0e06e97ffffc72e6a517404e82fd08a8232c75;hb=aa60114843f4990ef93ba83974501495ddda358b;hp=55370e7557674ec39cbedc1037e5263a23da29ba;hpb=96de823f23e29de25d645b42a8b1c43c41d7a594;p=ardour.git diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 55370e7557..7e0e06e97f 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 1999-2002 Paul Davis + Copyright (C) 1999-2007 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 @@ -28,6 +28,8 @@ #include +#include + #include #include @@ -35,6 +37,8 @@ #include #include #include +#include +#include #include #include #include @@ -85,6 +89,7 @@ ARDOUR_UI *ARDOUR_UI::theArdourUI = 0; sigc::signal ARDOUR_UI::Blink; sigc::signal ARDOUR_UI::RapidScreenUpdate; +sigc::signal ARDOUR_UI::MidRapidScreenUpdate; sigc::signal ARDOUR_UI::SuperRapidScreenUpdate; sigc::signal ARDOUR_UI::Clock; @@ -92,10 +97,10 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile) : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile), - primary_clock (X_("TransportClockDisplay"), true, false, true), - secondary_clock (X_("SecondaryClockDisplay"), true, false, true), - preroll_clock (X_("PreRollClock"), true, true), - postroll_clock (X_("PostRollClock"), true, true), + primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true), + secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true), + preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true), + postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true), /* adjuster table */ @@ -108,7 +113,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile) /* big clock */ - big_clock ("BigClockDisplay", true), + big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true), /* transport */ @@ -141,7 +146,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile) color_manager = new ColorManager(); std::string color_file = ARDOUR::find_config_file("ardour.colors"); - + color_manager->load (color_file); editor = 0; @@ -156,7 +161,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile) route_params = 0; option_editor = 0; location_ui = 0; - sfdb = 0; open_session_selector = 0; have_configure_timeout = false; have_disk_overrun_displayed = false; @@ -164,6 +168,10 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile) _will_create_new_session_automatically = false; session_loaded = false; last_speed_displayed = -1.0f; + keybindings_path = ARDOUR::find_config_file ("ardour.bindings"); + + can_save_keybindings = false; + Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::first_idle)); last_configure_time.tv_sec = 0; last_configure_time.tv_usec = 0; @@ -178,7 +186,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile) gettimeofday (&last_peak_grab, 0); gettimeofday (&last_shuttle_request, 0); - ARDOUR::AudioDiskstream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread)); ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler)); ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler)); @@ -245,6 +252,11 @@ ARDOUR_UI::set_engine (AudioEngine& e) throw failed_constructor(); } + /* set default clock modes */ + + primary_clock.set_mode (AudioClock::SMPTE); + secondary_clock.set_mode (AudioClock::BBT); + /* start the time-of-day-clock */ update_wall_clock (); @@ -346,22 +358,31 @@ ARDOUR_UI::save_ardour_state () Config->add_instant_xml (mnode, get_user_ardour_path()); } - /* keybindings */ - - AccelMap::save ("ardour.saved_bindings"); + save_keybindings (); } void ARDOUR_UI::startup () { - /* Once the UI is up and running, start the audio engine. Doing - this before the UI is up and running can cause problems - when not running with SCHED_FIFO, because the amount of - CPU and disk work needed to get the UI started can interfere - with the scheduling of the audio thread. - */ + if (engine->is_realtime()) { - Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine)); + struct rlimit limits; + + if (getrlimit (RLIMIT_MEMLOCK, &limits)) { + return; + } + + if (limits.rlim_cur != RLIM_INFINITY) { + MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. " + "This might cause Ardour to run out of memory before your system " + "runs out of memory. \n\n" + "You can view the memory limit with 'ulimit -l', " + "and it is normally controlled by /etc/security/limits.conf")); + + editor->ensure_float (msg); + msg.run (); + } + } } void @@ -389,6 +410,11 @@ If you still wish to quit, please use the\n\n\ break; } } + + if (session) { + session->set_deletion_in_progress (); + } + engine->stop (true); Config->save_state(); quit (); } @@ -445,7 +471,8 @@ ARDOUR_UI::ask_about_saving_session (const string & what) save_the_session = 0; - editor->ensure_float (window); + window.set_keep_above (true); + window.present (); ResponseType r = (ResponseType) window.run(); @@ -480,6 +507,13 @@ ARDOUR_UI::every_point_one_seconds () return TRUE; } +gint +ARDOUR_UI::every_point_oh_five_seconds () +{ + MidRapidScreenUpdate(); /* EMIT_SIGNAL */ + return true; +} + gint ARDOUR_UI::every_point_zero_one_seconds () { @@ -539,11 +573,11 @@ ARDOUR_UI::update_buffer_load () } void -ARDOUR_UI::count_recenabled_diskstreams (Route& route) +ARDOUR_UI::count_recenabled_streams (Route& route) { Track* track = dynamic_cast(&route); if (track && track->diskstream()->record_enabled()) { - rec_enabled_diskstreams++; + rec_enabled_streams += track->n_inputs(); } } @@ -565,21 +599,11 @@ ARDOUR_UI::update_disk_space() int secs; nframes_t fr = session->frame_rate(); - if (session->actively_recording()){ - - rec_enabled_diskstreams = 0; - session->foreach_route (this, &ARDOUR_UI::count_recenabled_diskstreams); - - if (rec_enabled_diskstreams) { - frames /= rec_enabled_diskstreams; - } - - } else { - - /* hmmm. shall we divide by the route count? or the diskstream count? - or what? for now, do nothing ... - */ - + rec_enabled_streams = 0; + session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams); + + if (rec_enabled_streams) { + frames /= rec_enabled_streams; } hrs = frames / (fr * 3600); @@ -960,7 +984,7 @@ ARDOUR_UI::transport_goto_start () */ if (editor) { - editor->reposition_x_origin (session->current_start_frame()); + editor->reset_x_origin (session->current_start_frame()); } } } @@ -977,7 +1001,7 @@ ARDOUR_UI::transport_goto_zero () */ if (editor) { - editor->reposition_x_origin (0); + editor->reset_x_origin (0); } } } @@ -994,7 +1018,7 @@ ARDOUR_UI::transport_goto_end () */ if (editor) { - editor->reposition_x_origin (frame); + editor->reset_x_origin (frame); } } } @@ -1011,7 +1035,7 @@ ARDOUR_UI::transport_stop () return; } - if (Config->get_auto_loop()) { + if (session->get_play_loop ()) { session->request_play_loop (false); } @@ -1041,8 +1065,7 @@ ARDOUR_UI::transport_record () switch (session->record_status()) { case Session::Disabled: if (session->ntracks() == 0) { - string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."); - MessageDialog msg (*editor, txt); + MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.")); msg.run (); return; } @@ -1066,7 +1089,7 @@ ARDOUR_UI::transport_roll () rolling = session->transport_rolling (); - if (Config->get_auto_loop()) { + if (session->get_play_loop()) { session->request_play_loop (false); auto_loop_button.set_active (false); roll_button.set_active (true); @@ -1084,7 +1107,7 @@ void ARDOUR_UI::transport_loop() { if (session) { - if (Config->get_auto_loop()) { + if (session->get_play_loop()) { if (session->transport_rolling()) { Location * looploc = session->locations()->auto_loop_location(); if (looploc) { @@ -1243,13 +1266,55 @@ ARDOUR_UI::engine_stopped () ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true); } - void ARDOUR_UI::engine_running () { ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running)); ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true); ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false); + + Glib::RefPtr action; + char* action_name = 0; + + switch (engine->frames_per_cycle()) { + case 32: + action_name = X_("JACKLatency32"); + break; + case 64: + action_name = X_("JACKLatency64"); + break; + case 128: + action_name = X_("JACKLatency128"); + break; + case 512: + action_name = X_("JACKLatency512"); + break; + case 1024: + action_name = X_("JACKLatency1024"); + break; + case 2048: + action_name = X_("JACKLatency2048"); + break; + case 4096: + action_name = X_("JACKLatency4096"); + break; + case 8192: + action_name = X_("JACKLatency8192"); + break; + default: + /* XXX can we do anything useful ? */ + break; + } + + if (action_name) { + + action = ActionManager::get_action (X_("JACK"), action_name); + + if (action) { + Glib::RefPtr ract = Glib::RefPtr::cast_dynamic (action); + ract->set_active (); + } + } } void @@ -1278,14 +1343,6 @@ ARDOUR_UI::do_engine_start () engine->start(); } - catch (AudioEngine::PortRegistrationFailure& err) { - engine->stop (); - error << _("Unable to create all required ports") - << endmsg; - unload_session (); - return -1; - } - catch (...) { engine->stop (); error << _("Unable to start the session running") @@ -1307,14 +1364,6 @@ ARDOUR_UI::start_engine () */ session->save_state (""); } - - /* there is too much going on, in too many threads, for us to - end up with a clean session. So wait 1 second after loading, - and fix it up. its ugly, but until i come across a better - solution, its what we have. - */ - - Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000); } return FALSE; @@ -1323,7 +1372,9 @@ ARDOUR_UI::start_engine () void ARDOUR_UI::update_clocks () { - Clock (session->audible_frame()); /* EMIT_SIGNAL */ + if (!editor || !editor->dragging_playhead()) { + Clock (session->audible_frame()); /* EMIT_SIGNAL */ + } } void @@ -1436,18 +1487,18 @@ ARDOUR_UI::snapshot_session () { ArdourPrompter prompter (true); string snapname; - string now; + char timebuf[128]; time_t n; + struct tm local_time; time (&n); - now = ctime (&n); - now = now.substr (20, 4) + now.substr (3, 16) + " (" + now.substr (0, 3) + ")"; + localtime_r (&n, &local_time); + strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time); prompter.set_name ("Prompter"); prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT); - prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false); prompter.set_prompt (_("Name of New Snapshot")); - prompter.set_initial_text (now); + prompter.set_initial_text (timebuf); switch (prompter.run()) { case RESPONSE_ACCEPT: @@ -1595,7 +1646,6 @@ ARDOUR_UI::save_template () prompter.set_prompt (_("Name for mix template:")); prompter.set_initial_text(session->name() + _("-template")); prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT); - prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false); switch (prompter.run()) { case RESPONSE_ACCEPT: @@ -1612,7 +1662,7 @@ ARDOUR_UI::save_template () } void -ARDOUR_UI::new_session (bool startup, std::string predetermined_path) +ARDOUR_UI::new_session (std::string predetermined_path) { string session_name; string session_path; @@ -1620,18 +1670,25 @@ ARDOUR_UI::new_session (bool startup, std::string predetermined_path) int response = Gtk::RESPONSE_NONE; new_session_dialog->set_modal(true); - new_session_dialog->set_name(predetermined_path); + new_session_dialog->set_name (predetermined_path); new_session_dialog->reset_recent(); new_session_dialog->show(); do { response = new_session_dialog->run (); + + _session_is_new = false; - if(response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) { - quit(); + if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) { + + if (!session) { + quit(); + } + new_session_dialog->hide (); return; } else if (response == Gtk::RESPONSE_NONE) { + /* Clear was pressed */ new_session_dialog->reset(); @@ -1683,8 +1740,6 @@ ARDOUR_UI::new_session (bool startup, std::string predetermined_path) } else { - _session_is_new = true; - if (session_name.empty()) { response = Gtk::RESPONSE_NONE; continue; @@ -1699,15 +1754,44 @@ ARDOUR_UI::new_session (bool startup, std::string predetermined_path) } else { - std::string session_path = new_session_dialog->session_folder(); - + session_path = new_session_dialog->session_folder(); + } - + //XXX This is needed because session constructor wants a //non-existant path. hopefully this will be fixed at some point. session_path = Glib::build_filename (session_path, session_name); + if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { + + Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path); + + MessageDialog msg (str, + false, + Gtk::MESSAGE_WARNING, + Gtk::BUTTONS_YES_NO, + true); + + + msg.set_name (X_("CleanupDialog")); + msg.set_wmclass (X_("existing_session"), "Ardour"); + msg.set_position (Gtk::WIN_POS_MOUSE); + + switch (msg.run()) { + case RESPONSE_YES: + load_session (session_path, session_name); + goto done; + break; + default: + response = RESPONSE_NONE; + new_session_dialog->reset (); + continue; + } + } + + _session_is_new = true; + std::string template_name = new_session_dialog->session_template_name(); if (new_session_dialog->use_session_template()) { @@ -1767,6 +1851,7 @@ ARDOUR_UI::new_session (bool startup, std::string predetermined_path) } while (response == Gtk::RESPONSE_NONE); + done: show(); new_session_dialog->get_window()->set_cursor(); new_session_dialog->hide(); @@ -1785,6 +1870,7 @@ ARDOUR_UI::load_session (const string & path, const string & snap_name, string* Session *new_session; int x; session_loaded = false; + x = unload_session (); if (x < 0) { @@ -1796,9 +1882,8 @@ ARDOUR_UI::load_session (const string & path, const string & snap_name, string* /* if it already exists, we must have write access */ if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) { - MessageDialog msg (*editor, _("\ -You do not have write access to this session.\n\ -This prevents the session from being loaded.")); + MessageDialog msg (*editor, _("You do not have write access to this session.\n" + "This prevents the session from being loaded.")); msg.run (); return -1; } @@ -1818,19 +1903,14 @@ This prevents the session from being loaded.")); Config->set_current_owner (ConfigVariableBase::Interface); session_loaded = true; - return 0; -} + + goto_editor_window (); -int -ARDOUR_UI::make_session_clean () -{ if (session) { session->set_clean (); } - show (); - - return FALSE; + return 0; } int @@ -1885,10 +1965,6 @@ ARDOUR_UI::show () shown_flag = true; } - - if (about) { - about->present (); - } } void @@ -1896,8 +1972,16 @@ ARDOUR_UI::show_splash () { if (about == 0) { about = new About(); + about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) ); } about->present(); + flush_pending (); +} + +void +ARDOUR_UI::about_signal_response(int response) +{ + hide_splash(); } void @@ -1921,7 +2005,7 @@ ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* l _("No audio files were ready for cleanup"), true, Gtk::MESSAGE_INFO, - (Gtk::ButtonsType)(Gtk::BUTTONS_CLOSE) ); + (Gtk::ButtonsType)(Gtk::BUTTONS_OK) ); msgd.set_secondary_text (_("If this seems suprising, \n\ check for any existing snapshots.\n\ These may still include regions that\n\ @@ -2031,7 +2115,7 @@ After cleanup, unused audio files will be moved to a \ checker.set_default_response (RESPONSE_CANCEL); checker.set_name (_("CleanupDialog")); - checker.set_wmclass (_("ardour_cleanup"), "Ardour"); + checker.set_wmclass (X_("ardour_cleanup"), "Ardour"); checker.set_position (Gtk::WIN_POS_MOUSE); switch (checker.run()) { @@ -2197,18 +2281,6 @@ ARDOUR_UI::halt_on_xrun_message () msg.run (); } -void -ARDOUR_UI::delete_sources_in_the_right_thread (list >* deletion_list) -{ - ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list)); - - for (list >::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) { - (*i)->drop_references (); - } - - delete deletion_list; -} - void ARDOUR_UI::disk_overrun_handler () { @@ -2311,13 +2383,6 @@ ARDOUR_UI::reconnect_to_jack () } } -void -ARDOUR_UI::set_jack_buffer_size (nframes_t nframes) -{ - engine->request_buffer_size (nframes); - update_sample_rate (0); -} - int ARDOUR_UI::cmdline_new_session (string path) { @@ -2332,7 +2397,7 @@ ARDOUR_UI::cmdline_new_session (string path) path = str; } - new_session (false, path); + new_session (path); _will_create_new_session_automatically = false; /* done it */ return FALSE; /* don't call it again */ @@ -2386,3 +2451,71 @@ ARDOUR_UI::use_config () ract->set_active (); } } + +void +ARDOUR_UI::update_transport_clocks (nframes_t pos) +{ + primary_clock.set (pos); + secondary_clock.set (pos); + + if (big_clock_window) { + big_clock.set (pos); + } +} + +void +ARDOUR_UI::record_state_changed () +{ + ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed)); + + if (!session || !big_clock_window) { + /* why bother - the clock isn't visible */ + return; + } + + switch (session->record_status()) { + case Session::Recording: + big_clock.set_widget_name ("BigClockRecording"); + break; + default: + big_clock.set_widget_name ("BigClockNonRecording"); + break; + } +} + +void +ARDOUR_UI::set_keybindings_path (string path) +{ + keybindings_path = path; +} + +void +ARDOUR_UI::save_keybindings () +{ + if (can_save_keybindings) { + AccelMap::save (keybindings_path); + } +} + +bool +ARDOUR_UI::first_idle () +{ + can_save_keybindings = true; + return false; +} + +void +ARDOUR_UI::store_clock_modes () +{ + XMLNode* node = new XMLNode(X_("ClockModes")); + + for (vector::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) { + node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode())); + } + + session->add_extra_xml (*node); + session->set_dirty (); +} + + +