continue cleanup+improvements to audio setup dialog; add save+restore to said dialog
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 17 Aug 2007 15:53:59 +0000 (15:53 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 17 Aug 2007 15:53:59 +0000 (15:53 +0000)
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2321 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/ardour-sae.menus
gtk2_ardour/ardour2_ui_dark.rc.in
gtk2_ardour/ardour2_ui_light.rc.in
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/engine_dialog.cc
gtk2_ardour/engine_dialog.h
gtk2_ardour/new_session_dialog.cc
gtk2_ardour/option_editor.cc

index 83245b879b6bbe7b002b75b4b12e9ab8821c5fc4..d9827a38ddcd74419efc37139fc10d0ebd37201e 100644 (file)
                        <menuitem action='set-mouse-mode-gain'/>
                        <menuitem action='set-mouse-mode-zoom'/>
                        <menuitem action='set-mouse-mode-timefx'/>
-               </menu>
+               </menu>
+                <separator/>       
+                <menuitem action='ToggleOptionsEditor'/>
         </menu>         
        <menu name='Regions' action='Regions'>
                    <menuitem action='crop'/>
               <separator/>
                <menuitem action='goto-editor'/>
                <menuitem action='goto-mixer'/>
-               <menuitem action='ToggleOptionsEditor'/>
                <menuitem action='ToggleInspector'/>
                <menuitem action='ToggleLocations'/>
                <menuitem action='ToggleThemeManager'/>
index 254950629961c115aa7faa4f231b588ecd8be134..1510b1c1bd28818a6d50b7d4f803e03ac403fcff 100644 (file)
@@ -454,7 +454,7 @@ style "ardour_progressbars" = "default_buttons_menus"
   bg[PRELIGHT] = { 0.00, 0.36, 0.40 }
 }
 
-style "options_window"  = "default_base"
+style "preferences"  = "default_base"
 {
        font_name = "%FONT_NORMAL%"
        fg[PRELIGHT] = { 0.80, 0.80, 0.80 }
@@ -1208,15 +1208,15 @@ widget "*MixerMonitorInputButton.*" style:highest "very_small_button"
 widget "*MixerIOButton" style:highest "very_small_button"
 widget "*MixerIOButtonLabel" style:highest "very_small_button"
 widget "*AddRouteDialogSpinner" style:highest "ardour_adjusters"
-widget "*AddRouteDialogRadioButton*" style:highest "options_window"
-widget "*OptionsNotebook" style:highest "options_window"
-widget "*OptionEditorToggleButton*" style:highest "options_window"
-widget "*OptionsLabel" style:highest "options_window"
-widget "*OptionEditorAuditionerLabel" style:highest "options_window"
+widget "*AddRouteDialogRadioButton*" style:highest "preferences"
+widget "*OptionsNotebook" style:highest "preferences"
+widget "*OptionEditorToggleButton*" style:highest "preferences"
+widget "*OptionsLabel" style:highest "preferences"
+widget "*OptionEditorAuditionerLabel" style:highest "preferences"
 widget "*OptionsEntry" style:highest "option_entry"
-widget "*InspectorNotebook" style:highest "options_window"
-widget "*NewSessionDialog" style:highest "options_window"
-widget "*NewSessionDialogButton*" style:highest "options_window"
+widget "*InspectorNotebook" style:highest "preferences"
+widget "*NewSessionDialog" style:highest "preferences"
+widget "*NewSessionDialogButton*" style:highest "preferences"
 widget "*MixerSendSwitch*" style:highest "very_small_red_active_and_selected_button"
 widget "*OptionEditorToggleButton" style:highest "small_red_active_and_selected_button"
 widget "*NewSessionDialogButton" style:highest "small_red_active_and_selected_button"
index dec884f41fafb81189dff4f7c64b3692cc0115c0..c9c054783af8818d4112f659632ec470d2aa3b15 100644 (file)
@@ -457,7 +457,7 @@ style "ardour_progressbars" = "default_buttons_menus"
   bg[PRELIGHT] = { 0.00, 0.36, 0.40 }
 }
 
-style "options_window"  = "default_base"
+style "preferences"  = "default_base"
 {
        font_name = "%FONT_NORMAL%"
        fg[PRELIGHT] = { 0.80, 0.80, 0.80 }
@@ -1212,15 +1212,15 @@ widget "*MixerMonitorInputButton.*" style:highest "very_small_button"
 widget "*MixerIOButton" style:highest "very_small_button"
 widget "*MixerIOButtonLabel" style:highest "very_small_button"
 widget "*AddRouteDialogSpinner" style:highest "ardour_adjusters"
-widget "*AddRouteDialogRadioButton*" style:highest "options_window"
-widget "*OptionsNotebook" style:highest "options_window"
-widget "*OptionEditorToggleButton*" style:highest "options_window"
-widget "*OptionsLabel" style:highest "options_window"
-widget "*OptionEditorAuditionerLabel" style:highest "options_window"
+widget "*AddRouteDialogRadioButton*" style:highest "preferences"
+widget "*OptionsNotebook" style:highest "preferences"
+widget "*OptionEditorToggleButton*" style:highest "preferences"
+widget "*OptionsLabel" style:highest "preferences"
+widget "*OptionEditorAuditionerLabel" style:highest "preferences"
 widget "*OptionsEntry" style:highest "option_entry"
-widget "*InspectorNotebook" style:highest "options_window"
-widget "*NewSessionDialog" style:highest "options_window"
-widget "*NewSessionDialogButton*" style:highest "options_window"
+widget "*InspectorNotebook" style:highest "preferences"
+widget "*NewSessionDialog" style:highest "preferences"
+widget "*NewSessionDialogButton*" style:highest "preferences"
 widget "*MixerSendSwitch*" style:highest "very_small_red_active_and_selected_button"
 widget "*OptionEditorToggleButton" style:highest "small_red_active_and_selected_button"
 widget "*NewSessionDialogButton" style:highest "small_red_active_and_selected_button"
index 99a8c072f6a4636047f9d1cc2cc0613ce35ff788..8c5ddd752bfd16a3c99eb7892b0c6b1d38e085c9 100644 (file)
@@ -475,6 +475,11 @@ 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());
+       if (new_session_dialog) {
+               if (new_session_dialog->engine_control.was_used()) {
+                       Config->add_extra_xml (new_session_dialog->engine_control.get_state());
+               }
+       }
        Config->save_state();
 
        XMLNode enode(static_cast<Stateful*>(editor)->get_state());
@@ -562,7 +567,7 @@ ARDOUR_UI::startup ()
        bool isnew;
 
        new_session_dialog = new NewSessionDialog();
-
+       
        /* If no session name is given: we're not loading a session yet, nor creating a new one */
 
        if (session_name.length()) {
@@ -609,7 +614,13 @@ ARDOUR_UI::startup ()
                }
                
        } else {
+
+               XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
                
+               if (audio_setup) {
+                       new_session_dialog->engine_control.set_state (*audio_setup);
+               }
+
                /* no backend audio, must bring up NSD to check configuration */
                
                need_nsd = true;
index 98cf2b42ac304942309f3279e98dfb55d09164dd..ca0d3d58fb8c130f513db5ab7d47764db2a18ff6 100644 (file)
@@ -201,7 +201,7 @@ ARDOUR_UI::install_actions ()
 
        ActionManager::register_action (common_actions, X_("goto-editor"), _("Show Editor"),  mem_fun(*this, &ARDOUR_UI::goto_editor_window));
        ActionManager::register_action (common_actions, X_("goto-mixer"), _("Show Mixer"),  mem_fun(*this, &ARDOUR_UI::goto_mixer_window));
-       ActionManager::register_toggle_action (common_actions, X_("ToggleOptionsEditor"), _("Options Editor"), mem_fun(*this, &ARDOUR_UI::toggle_options_window));
+       ActionManager::register_toggle_action (common_actions, X_("ToggleOptionsEditor"), _("Preferences"), mem_fun(*this, &ARDOUR_UI::toggle_options_window));
        act = ActionManager::register_toggle_action (common_actions, X_("ToggleInspector"), _("Track/Bus Inspector"), mem_fun(*this, &ARDOUR_UI::toggle_route_params_window));
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_toggle_action (common_actions, X_("ToggleConnections"), _("Connections"), mem_fun(*this, &ARDOUR_UI::toggle_connection_editor));
index 5cb7a0d0ff1f80e8ab76cbecfa9edb89759eca41..75d950051f7f3469a6d1c61140882f7093d82acf 100644 (file)
@@ -3,11 +3,14 @@
 #include <fstream>
 
 #include <glibmm.h>
+#include <pbd/xml++.h>
 
 #ifdef __APPLE__
 #include <CoreAudio/CoreAudio.h>
 #include <CoreFoundation/CFString.h>
-#endif __APPLE__
+#else
+#include <alsa/asoundlib.h>
+#endif
 
 #include <ardour/profile.h>
 #include <jack/jack.h>
@@ -50,13 +53,19 @@ EngineControl::EngineControl ()
          start_button (_("Start")),
          stop_button (_("Stop")),
          basic_packer (8, 2),
-         options_packer (12, 2),
+#ifdef __APPLE__
+         options_packer (4, 2),
+#else
+         options_packer (14, 2),
+#endif   
          device_packer (3, 2)
 {
        using namespace Notebook_Helpers;
        Label* label;
        vector<string> strings;
 
+       _used = false;
+
        strings.push_back (_("8000Hz"));
        strings.push_back (_("22050Hz"));
        strings.push_back (_("44100Hz"));
@@ -80,6 +89,14 @@ EngineControl::EngineControl ()
        set_popdown_strings (period_size_combo, strings);
        period_size_combo.set_active_text ("1024");
 
+       strings.clear ();
+       strings.push_back (_("None"));
+       strings.push_back (_("Triangular"));
+       strings.push_back (_("Rectangular"));
+       strings.push_back (_("Shaped"));
+       set_popdown_strings (dither_mode_combo, strings);
+       dither_mode_combo.set_active_text (_("None"));
+
        /* basic parameters */
 
        basic_packer.set_spacings (6);
@@ -104,9 +121,10 @@ EngineControl::EngineControl ()
        driver_changed ();
 
        strings.clear ();
-       strings.push_back (_("Duplex"));
+       strings.push_back (_("Playback/Recording on 1 Device"));
+       strings.push_back (_("Playback/Recording on 2 Devices"));
        strings.push_back (_("Playback only"));
-       strings.push_back (_("Capture only"));
+       strings.push_back (_("Recording only"));
        set_popdown_strings (audio_mode_combo, strings);
        audio_mode_combo.set_active_text (strings.front());
 
@@ -135,6 +153,7 @@ EngineControl::EngineControl ()
        periods_spinner.set_value (2);
 
        label = manage (new Label (_("Approximate latency")));
+       label->set_alignment (0.0, 0.5);
        basic_packer.attach (*label, 0, 1, 5, 6, FILL|EXPAND, (AttachOptions) 0);
        basic_packer.attach (latency_label, 1, 2, 5, 6, FILL|EXPAND, (AttachOptions) 0);
 
@@ -145,9 +164,14 @@ EngineControl::EngineControl ()
 
        label = manage (new Label (_("Audio Mode")));
        basic_packer.attach (*label, 0, 1, 6, 7, FILL|EXPAND, (AttachOptions) 0);
+       
+       /* no audio mode with CoreAudio, its duplex or nuthin' */
+
+#ifndef __APPLE__
        basic_packer.attach (audio_mode_combo, 1, 2, 6, 7, FILL|EXPAND, (AttachOptions) 0);
+#endif
 
-       /* 
+       /*
 
        if (engine_running()) {
                start_button.set_sensitive (false);
@@ -166,26 +190,41 @@ EngineControl::EngineControl ()
 
        /* options */
 
-       options_packer.attach (realtime_button, 0, 1, 0, 1, FILL|EXPAND, (AttachOptions) 0);
+       int row = 0;
+       options_packer.set_spacings (6);
+
+       options_packer.attach (realtime_button, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
        label = manage (new Label (_("Realtime Priority")));
-       options_packer.attach (*label, 0, 1, 1, 2, FILL|EXPAND, (AttachOptions) 0);
-       options_packer.attach (priority_spinner, 1, 2, 1, 2, FILL|EXPAND, (AttachOptions) 0);
+       label->set_alignment (0.0, 0.5);
+       options_packer.attach (priority_spinner, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       options_packer.attach (*label, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
        priority_spinner.set_value (60);
 
        realtime_button.signal_toggled().connect (mem_fun (*this, &EngineControl::realtime_changed));
        realtime_changed ();
 
 #ifndef __APPLE__
-       options_packer.attach (no_memory_lock_button, 0, 1, 2, 3, FILL|EXPAND, (AttachOptions) 0);
-       options_packer.attach (unlock_memory_button, 0, 1, 3, 4, FILL|EXPAND, (AttachOptions) 0);
-       options_packer.attach (soft_mode_button, 0, 1, 4, 5, FILL|EXPAND, (AttachOptions) 0);
-       options_packer.attach (monitor_button, 0, 1, 5, 6, FILL|EXPAND, (AttachOptions) 0);
-       options_packer.attach (force16bit_button, 0, 1, 6, 7, FILL|EXPAND, (AttachOptions) 0);
-       options_packer.attach (hw_monitor_button, 0, 1, 7, 8, FILL|EXPAND, (AttachOptions) 0);
-       options_packer.attach (hw_meter_button, 0, 1, 8, 9, FILL|EXPAND, (AttachOptions) 0);
-       options_packer.attach (verbose_output_button, 0, 1, 9, 10, FILL|EXPAND, (AttachOptions) 0);
+       options_packer.attach (no_memory_lock_button, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
+       options_packer.attach (unlock_memory_button, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
+       options_packer.attach (soft_mode_button, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
+       options_packer.attach (monitor_button, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
+       options_packer.attach (force16bit_button, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
+       options_packer.attach (hw_monitor_button, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
+       options_packer.attach (hw_meter_button, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
+       options_packer.attach (verbose_output_button, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
 #else 
-       options_packer.attach (verbose_output_button, 0, 1, 2, 3, FILL|EXPAND, (AttachOptions) 0);
+       options_packer.attach (verbose_output_button, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
 #endif
 
        strings.clear ();
@@ -198,12 +237,24 @@ EngineControl::EngineControl ()
        timeout_combo.set_active_text (strings.front ());
 
        label = manage (new Label (_("Client timeout")));
-       options_packer.attach (*label, 0, 1, 11, 12, (AttachOptions) 0, (AttachOptions) 0);
-       options_packer.attach (timeout_combo, 1, 2, 11, 12, FILL|EXPAND, AttachOptions(0));
+       label->set_alignment (0.0, 0.5);
+       options_packer.attach (timeout_combo, 0, 1, row, row + 1, FILL|EXPAND, AttachOptions(0));
+       options_packer.attach (*label, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
 
        label = manage (new Label (_("Number of ports")));
-       options_packer.attach (*label, 0, 1, 12, 13, (AttachOptions) 0, (AttachOptions) 0);
-       options_packer.attach (ports_spinner, 1, 2, 12, 13, FILL|EXPAND, AttachOptions(0));
+       label->set_alignment (0.0, 0.5);
+       options_packer.attach (ports_spinner, 0, 1, row, row + 1, FILL|EXPAND, AttachOptions(0));
+       options_packer.attach (*label, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
+
+#ifndef __APPLE__
+       label = manage (new Label (_("Dither")));       
+       label->set_alignment (0.0, 0.5);
+       options_packer.attach (dither_mode_combo, 0, 1, row, row + 1, FILL|EXPAND, AttachOptions(0));
+       options_packer.attach (*label, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+       ++row;
+#endif
 
        strings.clear ();
 
@@ -217,12 +268,12 @@ EngineControl::EngineControl ()
        set_popdown_strings (serverpath_combo, strings);
        serverpath_combo.set_active_text (strings.front());
 
-       cerr << "we have " << strings.size() << " possible Jack servers\n";
-
        if (strings.size() > 1) {
                label = manage (new Label (_("Server:")));
-               options_packer.attach (*label, 0, 1, 11, 12, (AttachOptions) 0, (AttachOptions) 0);
-               options_packer.attach (serverpath_combo, 1, 2, 11, 12, FILL|EXPAND, (AttachOptions) 0);
+               options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+               label->set_alignment (0.0, 0.5);
+               options_packer.attach (serverpath_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+               ++row;
        }
 
        /* device settings */
@@ -230,25 +281,33 @@ EngineControl::EngineControl ()
        device_packer.set_spacings (6);
 
        label = manage (new Label (_("Input device")));
+       label->set_alignment (1.0, 0.5);
        device_packer.attach (*label, 0, 1, 0, 1, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (input_device_combo, 1, 2, 0, 1, FILL|EXPAND, (AttachOptions) 0);
        label = manage (new Label (_("Output device")));
+       label->set_alignment (1.0, 0.5);
        device_packer.attach (*label, 0, 1, 1, 2, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (output_device_combo, 1, 2, 1, 2, FILL|EXPAND, (AttachOptions) 0); 
        label = manage (new Label (_("Input channels")));
+       label->set_alignment (1.0, 0.5);
        device_packer.attach (*label, 0, 1, 2, 3, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (input_channels, 1, 2, 2, 3, FILL|EXPAND, (AttachOptions) 0);
        label = manage (new Label (_("Output channels")));
+       label->set_alignment (1.0, 0.5);
        device_packer.attach (*label, 0, 1, 3, 4, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (output_channels, 1, 2, 3, 4, FILL|EXPAND, (AttachOptions) 0);
-       label = manage (new Label (_("Input latency (samples)")));
+       label = manage (new Label (_("Hardware input latency (samples)")));
+       label->set_alignment (1.0, 0.5);
        device_packer.attach (*label, 0, 1, 4, 5, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (input_latency, 1, 2, 4, 5, FILL|EXPAND, (AttachOptions) 0);
-       label = manage (new Label (_("Output latency (samples)")));
+       label = manage (new Label (_("Hardware output latency (samples)")));
+       label->set_alignment (1.0, 0.5);
        device_packer.attach (*label, 0, 1, 5, 6, FILL|EXPAND, (AttachOptions) 0);
        device_packer.attach (output_latency, 1, 2, 5, 6, FILL|EXPAND, (AttachOptions) 0);
 
-       notebook.pages().push_back (TabElem (basic_packer, _("Basics")));
+       basic_hbox.pack_start (basic_packer, false, false);
+
+       notebook.pages().push_back (TabElem (basic_hbox, _("Basics")));
        notebook.pages().push_back (TabElem (options_packer, _("Options")));
        notebook.pages().push_back (TabElem (device_packer, _("Device Parameters")));
 
@@ -338,16 +397,26 @@ EngineControl::build_command_line (vector<string>& cmd)
 
        /* driver arguments */
 
-       str = audio_mode_combo.get_active_text();
-       if (str == _("Duplex")) {
-               /* relax */
-       } else if (str == _("Playback only")) {
-               cmd.push_back ("-P");
-       } else if (str == _("Capture only")) {
-               cmd.push_back ("-C");
-       }
-
        if (!using_coreaudio) {
+               str = audio_mode_combo.get_active_text();
+               
+               if (str == _("Playback/Recording on 1 Device")) {
+                       
+                       /* relax */
+                       
+               } else if (str == _("Playback/Recording on 2 Devices")) {
+                       
+                       cmd.push_back ("-C");
+                       cmd.push_back (get_device_name (driver, input_device_combo.get_active_text()));
+                       cmd.push_back ("-P");
+                       cmd.push_back (get_device_name (driver, output_device_combo.get_active_text()));
+                       
+               } else if (str == _("Playback only")) {
+                       cmd.push_back ("-P");
+               } else if (str == _("Recording only")) {
+                       cmd.push_back ("-C");
+               }
+
                cmd.push_back ("-n");
                cmd.push_back (to_string ((uint32_t) floor (periods_spinner.get_value()), std::dec));
        }
@@ -359,9 +428,11 @@ EngineControl::build_command_line (vector<string>& cmd)
        cmd.push_back (period_size_combo.get_active_text());
 
        if (using_alsa) {
-
-               cmd.push_back ("-d");
-               cmd.push_back (interface_combo.get_active_text());
+               
+               if (audio_mode_combo.get_active_text() != _("Playback/Recording on 2 Devices")) {
+                       cmd.push_back ("-d");
+                       cmd.push_back (get_device_name (driver, interface_combo.get_active_text()));
+               } 
 
                if (hw_meter_button.get_active()) {
                        cmd.push_back ("-M");
@@ -372,6 +443,7 @@ EngineControl::build_command_line (vector<string>& cmd)
                }
 
                str = dither_mode_combo.get_active_text();
+
                if (str == _("None")) {
                } else if (str == _("Triangular")) {
                        cmd.push_back ("-z triangular");
@@ -393,23 +465,7 @@ EngineControl::build_command_line (vector<string>& cmd)
 
 #ifdef __APPLE__
                cmd.push_back ("-n");
-
-               Glib::ustring str = interface_combo.get_active_text();
-               vector<string>::iterator n;
-               vector<string>::iterator i;
-               
-               for (i = devices[driver].begin(), n = coreaudio_devs.begin(); i != devices[driver].end(); ++i, ++n) {
-                       if (str == (*i)) {
-                               cerr << "for " << str << " use " << (*n) << endl;
-                               cmd.push_back (*n);
-                               break;
-                       }
-               }
-                       
-               if (i == devices[driver].end()) {
-                       fatal << string_compose (_("programming error: %1"), "coreaudio device ID missing") << endmsg;
-                       /*NOTREACHED*/
-               }
+               cmd.push_back (get_device_name (driver, interface_combo.get_active_text()));
 #endif
 
        } else if (using_oss) {
@@ -458,6 +514,8 @@ EngineControl::start_engine ()
        jackdrc << endl;
        cerr << endl;
        jackdrc.close ();
+
+       _used = true;
        
 #if 0
 
@@ -477,10 +535,6 @@ EngineControl::start_engine ()
 int
 EngineControl::stop_engine ()
 {
-       close (engine_stdin);
-       close (engine_stderr);
-       close (engine_stdout);
-       spawn_close_pid (engine_pid);
        return 0;
 }
 
@@ -531,7 +585,7 @@ EngineControl::enumerate_coreaudio_devices ()
        Boolean isWritable;
        size_t outSize = sizeof(isWritable);
 
-       coreaudio_devs.clear ();
+       backend_devs.clear ();
 
        err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,
                                           &outSize, &isWritable);
@@ -563,7 +617,7 @@ EngineControl::enumerate_coreaudio_devices ()
                                                
                                                if (getDeviceUIDFromID(coreDeviceIDs[i], drivername, sizeof (drivername)) == noErr) {
                                                        devs.push_back (coreDeviceName);
-                                                       coreaudio_devs.push_back (drivername);
+                                                       backend_devs.push_back (drivername);
                                                } 
                                        }
                                }
@@ -579,12 +633,63 @@ vector<string>
 EngineControl::enumerate_alsa_devices ()
 {
        vector<string> devs;
-       devs.push_back ("hw:0");
-       devs.push_back ("hw:1");
-       devs.push_back ("plughw:0");
-       devs.push_back ("plughw:1");
+
+       snd_ctl_t *handle;
+       snd_ctl_card_info_t *info;
+       snd_pcm_info_t *pcminfo;
+       snd_ctl_card_info_alloca(&info);
+       snd_pcm_info_alloca(&pcminfo);
+       string devname;
+       int cardnum = -1;
+       int device = -1;
+
+       backend_devs.clear ();
+
+       while (snd_card_next (&cardnum) >= 0 && cardnum >= 0) {
+
+               devname = "hw:";
+               devname += to_string (cardnum, std::dec);
+
+               if (snd_ctl_open (&handle, devname.c_str(), 0) >= 0 && snd_ctl_card_info (handle, info) >= 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) {
+                                       have_playback = true;
+                               }
+
+                               if (have_capture && have_playback) {
+                                       devs.push_back (snd_pcm_info_get_name (pcminfo));
+                                       devname += ',';
+                                       devname += to_string (device, std::dec);
+                                       backend_devs.push_back (devname);
+                               }
+                       }
+
+                       snd_ctl_close(handle);
+               }
+       }
+
        return devs;
 }
+
 vector<string>
 EngineControl::enumerate_ffado_devices ()
 {
@@ -618,9 +723,13 @@ EngineControl::driver_changed ()
        vector<string>& strings = devices[driver];
        
        set_popdown_strings (interface_combo, strings);
+       set_popdown_strings (input_device_combo, strings);
+       set_popdown_strings (output_device_combo, strings);
 
        if (!strings.empty()) {
                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") {
@@ -662,19 +771,23 @@ EngineControl::audio_mode_changed ()
 {
        Glib::ustring str = audio_mode_combo.get_active_text();
 
-       if (str == _("Duplex")) {
+       if (str == _("Playback/Recording on 1 Device")) {
                input_device_combo.set_sensitive (false);
                output_device_combo.set_sensitive (false);
-       } else {
+       } else if (str == _("Playback/Recording on 2 Devices")) {
                input_device_combo.set_sensitive (true);
                output_device_combo.set_sensitive (true);
+       } else if (str == _("Playback only")) {
+               output_device_combo.set_sensitive (true);
+       } else if (str == _("Recording only")) {
+               input_device_combo.set_sensitive (true);
        }
 }
 
 void
 EngineControl::find_jack_servers (vector<string>& strings)
 {
-#ifdef __APPLE
+#ifdef __APPLE__
        if (Profile->get_single_package()) {
 
                /* this magic lets us finds the path to the OSX bundle, and then
@@ -696,8 +809,9 @@ EngineControl::find_jack_servers (vector<string>& strings)
                } else {
                        warning << _("JACK appears to be missing from the Ardour bundle") << endmsg;
                }
+       }
 #endif
-
+       
        if (Glib::file_test ("/usr/bin/jackd", FILE_TEST_EXISTS)) {
                strings.push_back ("/usr/bin/jackd");
        }
@@ -718,3 +832,244 @@ EngineControl::find_jack_servers (vector<string>& strings)
        }
 
 }
+
+string
+EngineControl::get_device_name (const string& driver, const string& human_readable)
+{
+       vector<string>::iterator n;
+       vector<string>::iterator i;
+
+       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);
+               }
+       }
+       
+       if (i == devices[driver].end()) {
+               fatal << string_compose (_("programming error: %1"), "true hardware name for ID missing") << endmsg;
+               /*NOTREACHED*/
+       }
+
+       /* keep gcc happy */
+
+       return string();
+}
+
+XMLNode&
+EngineControl::get_state ()
+{
+       XMLNode* root = new XMLNode ("AudioSetup");
+       XMLNode* child;
+       Glib::ustring path;
+
+       child = new XMLNode ("periods");
+       child->add_property ("val", to_string (periods_adjustment.get_value(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("priority");
+       child->add_property ("val", to_string (priority_adjustment.get_value(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("ports");
+       child->add_property ("val", to_string (ports_adjustment.get_value(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("inchannels");
+       child->add_property ("val", to_string (input_channels.get_value(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("outchannels");
+       child->add_property ("val", to_string (output_channels.get_value(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("inlatency");
+       child->add_property ("val", to_string (input_latency.get_value(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("outlatency");
+       child->add_property ("val", to_string (output_latency.get_value(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("realtime");
+       child->add_property ("val", to_string (realtime_button.get_active(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("nomemorylock");
+       child->add_property ("val", to_string (no_memory_lock_button.get_active(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("unlockmemory");
+       child->add_property ("val", to_string (unlock_memory_button.get_active(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("softmode");
+       child->add_property ("val", to_string (soft_mode_button.get_active(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("force16bit");
+       child->add_property ("val", to_string (force16bit_button.get_active(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("hwmonitor");
+       child->add_property ("val", to_string (hw_monitor_button.get_active(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("hwmeter");
+       child->add_property ("val", to_string (hw_meter_button.get_active(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("verbose");
+       child->add_property ("val", to_string (verbose_output_button.get_active(), std::dec));
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("samplerate");
+       child->add_property ("val", sample_rate_combo.get_active_text());
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("periodsize");
+       child->add_property ("val", period_size_combo.get_active_text());
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("serverpath");
+       child->add_property ("val", serverpath_combo.get_active_text());
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("driver");
+       child->add_property ("val", driver_combo.get_active_text());
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("interface");
+       child->add_property ("val", interface_combo.get_active_text());
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("timeout");
+       child->add_property ("val", timeout_combo.get_active_text());
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("dither");
+       child->add_property ("val", dither_mode_combo.get_active_text());
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("audiomode");
+       child->add_property ("val", audio_mode_combo.get_active_text());
+       root->add_child_nocopy (*child);
+
+       child = new XMLNode ("inputdevice");
+       child->add_property ("val", input_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);
+       
+       return *root;
+}
+
+void
+EngineControl::set_state (const XMLNode& root)
+{
+       XMLNodeList          clist;
+       XMLNodeConstIterator citer;
+       XMLNode* child;
+       XMLProperty* prop;
+
+       int val;
+       string strval;
+
+       clist = root.children();
+
+       for (citer = clist.begin(); citer != clist.end(); ++citer) {
+
+               child = *citer;
+
+               prop = child->property ("val");
+
+               if (!prop || prop->value().empty()) {
+                       error << string_compose (_("AudioSetup value for %1 is missing data"), child->name()) << endmsg;
+                       continue;
+               }
+               
+               strval = prop->value();
+
+               /* adjustments/spinners */
+
+               if (child->name() == "periods") {
+                       val = atoi (strval);
+                       periods_adjustment.set_value(val);
+               } else if (child->name() == "priority") {
+                       val = atoi (strval);
+                       priority_adjustment.set_value(val);
+               } else if (child->name() == "ports") {
+                       val = atoi (strval);
+                       ports_adjustment.set_value(val);
+               } else if (child->name() == "inchannels") {
+                       val = atoi (strval);
+                       input_channels.set_value(val);
+               } else if (child->name() == "outchannels") {
+                       val = atoi (strval);
+                       output_channels.set_value(val);
+               } else if (child->name() == "inlatency") {
+                       val = atoi (strval);
+                       input_latency.set_value(val);
+               } else if (child->name() == "outlatency") {
+                       val = atoi (strval);
+                       output_latency.set_value(val);
+               }
+
+               /* buttons */
+
+               else if (child->name() == "realtime") {
+                       val = atoi (strval);
+                       realtime_button.set_active(val);
+               } else if (child->name() == "nomemorylock") {
+                       val = atoi (strval);
+                       no_memory_lock_button.set_active(val);
+               } else if (child->name() == "unlockmemory") {
+                       val = atoi (strval);
+                       unlock_memory_button.set_active(val);
+               } else if (child->name() == "softmode") {
+                       val = atoi (strval);
+                       soft_mode_button.set_active(val);
+               } else if (child->name() == "force16bit") {
+                       val = atoi (strval);
+                       force16bit_button.set_active(val);
+               } else if (child->name() == "hwmonitor") {
+                       val = atoi (strval);
+                       hw_monitor_button.set_active(val);
+               } else if (child->name() == "hwmeter") {
+                       val = atoi (strval);
+                       hw_meter_button.set_active(val);
+               } else if (child->name() == "verbose") {
+                       val = atoi (strval);
+                       verbose_output_button.set_active(val);
+               }
+
+               /* combos */
+
+               else if (child->name() == "samplerate") {
+                       sample_rate_combo.set_active_text(strval);
+               } else if (child->name() == "periodsize") {
+                       period_size_combo.set_active_text(strval);
+               } else if (child->name() == "serverpath") {
+                       serverpath_combo.set_active_text(strval);
+               } else if (child->name() == "driver") {
+                       driver_combo.set_active_text(strval);
+               } else if (child->name() == "interface") {
+                       interface_combo.set_active_text(strval);
+               } else if (child->name() == "timeout") {
+                       timeout_combo.set_active_text(strval);
+               } else if (child->name() == "dither") {
+                       dither_mode_combo.set_active_text(strval);
+               } else if (child->name() == "audiomode") {
+                       audio_mode_combo.set_active_text(strval);
+               } else if (child->name() == "inputdevice") {
+                       input_device_combo.set_active_text(strval);
+               } else if (child->name() == "outputdevice") {
+                       output_device_combo.set_active_text(strval);
+               }
+       }
+}
index 21155386796671cb81e46320c5223b0d1bf36045..e3623d2d76e6ae0b955302fddb1528a82072f116 100644 (file)
@@ -24,6 +24,10 @@ class EngineControl : public Gtk::VBox {
        int start_engine ();
        int stop_engine ();
 
+       bool was_used() const { return _used; }
+       XMLNode& get_state ();
+       void set_state (const XMLNode&);
+
   private:
        Gtk::Adjustment periods_adjustment;
        Gtk::SpinButton periods_spinner;
@@ -67,24 +71,21 @@ class EngineControl : public Gtk::VBox {
        Gtk::Table basic_packer;
        Gtk::Table options_packer;
        Gtk::Table device_packer;
-
+       Gtk::HBox basic_hbox;
        Gtk::Notebook notebook;
+       
+       bool _used;
 
        void realtime_changed ();
        void driver_changed ();
-
        void build_command_line (std::vector<std::string>&);
-       Glib::Pid engine_pid;
-       int engine_stdin;
-       int engine_stdout;
-       int engine_stderr;
 
        std::map<std::string,std::vector<std::string> > devices;
+       std::vector<std::string> backend_devs;
        void enumerate_devices ();
 
 #ifdef __APPLE__
        std::vector<std::string> enumerate_coreaudio_devices ();
-       std::vector<std::string> coreaudio_devs;
 #else
        std::vector<std::string> enumerate_alsa_devices ();
        std::vector<std::string> enumerate_oss_devices ();
@@ -97,6 +98,7 @@ class EngineControl : public Gtk::VBox {
        uint32_t get_rate();
        void audio_mode_changed ();
        void find_jack_servers (std::vector<std::string>&);
+       std::string get_device_name (const std::string& driver, const std::string& human_readable_name);
 };
 
 #endif /* __gtk2_ardour_engine_dialog_h__ */
index d48a332cbcbfe7fcf21aaf7b78a6acb5b95a2ec0..65fdc35903babf45794cdf967c19b5868dafe565 100644 (file)
@@ -452,10 +452,8 @@ void
 NewSessionDialog::set_have_engine (bool yn)
 {
        if (yn) {
-               cerr << "removing audio page\n";
                m_notebook->remove_page (engine_control);
        } else {
-               cerr << "appending audio page\n";
                m_notebook->append_page (engine_control, _("Audio Setup"));
                m_notebook->show_all_children();
        }
index e68be7149c631f0b2739a4a237889eecedc4bfbf..2ef7c43d4f9060cea5ea61ea0af89a8d2a8b2b8d 100644 (file)
@@ -106,13 +106,13 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
        session = 0;
        
        WindowTitle title(Glib::get_application_name());
-       title += _("Options Editor");
+       title += _("Preferences");
        set_title(title.get_string());
 
        set_default_size (300, 300);
-       set_wmclass (X_("ardour_option_editor"), "Ardour");
+       set_wmclass (X_("ardour_preferences"), "Ardour");
 
-       set_name ("OptionsWindow");
+       set_name ("Preferences");
        add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
        
        VBox *vbox = get_vbox();