Fix insertion of processors at the point at which the processor menu was opened;...
[ardour.git] / gtk2_ardour / engine_dialog.cc
index 7d8f29cce46c3c5f2a11b27e2033c03fa4b97884..d6e6a52f4606e2cc6e5168b1f78b255a3ed9dc59 100644 (file)
@@ -1,11 +1,34 @@
+/*
+    Copyright (C) 2010 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.
+
+*/
+
 #include <vector>
 #include <cmath>
 #include <fstream>
 #include <map>
 
 #include <vector>
 #include <cmath>
 #include <fstream>
 #include <map>
 
+#include <boost/scoped_ptr.hpp>
+
 #include <glibmm.h>
 #include <gtkmm/messagedialog.h>
 #include <glibmm.h>
 #include <gtkmm/messagedialog.h>
-#include <pbd/xml++.h>
+
+#include "pbd/epa.h"
+#include "pbd/xml++.h"
 
 #ifdef __APPLE__
 #include <CoreAudio/CoreAudio.h>
 
 #ifdef __APPLE__
 #include <CoreAudio/CoreAudio.h>
 #include <alsa/asoundlib.h>
 #endif
 
 #include <alsa/asoundlib.h>
 #endif
 
-#include <ardour/profile.h>
+#include "ardour/profile.h"
 #include <jack/jack.h>
 
 #include <gtkmm/stock.h>
 #include <gtkmm2ext/utils.h>
 
 #include <jack/jack.h>
 
 #include <gtkmm/stock.h>
 #include <gtkmm2ext/utils.h>
 
-#include <pbd/convert.h>
-#include <pbd/error.h>
-#include <pbd/pathscanner.h>
+#include "pbd/convert.h"
+#include "pbd/error.h"
+#include "pbd/pathscanner.h"
 
 #ifdef __APPLE
 #include <CFBundle.h>
 
 #ifdef __APPLE
 #include <CFBundle.h>
@@ -46,6 +69,10 @@ EngineControl::EngineControl ()
          priority_spinner (priority_adjustment),
          ports_adjustment (128, 8, 1024, 1, 16),
          ports_spinner (ports_adjustment),
          priority_spinner (priority_adjustment),
          ports_adjustment (128, 8, 1024, 1, 16),
          ports_spinner (ports_adjustment),
+         input_latency_adjustment (0, 0, 99999, 1),
+         input_latency (input_latency_adjustment),
+         output_latency_adjustment (0, 0, 99999, 1),
+         output_latency (output_latency_adjustment),
          realtime_button (_("Realtime")),
          no_memory_lock_button (_("Do not lock memory")),
          unlock_memory_button (_("Unlock memory")),
          realtime_button (_("Realtime")),
          no_memory_lock_button (_("Do not lock memory")),
          unlock_memory_button (_("Unlock memory")),
@@ -65,7 +92,7 @@ EngineControl::EngineControl ()
          basic_packer (8, 2),
          options_packer (14, 2),
          device_packer (6, 2)
          basic_packer (8, 2),
          options_packer (14, 2),
          device_packer (6, 2)
-#endif   
+#endif
 {
        using namespace Notebook_Helpers;
        Label* label;
 {
        using namespace Notebook_Helpers;
        Label* label;
@@ -115,6 +142,7 @@ EngineControl::EngineControl ()
 #else
        strings.push_back (X_("ALSA"));
        strings.push_back (X_("OSS"));
 #else
        strings.push_back (X_("ALSA"));
        strings.push_back (X_("OSS"));
+       strings.push_back (X_("FreeBoB"));
        strings.push_back (X_("FFADO"));
 #endif
        strings.push_back (X_("NetJACK"));
        strings.push_back (X_("FFADO"));
 #endif
        strings.push_back (X_("NetJACK"));
@@ -122,73 +150,86 @@ EngineControl::EngineControl ()
        set_popdown_strings (driver_combo, strings);
        driver_combo.set_active_text (strings.front());
 
        set_popdown_strings (driver_combo, strings);
        driver_combo.set_active_text (strings.front());
 
-       driver_combo.signal_changed().connect (mem_fun (*this, &EngineControl::driver_changed));
+       driver_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::driver_changed));
        driver_changed ();
 
        strings.clear ();
        driver_changed ();
 
        strings.clear ();
-       strings.push_back (_("Playback/Recording on 1 Device"));
-       strings.push_back (_("Playback/Recording on 2 Devices"));
+       strings.push_back (_("Playback/recording on 1 device"));
+       strings.push_back (_("Playback/recording on 2 devices"));
        strings.push_back (_("Playback only"));
        strings.push_back (_("Recording only"));
        set_popdown_strings (audio_mode_combo, strings);
        audio_mode_combo.set_active_text (strings.front());
 
        strings.push_back (_("Playback only"));
        strings.push_back (_("Recording only"));
        set_popdown_strings (audio_mode_combo, strings);
        audio_mode_combo.set_active_text (strings.front());
 
-       audio_mode_combo.signal_changed().connect (mem_fun (*this, &EngineControl::audio_mode_changed));
+       audio_mode_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::audio_mode_changed));
        audio_mode_changed ();
 
        audio_mode_changed ();
 
+       strings.clear ();
+       strings.push_back (_("None"));
+       strings.push_back (_("seq"));
+       strings.push_back (_("raw"));
+       set_popdown_strings (midi_driver_combo, strings);
+       midi_driver_combo.set_active_text (strings.front ());
+
        row = 0;
 
        row = 0;
 
-       label = manage (new Label (_("Driver")));
+       label = manage (new Label (_("Driver:")));
+       label->set_alignment (0, 0.5);
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (driver_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        row++;
 
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (driver_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        row++;
 
-       label = manage (new Label (_("Interface")));
+       label = manage (new Label (_("Interface:")));
+       label->set_alignment (0, 0.5);
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (interface_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        row++;
 
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (interface_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        row++;
 
-       label = manage (new Label (_("Sample Rate")));
+       label = manage (new Label (_("Sample rate:")));
+       label->set_alignment (0, 0.5);
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        row++;
 
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        row++;
 
-       label = manage (new Label (_("Buffer size")));
+       label = manage (new Label (_("Buffer size:")));
+       label->set_alignment (0, 0.5);
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (period_size_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        row++;
 
 #ifndef __APPLE__
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (period_size_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        row++;
 
 #ifndef __APPLE__
-       label = manage (new Label (_("Number of buffers")));
+       label = manage (new Label (_("Number of buffers:")));
+       label->set_alignment (0, 0.5);
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (periods_spinner, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        periods_spinner.set_value (2);
        row++;
 #endif
 
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (periods_spinner, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        periods_spinner.set_value (2);
        row++;
 #endif
 
-       label = manage (new Label (_("Approximate latency")));
-       label->set_alignment (0.0, 0.5);
+       label = manage (new Label (_("Approximate latency:")));
+       label->set_alignment (0, 0.5);
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (latency_label, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        row++;
 
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (latency_label, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        row++;
 
-       sample_rate_combo.signal_changed().connect (mem_fun (*this, &EngineControl::redisplay_latency));
-       periods_adjustment.signal_value_changed().connect (mem_fun (*this, &EngineControl::redisplay_latency));
-       period_size_combo.signal_changed().connect (mem_fun (*this, &EngineControl::redisplay_latency));
+       sample_rate_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::redisplay_latency));
+       periods_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &EngineControl::redisplay_latency));
+       period_size_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::redisplay_latency));
        redisplay_latency();
        row++;
        /* no audio mode with CoreAudio, its duplex or nuthin' */
 
 #ifndef __APPLE__
        redisplay_latency();
        row++;
        /* no audio mode with CoreAudio, its duplex or nuthin' */
 
 #ifndef __APPLE__
-       label = manage (new Label (_("Audio Mode")));
+       label = manage (new Label (_("Audio mode:")));
+       label->set_alignment (0, 0.5);
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (audio_mode_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        row++;
 #endif
 
        basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (audio_mode_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        row++;
 #endif
 
-       interface_combo.set_size_request (125, -1);
-       input_device_combo.set_size_request (125, -1);
-       output_device_combo.set_size_request (125, -1);
+       interface_combo.set_size_request (250, -1);
+       input_device_combo.set_size_request (250, -1);
+       output_device_combo.set_size_request (250, -1);
 
        /*
 
 
        /*
 
@@ -198,8 +239,8 @@ EngineControl::EngineControl ()
                stop_button.set_sensitive (false);
        }
 
                stop_button.set_sensitive (false);
        }
 
-       start_button.signal_clicked().connect (mem_fun (*this, &EngineControl::start_engine));
-       stop_button.signal_clicked().connect (mem_fun (*this, &EngineControl::start_engine));
+       start_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::start_engine));
+       stop_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::start_engine));
        */
 
        button_box.pack_start (start_button, false, false);
        */
 
        button_box.pack_start (start_button, false, false);
@@ -215,9 +256,12 @@ EngineControl::EngineControl ()
        options_packer.attach (realtime_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
 
        options_packer.attach (realtime_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
 
-       realtime_button.signal_toggled().connect (mem_fun (*this, &EngineControl::realtime_changed));
+       realtime_button.set_active (true);
+       realtime_button.signal_toggled().connect (sigc::mem_fun (*this, &EngineControl::realtime_changed));
        realtime_changed ();
 
        realtime_changed ();
 
+#if PROVIDE_TOO_MANY_OPTIONS
+
 #ifndef __APPLE__
        label = manage (new Label (_("Realtime Priority")));
        label->set_alignment (1.0, 0.5);
 #ifndef __APPLE__
        label = manage (new Label (_("Realtime Priority")));
        label->set_alignment (1.0, 0.5);
@@ -242,7 +286,7 @@ EngineControl::EngineControl ()
        ++row;
        options_packer.attach (verbose_output_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
        ++row;
        options_packer.attach (verbose_output_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
-#else 
+#else
        options_packer.attach (verbose_output_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
 #endif
        options_packer.attach (verbose_output_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
 #endif
@@ -262,15 +306,22 @@ EngineControl::EngineControl ()
        options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
 
        options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
 
-       label = manage (new Label (_("Number of ports")));
-       label->set_alignment (1.0, 0.5);
+#endif /* PROVIDE_TOO_MANY_OPTIONS */
+       label = manage (new Label (_("Number of ports:")));
+       label->set_alignment (0, 0.5);
        options_packer.attach (ports_spinner, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0));
        options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
 
        options_packer.attach (ports_spinner, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0));
        options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
 
+       label = manage (new Label (_("MIDI driver:")));
+       label->set_alignment (0, 0.5);
+       options_packer.attach (midi_driver_combo, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0));
+       options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
+
 #ifndef __APPLE__
 #ifndef __APPLE__
-       label = manage (new Label (_("Dither")));       
-       label->set_alignment (1.0, 0.5);
+       label = manage (new Label (_("Dither:")));
+       label->set_alignment (0, 0.5);
        options_packer.attach (dither_mode_combo, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0));
        options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
        options_packer.attach (dither_mode_combo, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0));
        options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
@@ -282,7 +333,7 @@ EngineControl::EngineControl ()
                fatal << _("No JACK server found anywhere on this system. Please install JACK and restart") << endmsg;
                /*NOTREACHED*/
        }
                fatal << _("No JACK server found anywhere on this system. Please install JACK and restart") << endmsg;
                /*NOTREACHED*/
        }
-       
+
        set_popdown_strings (serverpath_combo, server_strings);
        serverpath_combo.set_active_text (server_strings.front());
 
        set_popdown_strings (serverpath_combo, server_strings);
        serverpath_combo.set_active_text (server_strings.front());
 
@@ -300,36 +351,42 @@ EngineControl::EngineControl ()
        row = 0;
 
 #ifndef __APPLE__
        row = 0;
 
 #ifndef __APPLE__
-       label = manage (new Label (_("Input device")));
-       label->set_alignment (1.0, 0.5);
+       label = manage (new Label (_("Input device:")));
+       label->set_alignment (0, 0.5);
        device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (input_device_combo, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
        device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (input_device_combo, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
-       label = manage (new Label (_("Output device")));
-       label->set_alignment (1.0, 0.5);
+       label = manage (new Label (_("Output device:")));
+       label->set_alignment (0, 0.5);
        device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
-       device_packer.attach (output_device_combo, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);   
+       device_packer.attach (output_device_combo, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
 #endif
        ++row;
 #endif
-       label = manage (new Label (_("Input channels")));
-       label->set_alignment (1.0, 0.5);
+       label = manage (new Label (_("Input channels:")));
+       label->set_alignment (0, 0.5);
        device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (input_channels, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
        device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (input_channels, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
-       label = manage (new Label (_("Output channels")));
-       label->set_alignment (1.0, 0.5);
+       label = manage (new Label (_("Output channels:")));
+       label->set_alignment (0, 0.5);
        device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (output_channels, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
        device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (output_channels, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
-       label = manage (new Label (_("Hardware input latency (samples)")));
-       label->set_alignment (1.0, 0.5);
+       label = manage (new Label (_("Hardware input latency:")));
+       label->set_alignment (0, 0.5);
        device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (input_latency, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (input_latency, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+       label = manage (new Label (_("samples")));
+       label->set_alignment (0, 0.5);
+       device_packer.attach (*label, 2, 3, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
        ++row;
-       label = manage (new Label (_("Hardware output latency (samples)")));
-       label->set_alignment (1.0, 0.5);
+       label = manage (new Label (_("Hardware output latency:")));
+       label->set_alignment (0, 0.5);
        device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (output_latency, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (output_latency, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+       label = manage (new Label (_("samples")));
+       label->set_alignment (0, 0.5);
+       device_packer.attach (*label, 2, 3, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        ++row;
 
        basic_hbox.pack_start (basic_packer, false, false);
        ++row;
 
        basic_hbox.pack_start (basic_packer, false, false);
@@ -358,33 +415,36 @@ EngineControl::build_command_line (vector<string>& cmd)
 {
        string str;
        string driver;
 {
        string str;
        string driver;
-       bool using_oss = false;
        bool using_alsa = false;
        bool using_coreaudio = false;
        bool using_alsa = false;
        bool using_coreaudio = false;
-       bool using_netjack = false;
-       bool using_ffado = false;
        bool using_dummy = false;
        bool using_dummy = false;
+       bool using_ffado = false;
 
        /* first, path to jackd */
 
        cmd.push_back (serverpath_combo.get_active_text ());
 
        /* first, path to jackd */
 
        cmd.push_back (serverpath_combo.get_active_text ());
-       
+
        /* now jackd arguments */
 
        str = timeout_combo.get_active_text ();
        /* now jackd arguments */
 
        str = timeout_combo.get_active_text ();
+
        if (str != _("Ignore")) {
        if (str != _("Ignore")) {
+
                double secs = 0;
                uint32_t msecs;
                double secs = 0;
                uint32_t msecs;
-               atof (str);
+               secs = atof (str);
                msecs = (uint32_t) floor (secs * 1000.0);
                msecs = (uint32_t) floor (secs * 1000.0);
-               cmd.push_back ("-t");
-               cmd.push_back (to_string (msecs, std::dec));
+
+               if (msecs > 0) {
+                       cmd.push_back ("-t");
+                       cmd.push_back (to_string (msecs, std::dec));
+               }
        }
 
        if (no_memory_lock_button.get_active()) {
                cmd.push_back ("-m"); /* no munlock */
        }
        }
 
        if (no_memory_lock_button.get_active()) {
                cmd.push_back ("-m"); /* no munlock */
        }
-       
+
        cmd.push_back ("-p"); /* port max */
        cmd.push_back (to_string ((uint32_t) floor (ports_spinner.get_value()), std::dec));
 
        cmd.push_back ("-p"); /* port max */
        cmd.push_back (to_string ((uint32_t) floor (ports_spinner.get_value()), std::dec));
 
@@ -392,6 +452,8 @@ EngineControl::build_command_line (vector<string>& cmd)
                cmd.push_back ("-R");
                cmd.push_back ("-P");
                cmd.push_back (to_string ((uint32_t) floor (priority_spinner.get_value()), std::dec));
                cmd.push_back ("-R");
                cmd.push_back ("-P");
                cmd.push_back (to_string ((uint32_t) floor (priority_spinner.get_value()), std::dec));
+       } else {
+               cmd.push_back ("-r"); /* override jackd's default --realtime */
        }
 
        if (unlock_memory_button.get_active()) {
        }
 
        if (unlock_memory_button.get_active()) {
@@ -401,7 +463,7 @@ EngineControl::build_command_line (vector<string>& cmd)
        if (verbose_output_button.get_active()) {
                cmd.push_back ("-v");
        }
        if (verbose_output_button.get_active()) {
                cmd.push_back ("-v");
        }
-       
+
        /* now add fixed arguments (not user-selectable) */
 
        cmd.push_back ("-T"); // temporary */
        /* now add fixed arguments (not user-selectable) */
 
        cmd.push_back ("-T"); // temporary */
@@ -411,31 +473,22 @@ EngineControl::build_command_line (vector<string>& cmd)
        cmd.push_back ("-d");
 
        driver = driver_combo.get_active_text ();
        cmd.push_back ("-d");
 
        driver = driver_combo.get_active_text ();
+
        if (driver == X_("ALSA")) {
                using_alsa = true;
                cmd.push_back ("alsa");
        } else if (driver == X_("OSS")) {
        if (driver == X_("ALSA")) {
                using_alsa = true;
                cmd.push_back ("alsa");
        } else if (driver == X_("OSS")) {
-               using_oss = true;
                cmd.push_back ("oss");
        } else if (driver == X_("CoreAudio")) {
                using_coreaudio = true;
                cmd.push_back ("coreaudio");
        } else if (driver == X_("NetJACK")) {
                cmd.push_back ("oss");
        } else if (driver == X_("CoreAudio")) {
                using_coreaudio = true;
                cmd.push_back ("coreaudio");
        } else if (driver == X_("NetJACK")) {
-               using_netjack = true;
                cmd.push_back ("netjack");
                cmd.push_back ("netjack");
+       } else if (driver == X_("FreeBoB")) {
+               cmd.push_back ("freebob");
        } else if (driver == X_("FFADO")) {
                using_ffado = true;
        } else if (driver == X_("FFADO")) {
                using_ffado = true;
-
-               /* do this until FFADO becomes the standard */
-
-               char* hack = getenv ("ARDOUR_FIREWIRE_DRIVER_NAME");
-
-               if (hack) {
-                       cmd.push_back (hack);
-               } else {
-                       cmd.push_back ("freebob");
-               }
-
+               cmd.push_back ("firewire");
        } else if ( driver == X_("Dummy")) {
                using_dummy = true;
                cmd.push_back ("dummy");
        } else if ( driver == X_("Dummy")) {
                using_dummy = true;
                cmd.push_back ("dummy");
@@ -445,13 +498,13 @@ EngineControl::build_command_line (vector<string>& cmd)
 
        if (!using_coreaudio) {
                str = audio_mode_combo.get_active_text();
 
        if (!using_coreaudio) {
                str = audio_mode_combo.get_active_text();
-               
+
                if (str == _("Playback/Recording on 1 Device")) {
                if (str == _("Playback/Recording on 1 Device")) {
-                       
+
                        /* relax */
                        /* relax */
-                       
+
                } else if (str == _("Playback/Recording on 2 Devices")) {
                } 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());
 
                        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());
 
@@ -462,6 +515,7 @@ EngineControl::build_command_line (vector<string>& cmd)
 
                        cmd.push_back ("-C");
                        cmd.push_back (input_device);
 
                        cmd.push_back ("-C");
                        cmd.push_back (input_device);
+
                        cmd.push_back ("-P");
                        cmd.push_back (output_device);
 
                        cmd.push_back ("-P");
                        cmd.push_back (output_device);
 
@@ -471,7 +525,7 @@ EngineControl::build_command_line (vector<string>& cmd)
                        cmd.push_back ("-C");
                }
 
                        cmd.push_back ("-C");
                }
 
-               if (! using_dummy ) {
+               if (!using_dummy) {
                        cmd.push_back ("-n");
                        cmd.push_back (to_string ((uint32_t) floor (periods_spinner.get_value()), std::dec));
                }
                        cmd.push_back ("-n");
                        cmd.push_back (to_string ((uint32_t) floor (periods_spinner.get_value()), std::dec));
                }
@@ -479,12 +533,29 @@ EngineControl::build_command_line (vector<string>& cmd)
 
        cmd.push_back ("-r");
        cmd.push_back (to_string (get_rate(), std::dec));
 
        cmd.push_back ("-r");
        cmd.push_back (to_string (get_rate(), std::dec));
-       
+
        cmd.push_back ("-p");
        cmd.push_back (period_size_combo.get_active_text());
 
        cmd.push_back ("-p");
        cmd.push_back (period_size_combo.get_active_text());
 
+       if (using_alsa || using_ffado || using_coreaudio) {
+
+               double val = input_latency_adjustment.get_value();
+
+                if (val) {
+                        cmd.push_back ("-I");
+                        cmd.push_back (to_string ((uint32_t) val, std::dec));
+                }
+
+                val = output_latency_adjustment.get_value();
+
+               if (val) {
+                        cmd.push_back ("-O");
+                        cmd.push_back (to_string ((uint32_t) val, std::dec));
+                }
+       }
+
        if (using_alsa) {
        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 (audio_mode_combo.get_active_text() != _("Playback/Recording on 2 Devices")) {
 
                        string device = get_device_name (driver, interface_combo.get_active_text());
@@ -495,12 +566,12 @@ EngineControl::build_command_line (vector<string>& cmd)
 
                        cmd.push_back ("-d");
                        cmd.push_back (device);
 
                        cmd.push_back ("-d");
                        cmd.push_back (device);
-               } 
+               }
 
                if (hw_meter_button.get_active()) {
                        cmd.push_back ("-M");
                }
 
                if (hw_meter_button.get_active()) {
                        cmd.push_back ("-M");
                }
-               
+
                if (hw_monitor_button.get_active()) {
                        cmd.push_back ("-H");
                }
                if (hw_monitor_button.get_active()) {
                        cmd.push_back ("-H");
                }
@@ -519,16 +590,23 @@ EngineControl::build_command_line (vector<string>& cmd)
                if (force16bit_button.get_active()) {
                        cmd.push_back ("-S");
                }
                if (force16bit_button.get_active()) {
                        cmd.push_back ("-S");
                }
-               
+
                if (soft_mode_button.get_active()) {
                        cmd.push_back ("-s");
                }
 
                if (soft_mode_button.get_active()) {
                        cmd.push_back ("-s");
                }
 
+               str = midi_driver_combo.get_active_text ();
+
+               if (str == _("seq")) {
+                       cmd.push_back ("-X seq");
+               } else if (str == _("raw")) {
+                       cmd.push_back ("-X raw");
+               }
        } else if (using_coreaudio) {
 
 #ifdef __APPLE__
                // note: older versions of the CoreAudio JACK backend use -n instead of -d here
        } else if (using_coreaudio) {
 
 #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 ();
                string device = get_device_name (driver, interface_combo.get_active_text());
                if (device.empty()) {
                        cmd.clear ();
@@ -539,16 +617,23 @@ EngineControl::build_command_line (vector<string>& cmd)
                cmd.push_back (device);
 #endif
 
                cmd.push_back (device);
 #endif
 
-       } else if (using_oss) {
-
-       } else if (using_netjack) {
-
        }
 }
 
 bool
 EngineControl::engine_running ()
 {
        }
 }
 
 bool
 EngineControl::engine_running ()
 {
+        EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
+        boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
+
+        /* revert all environment settings back to whatever they were when ardour started
+         */
+
+        if (global_epa) {
+                current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
+                global_epa->restore ();
+        }
+
        jack_status_t status;
        jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status);
 
        jack_status_t status;
        jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status);
 
@@ -566,12 +651,12 @@ EngineControl::setup_engine ()
        std::string cwd = "/tmp";
 
        build_command_line (args);
        std::string cwd = "/tmp";
 
        build_command_line (args);
-       
+
        if (args.empty()) {
                return 1; // try again
        }
 
        if (args.empty()) {
                return 1; // try again
        }
 
-       Glib::ustring jackdrc_path = Glib::get_home_dir();
+       std::string jackdrc_path = Glib::get_home_dir();
        jackdrc_path += "/.jackdrc";
 
        ofstream jackdrc (jackdrc_path.c_str());
        jackdrc_path += "/.jackdrc";
 
        ofstream jackdrc (jackdrc_path.c_str());
@@ -607,13 +692,15 @@ EngineControl::enumerate_devices (const string& driver)
        /* note: case matters for the map keys */
 
        if (driver == "CoreAudio") {
        /* note: case matters for the map keys */
 
        if (driver == "CoreAudio") {
-#ifdef __APPLE__               
+#ifdef __APPLE__
                devices[driver] = enumerate_coreaudio_devices ();
 #endif
 
 #ifndef __APPLE__
        } else if (driver == "ALSA") {
                devices[driver] = enumerate_alsa_devices ();
                devices[driver] = enumerate_coreaudio_devices ();
 #endif
 
 #ifndef __APPLE__
        } else if (driver == "ALSA") {
                devices[driver] = enumerate_alsa_devices ();
+       } else if (driver == "FreeBOB") {
+               devices[driver] = enumerate_freebob_devices ();
        } else if (driver == "FFADO") {
                devices[driver] = enumerate_ffado_devices ();
        } else if (driver == "OSS") {
        } else if (driver == "FFADO") {
                devices[driver] = enumerate_ffado_devices ();
        } else if (driver == "OSS") {
@@ -629,14 +716,14 @@ EngineControl::enumerate_devices (const string& driver)
 }
 
 #ifdef __APPLE__
 }
 
 #ifdef __APPLE__
-static OSStatus 
+static OSStatus
 getDeviceUIDFromID( AudioDeviceID id, char *name, size_t nsize)
 {
        UInt32 size = sizeof(CFStringRef);
        CFStringRef UI;
        OSStatus res = AudioDeviceGetProperty(id, 0, false,
                kAudioDevicePropertyDeviceUID, &size, &UI);
 getDeviceUIDFromID( AudioDeviceID id, char *name, size_t nsize)
 {
        UInt32 size = sizeof(CFStringRef);
        CFStringRef UI;
        OSStatus res = AudioDeviceGetProperty(id, 0, false,
                kAudioDevicePropertyDeviceUID, &size, &UI);
-       if (res == noErr) 
+       if (res == noErr)
                CFStringGetCString(UI,name,nsize,CFStringGetSystemEncoding());
        CFRelease(UI);
        return res;
                CFStringGetCString(UI,name,nsize,CFStringGetSystemEncoding());
        CFRelease(UI);
        return res;
@@ -646,7 +733,7 @@ vector<string>
 EngineControl::enumerate_coreaudio_devices ()
 {
        vector<string> devs;
 EngineControl::enumerate_coreaudio_devices ()
 {
        vector<string> devs;
-       
+
        // Find out how many Core Audio devices are there, if any...
        // (code snippet gently "borrowed" from St?hane Letz jackdmp;)
        OSStatus err;
        // Find out how many Core Audio devices are there, if any...
        // (code snippet gently "borrowed" from St?hane Letz jackdmp;)
        OSStatus err;
@@ -703,11 +790,11 @@ EngineControl::enumerate_coreaudio_devices ()
 
                                                // this returns the unique id for the device
                                                // that must be used on the commandline for jack
 
                                                // this returns the unique id for the device
                                                // that must be used on the commandline for jack
-                                               
+
                                                if (getDeviceUIDFromID(coreDeviceIDs[i], drivername, sizeof (drivername)) == noErr) {
                                                        devs.push_back (coreDeviceName);
                                                        backend_devs.push_back (drivername);
                                                if (getDeviceUIDFromID(coreDeviceIDs[i], drivername, sizeof (drivername)) == noErr) {
                                                        devs.push_back (coreDeviceName);
                                                        backend_devs.push_back (drivername);
-                                               } 
+                                               }
                                        }
                                }
                        }
                                        }
                                }
                        }
@@ -728,7 +815,7 @@ have no duplex audio device.\n\n\
 Alternatively, if you really want just playback\n\
 or recording but not both, start JACK before running\n\
 Ardour and choose the relevant device then."
 Alternatively, if you really want just playback\n\
 or recording but not both, start JACK before running\n\
 Ardour and choose the relevant device then."
-                                          ), 
+                                          ),
                                   true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
                msg.set_title (_("No suitable audio devices"));
                msg.set_position (Gtk::WIN_POS_MOUSE);
                                   true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
                msg.set_title (_("No suitable audio devices"));
                msg.set_position (Gtk::WIN_POS_MOUSE);
@@ -765,28 +852,11 @@ EngineControl::enumerate_alsa_devices ()
 
                        while (snd_ctl_pcm_next_device (handle, &device) >= 0 && device >= 0) {
 
 
                        while (snd_ctl_pcm_next_device (handle, &device) >= 0 && device >= 0) {
 
-                               bool have_playback = false;
-                               bool have_capture = false;
-
-                               /* find duplex devices only */
-
-                               snd_pcm_info_set_device (pcminfo, device);
-                               snd_pcm_info_set_subdevice (pcminfo, 0);
-                               snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_CAPTURE);
-
-                               if (snd_ctl_pcm_info (handle, pcminfo) >= 0) {
-                                       have_capture = true;
-                               }
-
                                snd_pcm_info_set_device (pcminfo, device);
                                snd_pcm_info_set_subdevice (pcminfo, 0);
                                snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_PLAYBACK);
 
                                if (snd_ctl_pcm_info (handle, pcminfo) >= 0) {
                                snd_pcm_info_set_device (pcminfo, device);
                                snd_pcm_info_set_subdevice (pcminfo, 0);
                                snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_PLAYBACK);
 
                                if (snd_ctl_pcm_info (handle, pcminfo) >= 0) {
-                                       have_playback = true;
-                               }
-
-                               if (have_capture && have_playback) {
                                        devs.push_back (snd_pcm_info_get_name (pcminfo));
                                        devname += ',';
                                        devname += to_string (device, std::dec);
                                        devs.push_back (snd_pcm_info_get_name (pcminfo));
                                        devname += ',';
                                        devname += to_string (device, std::dec);
@@ -815,6 +885,7 @@ EngineControl::enumerate_freebob_devices ()
        vector<string> devs;
        return devs;
 }
        vector<string> devs;
        return devs;
 }
+
 vector<string>
 EngineControl::enumerate_oss_devices ()
 {
 vector<string>
 EngineControl::enumerate_oss_devices ()
 {
@@ -840,22 +911,19 @@ EngineControl::driver_changed ()
 {
        string driver = driver_combo.get_active_text();
        string::size_type maxlen = 0;
 {
        string driver = driver_combo.get_active_text();
        string::size_type maxlen = 0;
-       int maxindex = -1;
        int n = 0;
 
        enumerate_devices (driver);
 
        vector<string>& strings = devices[driver];
 
        int n = 0;
 
        enumerate_devices (driver);
 
        vector<string>& strings = devices[driver];
 
-       if (strings.empty() && driver != "FFADO" && driver != "Dummy") {
-               error << string_compose (_("No devices found for driver \"%1\""), driver) << endmsg;
+       if (strings.empty() && driver != "FreeBoB" && driver != "FFADO" && driver != "Dummy") {
                return;
        }
                return;
        }
-       
+
        for (vector<string>::iterator i = strings.begin(); i != strings.end(); ++i, ++n) {
                if ((*i).length() > maxlen) {
                        maxlen = (*i).length();
        for (vector<string>::iterator i = strings.begin(); i != strings.end(); ++i, ++n) {
                if ((*i).length() > maxlen) {
                        maxlen = (*i).length();
-                       maxindex = n;
                }
        }
 
                }
        }
 
@@ -867,8 +935,8 @@ EngineControl::driver_changed ()
                interface_combo.set_active_text (strings.front());
                input_device_combo.set_active_text (strings.front());
                output_device_combo.set_active_text (strings.front());
                interface_combo.set_active_text (strings.front());
                input_device_combo.set_active_text (strings.front());
                output_device_combo.set_active_text (strings.front());
-       } 
-       
+       }
+
        if (driver == "ALSA") {
                soft_mode_button.set_sensitive (true);
                force16bit_button.set_sensitive (true);
        if (driver == "ALSA") {
                soft_mode_button.set_sensitive (true);
                force16bit_button.set_sensitive (true);
@@ -905,12 +973,13 @@ EngineControl::redisplay_latency ()
        snprintf (buf, sizeof(buf), "%.1fmsec", (periods * period_size) / (rate/1000.0));
 
        latency_label.set_text (buf);
        snprintf (buf, sizeof(buf), "%.1fmsec", (periods * period_size) / (rate/1000.0));
 
        latency_label.set_text (buf);
+       latency_label.set_alignment (0, 0.5);
 }
 
 void
 EngineControl::audio_mode_changed ()
 {
 }
 
 void
 EngineControl::audio_mode_changed ()
 {
-       Glib::ustring str = audio_mode_combo.get_active_text();
+       std::string str = audio_mode_combo.get_active_text();
 
        if (str == _("Playback/Recording on 1 Device")) {
                input_device_combo.set_sensitive (false);
 
        if (str == _("Playback/Recording on 1 Device")) {
                input_device_combo.set_sensitive (false);
@@ -925,7 +994,7 @@ EngineControl::audio_mode_changed ()
        }
 }
 
        }
 }
 
-static bool jack_server_filter(const string& str, void *arg)
+static bool jack_server_filter(const string& str, void */*arg*/)
 {
    return str == "jackd" || str == "jackdmp";
 }
 {
    return str == "jackd" || str == "jackdmp";
 }
@@ -937,23 +1006,23 @@ EngineControl::find_jack_servers (vector<string>& strings)
        /* this magic lets us finds the path to the OSX bundle, and then
           we infer JACK's location from there
        */
        /* this magic lets us finds the path to the OSX bundle, and then
           we infer JACK's location from there
        */
-       
+
        char execpath[MAXPATHLEN+1];
        uint32_t pathsz = sizeof (execpath);
 
        _NSGetExecutablePath (execpath, &pathsz);
        char execpath[MAXPATHLEN+1];
        uint32_t pathsz = sizeof (execpath);
 
        _NSGetExecutablePath (execpath, &pathsz);
-       
+
        string path (Glib::path_get_dirname (execpath));
        path += "/jackd";
 
        if (Glib::file_test (path, FILE_TEST_EXISTS)) {
                strings.push_back (path);
        string path (Glib::path_get_dirname (execpath));
        path += "/jackd";
 
        if (Glib::file_test (path, FILE_TEST_EXISTS)) {
                strings.push_back (path);
-       } 
+       }
 
        if (getenv ("ARDOUR_WITH_JACK")) {
                /* no other options - only use the JACK we supply */
                if (strings.empty()) {
 
        if (getenv ("ARDOUR_WITH_JACK")) {
                /* no other options - only use the JACK we supply */
                if (strings.empty()) {
-                       fatal << _("JACK appears to be missing from the Ardour bundle") << endmsg;
+                       fatal << string_compose (_("JACK appears to be missing from the %1 bundle"), PROGRAM_NAME) << endmsg;
                        /*NOTREACHED*/
                }
                return;
                        /*NOTREACHED*/
                }
                return;
@@ -961,7 +1030,7 @@ EngineControl::find_jack_servers (vector<string>& strings)
 #else
        string path;
 #endif
 #else
        string path;
 #endif
-       
+
        PathScanner scanner;
        vector<string *> *jack_servers;
        std::map<string,int> un;
        PathScanner scanner;
        vector<string *> *jack_servers;
        std::map<string,int> un;
@@ -997,12 +1066,12 @@ EngineControl::find_jack_servers (vector<string>& strings)
 #endif
 
        jack_servers = scanner (path, jack_server_filter, 0, false, true);
 #endif
 
        jack_servers = scanner (path, jack_server_filter, 0, false, true);
-       
+
        vector<string *>::iterator iter;
        vector<string *>::iterator iter;
-       
+
        for (iter = jack_servers->begin(); iter != jack_servers->end(); iter++) {
                string p = **iter;
        for (iter = jack_servers->begin(); iter != jack_servers->end(); iter++) {
                string p = **iter;
-               
+
                if (un[p]++ == 0) {
                        strings.push_back(p);
                }
                if (un[p]++ == 0) {
                        strings.push_back(p);
                }
@@ -1028,13 +1097,13 @@ EngineControl::get_device_name (const string& driver, const string& human_readab
        if (backend_devs.empty()) {
                return human_readable;
        }
        if (backend_devs.empty()) {
                return human_readable;
        }
-       
+
        for (i = devices[driver].begin(), n = backend_devs.begin(); i != devices[driver].end(); ++i, ++n) {
                if (human_readable == (*i)) {
                        return (*n);
                }
        }
        for (i = devices[driver].begin(), n = backend_devs.begin(); i != devices[driver].end(); ++i, ++n) {
                if (human_readable == (*i)) {
                        return (*n);
                }
        }
-       
+
        if (i == devices[driver].end()) {
                warning << string_compose (_("Audio device \"%1\" not known on this computer."), human_readable) << endmsg;
        }
        if (i == devices[driver].end()) {
                warning << string_compose (_("Audio device \"%1\" not known on this computer."), human_readable) << endmsg;
        }
@@ -1047,7 +1116,7 @@ EngineControl::get_state ()
 {
        XMLNode* root = new XMLNode ("AudioSetup");
        XMLNode* child;
 {
        XMLNode* root = new XMLNode ("AudioSetup");
        XMLNode* child;
-       Glib::ustring path;
+       std::string path;
 
        child = new XMLNode ("periods");
        child->add_property ("val", to_string (periods_adjustment.get_value(), std::dec));
 
        child = new XMLNode ("periods");
        child->add_property ("val", to_string (periods_adjustment.get_value(), std::dec));
@@ -1148,7 +1217,11 @@ EngineControl::get_state ()
        child = new XMLNode ("outputdevice");
        child->add_property ("val", output_device_combo.get_active_text());
        root->add_child_nocopy (*child);
        child = new XMLNode ("outputdevice");
        child->add_property ("val", output_device_combo.get_active_text());
        root->add_child_nocopy (*child);
-       
+
+       child = new XMLNode ("mididriver");
+       child->add_property ("val", midi_driver_combo.get_active_text());
+       root->add_child_nocopy (*child);
+
        return *root;
 }
 
        return *root;
 }
 
@@ -1160,34 +1233,46 @@ EngineControl::set_state (const XMLNode& root)
        XMLNode* child;
        XMLProperty* prop = NULL;
        bool using_dummy = false;
        XMLNode* child;
        XMLProperty* prop = NULL;
        bool using_dummy = false;
-       
+       bool using_ffado = false;
+
        int val;
        string strval;
        int val;
        string strval;
-       
+
        if ( (child = root.child ("driver"))){
                prop = child->property("val");
        if ( (child = root.child ("driver"))){
                prop = child->property("val");
+
                if (prop && (prop->value() == "Dummy") ) {
                        using_dummy = true;
                }
                if (prop && (prop->value() == "Dummy") ) {
                        using_dummy = true;
                }
+               if (prop && (prop->value() == "FFADO") ) {
+                       using_ffado = true;
+               }
+
        }
        }
-       
+
        clist = root.children();
 
        for (citer = clist.begin(); citer != clist.end(); ++citer) {
        clist = root.children();
 
        for (citer = clist.begin(); citer != clist.end(); ++citer) {
-               if ( prop && (prop->value() == "FFADO" ))
-                               continue;
+
                child = *citer;
 
                prop = child->property ("val");
 
                if (!prop || prop->value().empty()) {
 
                child = *citer;
 
                prop = child->property ("val");
 
                if (!prop || prop->value().empty()) {
 
-                       if ( using_dummy && ( child->name() == "interface" || child->name() == "inputdevice" || child->name() == "outputdevice" ))
+                       if (((using_dummy || using_ffado)
+                               && ( child->name() == "interface"
+                                       || child->name() == "inputdevice"
+                                       || child->name() == "outputdevice"))
+                               || child->name() == "timeout")
+                       {
                                continue;
                                continue;
+                       }
+
                        error << string_compose (_("AudioSetup value for %1 is missing data"), child->name()) << endmsg;
                        continue;
                }
                        error << string_compose (_("AudioSetup value for %1 is missing data"), child->name()) << endmsg;
                        continue;
                }
-               
+
                strval = prop->value();
 
                /* adjustments/spinners */
                strval = prop->value();
 
                /* adjustments/spinners */
@@ -1250,24 +1335,34 @@ EngineControl::set_state (const XMLNode& root)
                } else if (child->name() == "periodsize") {
                        period_size_combo.set_active_text(strval);
                } else if (child->name() == "serverpath") {
                } else if (child->name() == "periodsize") {
                        period_size_combo.set_active_text(strval);
                } else if (child->name() == "serverpath") {
-                       /* do not allow us to use a server path that doesn't
-                          exist on this system. this handles cases where
-                          the user has an RC file listing a serverpath
-                          from some other machine.
-                       */
-                       vector<string>::iterator x;
-                       for (x = server_strings.begin(); x != server_strings.end(); ++x) {
-                               if (*x == strval) {
-                                       break;
-                               }
-                       }
-                       if (x != server_strings.end()) {
-                               serverpath_combo.set_active_text (strval);
-                       } else {
-                               warning << string_compose (_("configuration files contain a JACK server path that doesn't exist (%1)"),
-                                                            strval)
-                                       << endmsg;
-                       }
+
+                        /* only attempt to set this if we have bothered to look
+                           up server names already. otherwise this is all
+                           redundant (actually, all of this dialog/widget
+                           is redundant in that case ...)
+                        */
+
+                        if (!server_strings.empty()) {
+                                /* do not allow us to use a server path that doesn't
+                                   exist on this system. this handles cases where
+                                   the user has an RC file listing a serverpath
+                                   from some other machine.
+                                */
+                                vector<string>::iterator x;
+                                for (x = server_strings.begin(); x != server_strings.end(); ++x) {
+                                        if (*x == strval) {
+                                                break;
+                                        }
+                                }
+                                if (x != server_strings.end()) {
+                                        serverpath_combo.set_active_text (strval);
+                                } else {
+                                        warning << string_compose (_("configuration files contain a JACK server path that doesn't exist (%1)"),
+                                                                   strval)
+                                                << endmsg;
+                                }
+                        }
+
                } else if (child->name() == "driver") {
                        driver_combo.set_active_text(strval);
                } else if (child->name() == "interface") {
                } else if (child->name() == "driver") {
                        driver_combo.set_active_text(strval);
                } else if (child->name() == "interface") {
@@ -1282,6 +1377,8 @@ EngineControl::set_state (const XMLNode& root)
                        input_device_combo.set_active_text(strval);
                } else if (child->name() == "outputdevice") {
                        output_device_combo.set_active_text(strval);
                        input_device_combo.set_active_text(strval);
                } else if (child->name() == "outputdevice") {
                        output_device_combo.set_active_text(strval);
+               } else if (child->name() == "mididriver") {
+                       midi_driver_combo.set_active_text(strval);
                }
        }
 }
                }
        }
 }