Rename libmusictime libtimecode (consistent with already used namespace "Timecode").
[ardour.git] / gtk2_ardour / engine_dialog.cc
index 3717feb038b5e994492036e1ac14533eb40ef6c6..a3c3edd1cc4815fad04270771516184b442e7fb9 100644 (file)
@@ -1,3 +1,22 @@
+/*
+    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>
@@ -46,6 +65,10 @@ EngineControl::EngineControl ()
          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")),
@@ -115,6 +138,7 @@ EngineControl::EngineControl ()
 #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"));
@@ -126,8 +150,8 @@ EngineControl::EngineControl ()
        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);
@@ -136,38 +160,50 @@ EngineControl::EngineControl ()
        audio_mode_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::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;
 
-       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++;
 
-       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++;
 
-       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++;
 
-       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__
-       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
 
-       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++;
@@ -180,15 +216,16 @@ EngineControl::EngineControl ()
        /* 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
 
-       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);
 
        /*
 
@@ -266,15 +303,21 @@ EngineControl::EngineControl ()
        ++row;
 
 #endif /* PROVIDE_TOO_MANY_OPTIONS */
-       label = manage (new Label (_("Number of ports")));
-       label->set_alignment (1.0, 0.5);
+       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;
 
+       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__
-       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;
@@ -304,36 +347,42 @@ EngineControl::EngineControl ()
        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;
-       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 (output_device_combo, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
        ++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;
-       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;
-       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);
+       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;
-       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);
+       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);
@@ -362,12 +411,10 @@ EngineControl::build_command_line (vector<string>& cmd)
 {
        string str;
        string driver;
-       bool using_oss = false;
        bool using_alsa = false;
        bool using_coreaudio = false;
-       bool using_netjack = false;
-       bool using_ffado = false;
        bool using_dummy = false;
+       bool using_ffado = false;
 
        /* first, path to jackd */
 
@@ -376,11 +423,14 @@ EngineControl::build_command_line (vector<string>& cmd)
        /* now jackd arguments */
 
        str = timeout_combo.get_active_text ();
+       
        if (str != _("Ignore")) {
+
                double secs = 0;
                uint32_t msecs;
                secs = atof (str);
                msecs = (uint32_t) floor (secs * 1000.0);
+               
                if (msecs > 0) {
                        cmd.push_back ("-t");
                        cmd.push_back (to_string (msecs, std::dec));
@@ -398,6 +448,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));
+       } else {
+               cmd.push_back ("-r"); /* override jackd's default --realtime */
        }
 
        if (unlock_memory_button.get_active()) {
@@ -417,31 +469,22 @@ EngineControl::build_command_line (vector<string>& cmd)
        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")) {
-               using_oss = true;
                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");
+       } else if (driver == X_("FreeBoB")) {
+               cmd.push_back ("freebob");
        } 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");
@@ -468,6 +511,7 @@ EngineControl::build_command_line (vector<string>& cmd)
 
                        cmd.push_back ("-C");
                        cmd.push_back (input_device);
+                       
                        cmd.push_back ("-P");
                        cmd.push_back (output_device);
 
@@ -477,7 +521,7 @@ EngineControl::build_command_line (vector<string>& cmd)
                        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));
                }
@@ -488,6 +532,23 @@ EngineControl::build_command_line (vector<string>& cmd)
 
        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) {
 
@@ -530,6 +591,13 @@ EngineControl::build_command_line (vector<string>& cmd)
                        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__
@@ -545,10 +613,6 @@ EngineControl::build_command_line (vector<string>& cmd)
                cmd.push_back (device);
 #endif
 
-       } else if (using_oss) {
-
-       } else if (using_netjack) {
-
        }
 }
 
@@ -577,7 +641,7 @@ EngineControl::setup_engine ()
                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());
@@ -620,6 +684,8 @@ EngineControl::enumerate_devices (const string& driver)
 #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") {
@@ -771,28 +837,11 @@ EngineControl::enumerate_alsa_devices ()
 
                        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) {
-                                       have_playback = true;
-                               }
-
-                               if (have_capture && have_playback) {
                                        devs.push_back (snd_pcm_info_get_name (pcminfo));
                                        devname += ',';
                                        devname += to_string (device, std::dec);
@@ -821,6 +870,7 @@ EngineControl::enumerate_freebob_devices ()
        vector<string> devs;
        return devs;
 }
+
 vector<string>
 EngineControl::enumerate_oss_devices ()
 {
@@ -853,7 +903,7 @@ EngineControl::driver_changed ()
 
        vector<string>& strings = devices[driver];
 
-       if (strings.empty() && driver != "FFADO" && driver != "Dummy") {
+       if (strings.empty() && driver != "FreeBoB" && driver != "FFADO" && driver != "Dummy") {
                error << string_compose (_("No devices found for driver \"%1\""), driver) << endmsg;
                return;
        }
@@ -911,12 +961,13 @@ EngineControl::redisplay_latency ()
        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 ()
 {
-       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);
@@ -1053,7 +1104,7 @@ EngineControl::get_state ()
 {
        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));
@@ -1155,6 +1206,10 @@ EngineControl::get_state ()
        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;
 }
 
@@ -1166,15 +1221,21 @@ EngineControl::set_state (const XMLNode& root)
        XMLNode* child;
        XMLProperty* prop = NULL;
        bool using_dummy = false;
+       bool using_ffado = false;
 
        int val;
        string strval;
 
        if ( (child = root.child ("driver"))){
                prop = child->property("val");
+               
                if (prop && (prop->value() == "Dummy") ) {
                        using_dummy = true;
                }
+               if (prop && (prop->value() == "FFADO") ) {
+                       using_ffado = true;
+               }
+
        }
 
        clist = root.children();
@@ -1187,8 +1248,15 @@ EngineControl::set_state (const XMLNode& root)
 
                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;
+                       }
+                       
                        error << string_compose (_("AudioSetup value for %1 is missing data"), child->name()) << endmsg;
                        continue;
                }
@@ -1297,6 +1365,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);
+               } else if (child->name() == "mididriver") {
+                       midi_driver_combo.set_active_text(strval);
                }
        }
 }