X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fardour_ui.cc;h=de006a8fecab3eb4a3e40e723118bd4e35ef2f85;hb=b3fe7cfc892f7d5978ad14eb81e9305fa9c14d13;hp=827a9673617c0df120f777bcdf41da3e11f3b60e;hpb=e51e31dca20d1e636508c61d93a740fdb48eeebd;p=ardour.git diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 827a967361..de006a8fec 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 @@ -15,9 +15,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id$ */ +#define __STDC_FORMAT_MACROS 1 +#include + #include #include #include @@ -28,6 +30,8 @@ #include +#include + #include #include @@ -35,17 +39,22 @@ #include #include #include +#include +#include #include #include #include #include #include #include +#include #include #include #include +#include +#include #include #include #include @@ -53,7 +62,6 @@ #include #include #include -#include #include #include #include @@ -66,7 +74,6 @@ #include "mixer_ui.h" #include "prompter.h" #include "opts.h" -#include "keyboard_target.h" #include "add_route_dialog.h" #include "new_session_dialog.h" #include "about.h" @@ -87,16 +94,16 @@ ARDOUR_UI *ARDOUR_UI::theArdourUI = 0; sigc::signal ARDOUR_UI::Blink; sigc::signal ARDOUR_UI::RapidScreenUpdate; sigc::signal ARDOUR_UI::SuperRapidScreenUpdate; -sigc::signal ARDOUR_UI::Clock; +sigc::signal ARDOUR_UI::Clock; ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile) - : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile), + : Gtkmm2ext::UI (X_("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 */ @@ -109,20 +116,38 @@ 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 */ - time_master_button (_("time\nmaster")), - + 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), + shuttle_controller_binding_proxy (shuttle_controllable), + + roll_button (roll_controllable), + stop_button (stop_controllable), + goto_start_button (goto_start_controllable), + goto_end_button (goto_end_controllable), + auto_loop_button (auto_loop_controllable), + play_selection_button (play_selection_controllable), + rec_button (rec_controllable), + shuttle_units_button (_("% ")), punch_in_button (_("Punch In")), punch_out_button (_("Punch Out")), auto_return_button (_("Auto Return")), - auto_play_button (_("Autuo Play")), + auto_play_button (_("Auto Play")), auto_input_button (_("Auto Input")), click_button (_("Click")), + time_master_button (_("time\nmaster")), + auditioning_alert_button (_("AUDITION")), solo_alert_button (_("SOLO")), shown_flag (false) @@ -137,17 +162,14 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile) theArdourUI = this; } - ActionManager::init (); - /* load colors */ color_manager = new ColorManager(); std::string color_file = ARDOUR::find_config_file("ardour.colors"); - + color_manager->load (color_file); - m_new_session_dialog = new NewSessionDialog(); editor = 0; mixer = 0; session = 0; @@ -160,14 +182,15 @@ 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; - have_disk_underrun_displayed = false; + have_disk_speed_dialog_displayed = false; _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; last_configure_time.tv_sec = 0; last_configure_time.tv_usec = 0; @@ -176,16 +199,12 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile) shuttle_fract = 0.0; shuttle_max_speed = 8.0f; - set_shuttle_units (Percentage); - set_shuttle_behaviour (Sprung); - shuttle_style_menu = 0; shuttle_unit_menu = 0; 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)); @@ -206,6 +225,9 @@ ARDOUR_UI::set_engine (AudioEngine& e) engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted)); engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate)); + ActionManager::init (); + new_session_dialog = new NewSessionDialog(); + _tooltips.enable(); keyboard = new Keyboard; @@ -245,9 +267,10 @@ ARDOUR_UI::set_engine (AudioEngine& e) AudioFileSource::set_build_peakfiles (true); AudioFileSource::set_build_missing_peakfiles (true); - if (AudioSource::start_peak_thread ()) { - 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 */ @@ -281,8 +304,6 @@ ARDOUR_UI::~ARDOUR_UI () if (add_route_dialog) { delete add_route_dialog; } - - AudioSource::stop_peak_thread (); } gint @@ -324,6 +345,63 @@ ARDOUR_UI::configure_handler (GdkEventConfigure* conf) return FALSE; } +void +ARDOUR_UI::set_transport_controllable_state (const XMLNode& node) +{ + const XMLProperty* prop; + + if ((prop = node.property ("roll")) != 0) { + roll_controllable.set_id (prop->value()); + } + if ((prop = node.property ("stop")) != 0) { + stop_controllable.set_id (prop->value()); + } + if ((prop = node.property ("goto_start")) != 0) { + goto_start_controllable.set_id (prop->value()); + } + if ((prop = node.property ("goto_end")) != 0) { + goto_end_controllable.set_id (prop->value()); + } + if ((prop = node.property ("auto_loop")) != 0) { + auto_loop_controllable.set_id (prop->value()); + } + if ((prop = node.property ("play_selection")) != 0) { + play_selection_controllable.set_id (prop->value()); + } + if ((prop = node.property ("rec")) != 0) { + rec_controllable.set_id (prop->value()); + } + if ((prop = node.property ("shuttle")) != 0) { + shuttle_controllable.set_id (prop->value()); + } +} + +XMLNode& +ARDOUR_UI::get_transport_controllable_state () +{ + XMLNode* node = new XMLNode(X_("TransportControllables")); + char buf[64]; + + roll_controllable.id().print (buf, sizeof (buf)); + node->add_property (X_("roll"), buf); + stop_controllable.id().print (buf, sizeof (buf)); + node->add_property (X_("stop"), buf); + goto_start_controllable.id().print (buf, sizeof (buf)); + node->add_property (X_("goto_start"), buf); + goto_end_controllable.id().print (buf, sizeof (buf)); + node->add_property (X_("goto_end"), buf); + auto_loop_controllable.id().print (buf, sizeof (buf)); + node->add_property (X_("auto_loop"), buf); + play_selection_controllable.id().print (buf, sizeof (buf)); + node->add_property (X_("play_selection"), buf); + rec_controllable.id().print (buf, sizeof (buf)); + node->add_property (X_("rec"), buf); + shuttle_controllable.id().print (buf, sizeof (buf)); + node->add_property (X_("shuttle"), buf); + + return *node; +} + void ARDOUR_UI::save_ardour_state () { @@ -337,6 +415,7 @@ ARDOUR_UI::save_ardour_state () XMLNode* node = new XMLNode (keyboard->get_state()); Config->add_extra_xml (*node); + Config->add_extra_xml (get_transport_controllable_state()); Config->save_state(); XMLNode enode(static_cast(editor)->get_state()); @@ -350,24 +429,111 @@ ARDOUR_UI::save_ardour_state () Config->add_instant_xml (mnode, get_user_ardour_path()); } - /* keybindings */ + save_keybindings (); +} + +gint +ARDOUR_UI::autosave_session () +{ + if (!Config->get_periodic_safety_backups()) + return 1; + + if (session) { + session->maybe_write_autosave(); + } + + return 1; +} - AccelMap::save ("ardour.saved_bindings"); +void +ARDOUR_UI::update_autosave () +{ + ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave)); + + if (session->dirty()) { + if (_autosave_connection.connected()) { + _autosave_connection.disconnect(); + } + + _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session), + Config->get_periodic_safety_backup_interval() * 1000); + + } else { + if (_autosave_connection.connected()) { + _autosave_connection.disconnect(); + } + } } 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. - */ + check_memory_locking(); +} - Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine)); +void +ARDOUR_UI::no_memory_warning () +{ + XMLNode node (X_("no-memory-warning")); + Config->add_instant_xml (node, get_user_ardour_path()); } +void +ARDOUR_UI::check_memory_locking () +{ +#ifdef __APPLE__ + /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */ + return; +#else // !__APPLE__ + + XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path()); + + if (engine->is_realtime() && memory_warning_node == 0) { + + struct rlimit limits; + int64_t ram; + long pages, page_size; + + if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) { + ram = 0; + } else { + ram = (int64_t) pages * (int64_t) page_size; + } + + if (getrlimit (RLIMIT_MEMLOCK, &limits)) { + return; + } + + if (limits.rlim_cur != RLIM_INFINITY) { + + if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) { + + + 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")); + + VBox* vbox = msg.get_vbox(); + HBox hbox; + CheckButton cb (_("Do not show this window again")); + + cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning)); + + hbox.pack_start (cb, true, false); + vbox->pack_start (hbox); + hbox.show_all (); + + editor->ensure_float (msg); + msg.run (); + } + } + } +#endif // !__APPLE__ +} + + void ARDOUR_UI::finish() { @@ -393,6 +559,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 (); } @@ -449,7 +620,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(); @@ -492,7 +664,7 @@ ARDOUR_UI::every_point_zero_one_seconds () } void -ARDOUR_UI::update_sample_rate (jack_nframes_t ignored) +ARDOUR_UI::update_sample_rate (nframes_t ignored) { char buf[32]; @@ -504,14 +676,14 @@ ARDOUR_UI::update_sample_rate (jack_nframes_t ignored) } else { - jack_nframes_t rate = engine->frame_rate(); + nframes_t rate = engine->frame_rate(); if (fmod (rate, 1000.0) != 0.0) { - snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f msecs"), + snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"), (float) rate/1000.0f, (engine->frames_per_cycle() / (float) rate) * 1000.0f); } else { - snprintf (buf, sizeof (buf), _("%u kHz / %4.1f msecs"), + snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"), rate/1000, (engine->frames_per_cycle() / (float) rate) * 1000.0f); } @@ -524,7 +696,7 @@ void ARDOUR_UI::update_cpu_load () { char buf[32]; - snprintf (buf, sizeof (buf), _("DSP: %.1f%%"), engine->get_cpu_load()); + snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load()); cpu_load_label.set_text (buf); } @@ -543,11 +715,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++; + if (track && track->diskstream()->record_enabled()) { + rec_enabled_streams += track->n_inputs().get_total(); } } @@ -558,7 +730,7 @@ ARDOUR_UI::update_disk_space() return; } - jack_nframes_t frames = session->available_capture_duration(); + nframes_t frames = session->available_capture_duration(); char buf[64]; if (frames == max_frames) { @@ -567,23 +739,13 @@ ARDOUR_UI::update_disk_space() int hrs; int mins; int secs; - jack_nframes_t fr = session->frame_rate(); + 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); @@ -613,40 +775,6 @@ ARDOUR_UI::update_wall_clock () return TRUE; } -void -ARDOUR_UI::control_methods_adjusted () - -{ - int which_method; - - which_method = (int) online_control_button->adjustment.get_value(); - switch (which_method) { - case 0: - allow_mmc_and_local (); - break; - case 1: - allow_mmc_only (); - break; - case 2: - allow_local_only (); - break; - default: - fatal << _("programming error: impossible control method") << endmsg; - } -} - - -void -ARDOUR_UI::mmc_device_id_adjusted () - -{ -#if 0 - if (mmc) { - int dev_id = (int) mmc_id_button->adjustment.get_value(); - mmc->set_device_id (dev_id); - } -#endif -} gint ARDOUR_UI::session_menu (GdkEventButton *ev) @@ -823,9 +951,30 @@ ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) return S_ISREG (statbuf.st_mode); } +bool +ARDOUR_UI::check_audioengine () +{ + if (engine) { + if (!engine->connected()) { + MessageDialog msg (_("Ardour is not connected to JACK\n" + "You cannot open or close sessions in this condition")); + msg.run (); + return false; + } + return true; + } else { + return false; + } +} + void ARDOUR_UI::open_session () { + if (!check_audioengine()) { + return; + + } + /* popup selector window */ if (open_session_selector == 0) { @@ -869,9 +1018,9 @@ ARDOUR_UI::open_session () void -ARDOUR_UI::session_add_midi_route (bool disk) +ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many) { - boost::shared_ptr route; + list > tracks; if (session == 0) { warning << _("You cannot add a track without a session already loaded.") << endmsg; @@ -880,14 +1029,21 @@ ARDOUR_UI::session_add_midi_route (bool disk) try { if (disk) { - if ((route = session->new_midi_track (/*mode*/)) == 0) { - error << _("could not create new midi track") << endmsg; + + tracks = session->new_midi_track (ARDOUR::Normal, how_many); + + if (tracks.size() != how_many) { + if (how_many == 1) { + error << _("could not create a new midi track") << endmsg; + } else { + error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg; + } } - } else { + } /*else { if ((route = session->new_midi_route ()) == 0) { error << _("could not create new midi bus") << endmsg; } - } + }*/ } catch (...) { @@ -902,23 +1058,39 @@ restart JACK with more ports.")); void -ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode) +ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many) { - boost::shared_ptr route; + list > tracks; + Session::RouteList routes; if (session == 0) { - warning << _("You cannot add a track without a session already loaded.") << endmsg; + warning << _("You cannot add a track or bus without a session already loaded.") << endmsg; return; } try { - if (disk) { - if ((route = session->new_audio_track (input_channels, output_channels, mode)) == 0) { - error << _("could not create new audio track") << endmsg; + if (track) { + tracks = session->new_audio_track (input_channels, output_channels, mode, how_many); + + if (tracks.size() != how_many) { + if (how_many == 1) { + error << _("could not create a new audio track") << endmsg; + } else { + error << string_compose (_("could only create %1 of %2 new audio %3"), + tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg; + } } + } else { - if ((route = session->new_audio_route (input_channels, output_channels)) == 0) { - error << _("could not create new audio bus") << endmsg; + + routes = session->new_audio_route (input_channels, output_channels, how_many); + + if (routes.size() != how_many) { + if (how_many == 1) { + error << _("could not create a new audio track") << endmsg; + } else { + error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg; + } } } @@ -936,6 +1108,7 @@ ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t o } catch (...) { + cerr << "About to complain about JACK\n"; MessageDialog msg (*editor, _("There are insufficient JACK ports available\n\ to create a new track or bus.\n\ @@ -946,17 +1119,13 @@ restart JACK with more ports.")); } void -ARDOUR_UI::diskstream_added (Diskstream* ds) +ARDOUR_UI::do_transport_locate (nframes_t new_position) { -} - -void -ARDOUR_UI::do_transport_locate (jack_nframes_t new_position) -{ - jack_nframes_t _preroll; + nframes_t _preroll = 0; if (session) { - _preroll = session->convert_to_frames_at (new_position, session->preroll); + // XXX CONFIG_CHANGE FIX - requires AnyTime handling + // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll()); if (new_position > _preroll) { new_position -= _preroll; @@ -980,7 +1149,7 @@ ARDOUR_UI::transport_goto_start () */ if (editor) { - editor->reposition_x_origin (session->current_start_frame()); + editor->reset_x_origin (session->current_start_frame()); } } } @@ -997,7 +1166,7 @@ ARDOUR_UI::transport_goto_zero () */ if (editor) { - editor->reposition_x_origin (0); + editor->reset_x_origin (0); } } } @@ -1006,7 +1175,7 @@ void ARDOUR_UI::transport_goto_end () { if (session) { - jack_nframes_t frame = session->current_end_frame(); + nframes_t frame = session->current_end_frame(); session->request_locate (frame); /* force displayed area in editor to start no matter @@ -1014,7 +1183,7 @@ ARDOUR_UI::transport_goto_end () */ if (editor) { - editor->reposition_x_origin (frame); + editor->reset_x_origin (frame); } } } @@ -1031,8 +1200,8 @@ ARDOUR_UI::transport_stop () return; } - if (session->get_auto_loop()) { - session->request_auto_loop (false); + if (session->get_play_loop ()) { + session->request_play_loop (false); } session->request_stop (); @@ -1061,8 +1230,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; } @@ -1086,13 +1254,13 @@ ARDOUR_UI::transport_roll () rolling = session->transport_rolling (); - if (session->get_auto_loop()) { - session->request_auto_loop (false); - auto_loop_button.set_active (false); - roll_button.set_active (true); + if (session->get_play_loop()) { + session->request_play_loop (false); + auto_loop_button.set_visual_state (1); + roll_button.set_visual_state (1); } else if (session->get_play_range ()) { session->request_play_range (false); - play_selection_button.set_active (false); + play_selection_button.set_visual_state (0); } else if (rolling) { session->request_locate (session->last_transport_start(), true); } @@ -1104,7 +1272,7 @@ void ARDOUR_UI::transport_loop() { if (session) { - if (session->get_auto_loop()) { + if (session->get_play_loop()) { if (session->transport_rolling()) { Location * looploc = session->locations()->auto_loop_location(); if (looploc) { @@ -1113,7 +1281,7 @@ ARDOUR_UI::transport_loop() } } else { - session->request_auto_loop (true); + session->request_play_loop (true); } } } @@ -1200,7 +1368,7 @@ ARDOUR_UI::toggle_record_enable (uint32_t dstream) Track* t; if ((t = dynamic_cast(r.get())) != 0) { - t->diskstream().set_record_enabled (!t->diskstream().record_enabled()); + t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled()); } } if (session == 0) { @@ -1230,24 +1398,6 @@ ARDOUR_UI::map_transport_state () } } -void -ARDOUR_UI::allow_local_only () -{ - -} - -void -ARDOUR_UI::allow_mmc_only () -{ - -} - -void -ARDOUR_UI::allow_mmc_and_local () -{ - -} - void ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg) { @@ -1263,13 +1413,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 @@ -1298,14 +1490,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") @@ -1327,14 +1511,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; @@ -1343,7 +1519,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 @@ -1381,7 +1559,7 @@ ARDOUR_UI::_blink (void *arg) void ARDOUR_UI::blink () { - Blink (blink_on = !blink_on); /* EMIT_SIGNAL */ + Blink (blink_on = !blink_on); /* EMIT_SIGNAL */ } void @@ -1393,7 +1571,7 @@ ARDOUR_UI::start_blinking () if (blink_timeout_tag < 0) { blink_on = false; - blink_timeout_tag = gtk_timeout_add (240, _blink, this); + blink_timeout_tag = g_timeout_add (240, _blink, this); } } @@ -1401,7 +1579,7 @@ void ARDOUR_UI::stop_blinking () { if (blink_timeout_tag >= 0) { - gtk_timeout_remove (blink_timeout_tag); + g_source_remove (blink_timeout_tag); blink_timeout_tag = -1; } } @@ -1413,7 +1591,7 @@ ARDOUR_UI::name_io_setup (AudioEngine& engine, bool in) { if (in) { - if (io.n_inputs() == 0) { + if (io.n_inputs().get_total() == 0) { buf = _("none"); return; } @@ -1432,7 +1610,7 @@ ARDOUR_UI::name_io_setup (AudioEngine& engine, } else { - if (io.n_outputs() == 0) { + if (io.n_outputs().get_total() == 0) { buf = _("none"); return; } @@ -1451,23 +1629,25 @@ ARDOUR_UI::name_io_setup (AudioEngine& engine, } } +/** Ask the user for the name of a new shapshot and then take it. + */ void 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: @@ -1574,18 +1754,18 @@ ARDOUR_UI::transport_rec_enable_blink (bool onoff) switch (session->record_status()) { case Session::Enabled: if (onoff) { - rec_button.set_state (1); + rec_button.set_visual_state (2); } else { - rec_button.set_state (0); + rec_button.set_visual_state (0); } break; case Session::Recording: - rec_button.set_state (2); + rec_button.set_visual_state (1); break; default: - rec_button.set_state (0); + rec_button.set_visual_state (0); break; } } @@ -1598,12 +1778,6 @@ ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window) return TRUE; } -void -ARDOUR_UI::start_keyboard_prefix () -{ - keyboard->start_prefix(); -} - void ARDOUR_UI::save_template () @@ -1615,7 +1789,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: @@ -1631,126 +1804,227 @@ ARDOUR_UI::save_template () } } -void -ARDOUR_UI::new_session (bool startup, std::string predetermined_path) +bool +ARDOUR_UI::new_session (std::string predetermined_path) { - m_new_session_dialog->show(); - m_new_session_dialog->set_modal(true); - m_new_session_dialog->set_name(predetermined_path); - m_new_session_dialog->reset_recent(); + string session_name; + string session_path; + + if (!check_audioengine()) { + return false; + } + + int response = Gtk::RESPONSE_NONE; - int response = Gtk::RESPONSE_CANCEL; + new_session_dialog->set_modal(true); + new_session_dialog->set_name (predetermined_path); + new_session_dialog->reset_recent(); + new_session_dialog->show(); + new_session_dialog->set_current_page (0); do { - response = m_new_session_dialog->run (); - if(response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) { - quit(); - return; + response = new_session_dialog->run (); - } else if (response == Gtk::RESPONSE_NONE) { - /* Clear was pressed */ - m_new_session_dialog->reset(); + if (!check_audioengine()) { + new_session_dialog->hide (); + return false; + } + + _session_is_new = false; - } else if (response == Gtk::RESPONSE_YES) { - /* YES == OPEN, but there's no enum for that */ - std::string session_name = m_new_session_dialog->session_name(); - std::string session_path = m_new_session_dialog->session_folder(); - load_session (session_path, session_name); + if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) { + if (!session) { + quit(); + } + new_session_dialog->hide (); + return false; - } else if (response == Gtk::RESPONSE_OK) { - if (m_new_session_dialog->get_current_page() == 1) { + } else if (response == Gtk::RESPONSE_NONE) { - /* XXX this is a bit of a hack.. - i really want the new sesion dialog to return RESPONSE_YES - if we're on page 1 (the load page) - Unfortunately i can't see how atm.. - */ - std::string session_name = m_new_session_dialog->session_name(); - std::string session_path = m_new_session_dialog->session_folder(); - load_session (session_path, session_name); + /* Clear was pressed */ + new_session_dialog->reset(); - } else { + } else if (response == Gtk::RESPONSE_YES) { - _session_is_new = true; - - std::string session_name = m_new_session_dialog->session_name(); - std::string session_path = m_new_session_dialog->session_folder(); - + /* YES == OPEN, but there's no enum for that */ - //XXX This is needed because session constructor wants a - //non-existant path. hopefully this will be fixed at some point. + session_name = new_session_dialog->session_name(); - session_path = Glib::build_filename(session_path, session_name); + if (session_name.empty()) { + response = Gtk::RESPONSE_NONE; + continue; + } + + if (session_name[0] == '/' || + (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') || + (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) { + load_session (Glib::path_get_dirname (session_name), session_name); + } else { + session_path = new_session_dialog->session_folder(); + load_session (session_path, session_name); + } - std::string template_name = m_new_session_dialog->session_template_name(); + } else if (response == Gtk::RESPONSE_OK) { + + session_name = new_session_dialog->session_name(); - if (m_new_session_dialog->use_session_template()) { + if (new_session_dialog->get_current_page() == 1) { + + /* XXX this is a bit of a hack.. + i really want the new sesion dialog to return RESPONSE_YES + if we're on page 1 (the load page) + Unfortunately i can't see how atm.. + */ - load_session (session_path, session_name, &template_name); - - } else { - - uint32_t cchns; - uint32_t mchns; - Session::AutoConnectOption iconnect; - Session::AutoConnectOption oconnect; + if (session_name.empty()) { + response = Gtk::RESPONSE_NONE; + continue; + } - if (m_new_session_dialog->create_control_bus()) { - cchns = (uint32_t) m_new_session_dialog->control_channel_count(); + if (session_name[0] == '/' || + (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') || + (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) { + load_session (Glib::path_get_dirname (session_name), session_name); } else { - cchns = 0; + session_path = new_session_dialog->session_folder(); + load_session (session_path, session_name); } - - if (m_new_session_dialog->create_master_bus()) { - mchns = (uint32_t) m_new_session_dialog->master_channel_count(); + + } else { + + if (session_name.empty()) { + response = Gtk::RESPONSE_NONE; + continue; + } + + if (session_name[0] == '/' || + (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') || + (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) { + + session_path = Glib::path_get_dirname (session_name); + session_name = Glib::path_get_basename (session_name); + } else { - mchns = 0; + + session_path = new_session_dialog->session_folder(); + } - if (m_new_session_dialog->connect_inputs()) { - iconnect = Session::AutoConnectPhysical; - } else { - iconnect = Session::AutoConnectOption (0); - } + //XXX This is needed because session constructor wants a + //non-existant path. hopefully this will be fixed at some point. - /// @todo some minor tweaks. + 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; - if (m_new_session_dialog->connect_outs_to_master()) { - oconnect = Session::AutoConnectMaster; - } else if (m_new_session_dialog->connect_outs_to_physical()) { - oconnect = Session::AutoConnectPhysical; + std::string template_name = new_session_dialog->session_template_name(); + + if (new_session_dialog->use_session_template()) { + + load_session (session_path, session_name, &template_name); + } else { - oconnect = Session::AutoConnectOption (0); - } - - uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count(); - uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count(); - - build_session (session_path, - session_name, - cchns, - mchns, - iconnect, - oconnect, - nphysin, - nphysout, - engine->frame_rate() * 60 * 5); + + uint32_t cchns; + uint32_t mchns; + AutoConnectOption iconnect; + AutoConnectOption oconnect; + + if (new_session_dialog->create_control_bus()) { + cchns = (uint32_t) new_session_dialog->control_channel_count(); + } else { + cchns = 0; + } + + if (new_session_dialog->create_master_bus()) { + mchns = (uint32_t) new_session_dialog->master_channel_count(); + } else { + mchns = 0; + } + + if (new_session_dialog->connect_inputs()) { + iconnect = AutoConnectPhysical; + } else { + iconnect = AutoConnectOption (0); + } + + /// @todo some minor tweaks. + + if (new_session_dialog->connect_outs_to_master()) { + oconnect = AutoConnectMaster; + } else if (new_session_dialog->connect_outs_to_physical()) { + oconnect = AutoConnectPhysical; + } else { + oconnect = AutoConnectOption (0); + } + + uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count(); + uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count(); + + if (build_session (session_path, + session_name, + cchns, + mchns, + iconnect, + oconnect, + nphysin, + nphysout, + engine->frame_rate() * 60 * 5)) { + + response = Gtk::RESPONSE_NONE; + new_session_dialog->reset (); + continue; + } + } } - } } } while (response == Gtk::RESPONSE_NONE); - m_new_session_dialog->hide(); - show(); + done: + show(); + new_session_dialog->get_window()->set_cursor(); + new_session_dialog->hide(); + return true; } void ARDOUR_UI::close_session() { - unload_session(); - new_session (); + if (!check_audioengine()) { + return; + } + + unload_session(); + new_session (); } int @@ -1759,6 +2033,11 @@ ARDOUR_UI::load_session (const string & path, const string & snap_name, string* Session *new_session; int x; session_loaded = false; + + if (!check_audioengine()) { + return -1; + } + x = unload_session (); if (x < 0) { @@ -1770,9 +2049,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; } @@ -1789,40 +2067,41 @@ This prevents the session from being loaded.")); connect_to_session (new_session); - //if (engine->running()) { - //mixer->show_window(); - //} + 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; + editor->edit_cursor_position (true); + return 0; } int ARDOUR_UI::build_session (const string & path, const string & snap_name, uint32_t control_channels, uint32_t master_channels, - Session::AutoConnectOption input_connect, - Session::AutoConnectOption output_connect, + AutoConnectOption input_connect, + AutoConnectOption output_connect, uint32_t nphysin, uint32_t nphysout, - jack_nframes_t initial_length) + nframes_t initial_length) { Session *new_session; int x; + if (!check_audioengine()) { + return -1; + } + session_loaded = false; + x = unload_session (); + if (x < 0) { return -1; } else if (x > 0) { @@ -1838,15 +2117,13 @@ ARDOUR_UI::build_session (const string & path, const string & snap_name, catch (...) { - error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg; + MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path)); + msg.run (); return -1; } connect_to_session (new_session); - //if (engine->running()) { - //mixer->show_window(); - //} session_loaded = true; return 0; } @@ -1856,15 +2133,12 @@ ARDOUR_UI::show () { if (editor) { editor->show_window (); - shown_flag = true; - } + + if (!shown_flag) { + editor->present (); + } - if (session && mixer) { - // mixer->show_window (); - } - - if (about) { - about->present (); + shown_flag = true; } } @@ -1873,15 +2147,24 @@ 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 ARDOUR_UI::hide_splash () { if (about) { - // about->hide(); + about->get_window()->set_cursor (); + about->hide(); } } @@ -1897,7 +2180,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\ @@ -2007,7 +2290,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()) { @@ -2021,9 +2304,17 @@ After cleanup, unused audio files will be moved to a \ editor->prepare_for_cleanup (); + /* do not allow flush until a session is reloaded */ + + Glib::RefPtr act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket")); + if (act) { + act->set_sensitive (false); + } + if (session->cleanup_sources (rep)) { return; } + checker.hide(); display_cleanup_results (rep, _("cleaned files"), @@ -2035,6 +2326,9 @@ Flushing the wastebasket will \n\ release an additional\n\ %4 %5bytes of disk space.\n" )); + + + } void @@ -2059,7 +2353,7 @@ releasing %4 %5bytes of disk space")); } void -ARDOUR_UI::add_route () +ARDOUR_UI::add_route (Gtk::Window* float_window) { int count; @@ -2069,7 +2363,9 @@ ARDOUR_UI::add_route () if (add_route_dialog == 0) { add_route_dialog = new AddRouteDialog; - editor->ensure_float (*add_route_dialog); + if (float_window) { + add_route_dialog->set_transient_for (*float_window); + } } if (add_route_dialog->is_visible()) { @@ -2078,15 +2374,15 @@ ARDOUR_UI::add_route () } ResponseType r = (ResponseType) add_route_dialog->run (); - + add_route_dialog->hide(); switch (r) { - case RESPONSE_ACCEPT: - break; - default: - return; - break; + case RESPONSE_ACCEPT: + break; + default: + return; + break; } if ((count = add_route_dialog->count()) <= 0) { @@ -2098,30 +2394,30 @@ ARDOUR_UI::add_route () string name_template = add_route_dialog->name_template (); bool track = add_route_dialog->track (); - Session::AutoConnectOption oac = session->get_output_auto_connect(); + AutoConnectOption oac = Config->get_output_auto_connect(); - if (oac & Session::AutoConnectMaster) { - output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan); + if (oac & AutoConnectMaster) { + output_chan = (session->master_out() ? session->master_out()->n_inputs().get(DataType::AUDIO) : input_chan); } else { output_chan = input_chan; } /* XXX do something with name template */ - while (count) { - if (track && add_route_dialog->midi()) { - session_add_midi_track(); - } else if (add_route_dialog->midi()) { - session_add_midi_bus(); - } else if (track) { - session_add_audio_track (input_chan, output_chan, add_route_dialog->mode()); - } else { - session_add_audio_bus (input_chan, output_chan); + if (add_route_dialog->type() == ARDOUR::DataType::MIDI) { + if (track) { + session_add_midi_track(count); + } else { + MessageDialog msg (*editor, + _("Sorry, MIDI Busses are not supported at this time.")); + msg.run (); + //session_add_midi_bus(); } - --count; - - while (Main::events_pending()) { - Main::iteration (); + } else { + if (track) { + session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count); + } else { + session_add_audio_bus (input_chan, output_chan, count); } } } @@ -2184,33 +2480,21 @@ 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) { - delete *i; - } - - delete deletion_list; -} - void ARDOUR_UI::disk_overrun_handler () { - ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler)); + ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler)); - if (!have_disk_overrun_displayed) { - have_disk_overrun_displayed = true; - MessageDialog msg (*editor, X_("diskrate dialog"), _("\ + if (!have_disk_speed_dialog_displayed) { + have_disk_speed_dialog_displayed = true; + MessageDialog* msg = new MessageDialog (*editor, _("\ The disk system on your computer\n\ was not able to keep up with Ardour.\n\ \n\ Specifically, it failed to write data to disk\n\ quickly enough to keep up with recording.\n")); - msg.run (); - have_disk_overrun_displayed = false; + msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg)); + msg->show_all (); } } @@ -2219,29 +2503,24 @@ ARDOUR_UI::disk_underrun_handler () { ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler)); - if (!have_disk_underrun_displayed) { - have_disk_underrun_displayed = true; - MessageDialog msg (*editor, - (_("The disk system on your computer\n\ + if (!have_disk_speed_dialog_displayed) { + have_disk_speed_dialog_displayed = true; + MessageDialog* msg = new MessageDialog (*editor, + _("The disk system on your computer\n\ was not able to keep up with Ardour.\n\ \n\ Specifically, it failed to read data from disk\n\ -quickly enough to keep up with playback.\n"))); - msg.run (); - have_disk_underrun_displayed = false; +quickly enough to keep up with playback.\n")); + msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg)); + msg->show_all (); } } void -ARDOUR_UI::disk_underrun_message_gone () -{ - have_disk_underrun_displayed = false; -} - -void -ARDOUR_UI::disk_overrun_message_gone () +ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg) { - have_disk_underrun_displayed = false; + have_disk_speed_dialog_displayed = false; + delete msg; } int @@ -2298,13 +2577,6 @@ ARDOUR_UI::reconnect_to_jack () } } -void -ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes) -{ - engine->request_buffer_size (nframes); - update_sample_rate (0); -} - int ARDOUR_UI::cmdline_new_session (string path) { @@ -2319,18 +2591,32 @@ 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 */ } void -ARDOUR_UI::set_native_file_header_format (HeaderFormat hf) +ARDOUR_UI::use_config () { Glib::RefPtr act; - - switch (hf) { + + switch (Config->get_native_file_data_format ()) { + case FormatFloat: + act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat")); + break; + case FormatInt24: + act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit")); + break; + } + + if (act) { + Glib::RefPtr ract = Glib::RefPtr::cast_dynamic(act); + ract->set_active (); + } + + switch (Config->get_native_file_header_format ()) { case BWF: act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF")); break; @@ -2356,86 +2642,194 @@ ARDOUR_UI::set_native_file_header_format (HeaderFormat hf) if (act) { Glib::RefPtr ract = Glib::RefPtr::cast_dynamic(act); - if (ract && ract->get_active() && Config->get_native_file_header_format() != hf) { - Config->set_native_file_header_format (hf); - if (session) { - session->reset_native_file_format (); - } - } + ract->set_active (); + } + + XMLNode* node = Config->extra_xml (X_("TransportControllables")); + if (node) { + set_transport_controllable_state (*node); } } void -ARDOUR_UI::set_native_file_data_format (SampleFormat sf) +ARDOUR_UI::update_transport_clocks (nframes_t pos) { - Glib::RefPtr act; - - switch (sf) { - case FormatFloat: - act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat")); + 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; - case FormatInt24: - act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit")); + default: + big_clock.set_widget_name ("BigClockNonRecording"); break; } +} - if (act) { - Glib::RefPtr ract = Glib::RefPtr::cast_dynamic(act); +void +ARDOUR_UI::set_keybindings_path (string path) +{ + keybindings_path = path; +} - if (ract && ract->get_active() && Config->get_native_file_data_format() != sf) { - Config->set_native_file_data_format (sf); - if (session) { - session->reset_native_file_format (); - } - } +void +ARDOUR_UI::save_keybindings () +{ + if (can_save_keybindings) { + AccelMap::save (keybindings_path); + } +} + +bool +ARDOUR_UI::first_idle () +{ + if (session) { + session->allow_auto_play (true); } + can_save_keybindings = true; + return false; } void -ARDOUR_UI::use_config () +ARDOUR_UI::store_clock_modes () { - Glib::RefPtr act; + XMLNode* node = new XMLNode(X_("ClockModes")); - switch (Config->get_native_file_data_format ()) { - case FormatFloat: - act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat")); + 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 (); +} + + + +ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp) + : Controllable (name), ui (u), type(tp) +{ + +} + +void +ARDOUR_UI::TransportControllable::set_value (float val) +{ + if (type == ShuttleControl) { + double fract; + + if (val == 0.5f) { + fract = 0.0; + } else { + if (val < 0.5f) { + fract = -((0.5f - val)/0.5f); + } else { + fract = ((val - 0.5f)/0.5f); + } + } + + ui.set_shuttle_fract (fract); + return; + } + + if (val < 0.5f) { + /* do nothing: these are radio-style actions */ + return; + } + + char *action = 0; + + switch (type) { + case Roll: + action = X_("Roll"); break; - case FormatInt24: - act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit")); + case Stop: + action = X_("Stop"); + break; + case GotoStart: + action = X_("Goto Start"); + break; + case GotoEnd: + action = X_("Goto End"); + break; + case AutoLoop: + action = X_("Loop"); + break; + case PlaySelection: + action = X_("Play Selection"); + break; + case RecordEnable: + action = X_("Record"); + break; + default: break; } + if (action == 0) { + return; + } + + Glib::RefPtr act = ActionManager::get_action ("Transport", action); + if (act) { - Glib::RefPtr ract = Glib::RefPtr::cast_dynamic(act); - ract->set_active (); - } + act->activate (); + } +} - switch (Config->get_native_file_header_format ()) { - case BWF: - act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF")); +float +ARDOUR_UI::TransportControllable::get_value (void) const +{ + float val = 0.0f; + + switch (type) { + case Roll: break; - case WAVE: - act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE")); + case Stop: break; - case WAVE64: - act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64")); + case GotoStart: break; - case iXML: - act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML")); + case GotoEnd: break; - case RF64: - act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64")); + case AutoLoop: break; - case CAF: - act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF")); + case PlaySelection: break; - case AIFF: - act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF")); + case RecordEnable: + break; + case ShuttleControl: + break; + default: break; } - if (act) { - Glib::RefPtr ract = Glib::RefPtr::cast_dynamic(act); - ract->set_active (); - } + return val; +} + +void +ARDOUR_UI::TransportControllable::set_id (const string& str) +{ + _id = str; +} + +void +ARDOUR_UI::setup_profile () +{ + if (gdk_screen_width() < 1200) { + Profile->set_small_screen (); + } }