Merged with trunk R776
authorDavid Robillard <d@drobilla.net>
Thu, 10 Aug 2006 01:22:45 +0000 (01:22 +0000)
committerDavid Robillard <d@drobilla.net>
Thu, 10 Aug 2006 01:22:45 +0000 (01:22 +0000)
git-svn-id: svn://localhost/ardour2/branches/midi@777 d708f5d6-7413-0410-9779-e7cbd77b26cf

110 files changed:
SConstruct
ardour.dox
au_pluginui.cc [new file with mode: 0644]
gtk2_ardour/SConscript
gtk2_ardour/ardev_common.sh
gtk2_ardour/ardour2_ui.rc
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui_dialogs.cc
gtk2_ardour/audio_region_view.cc
gtk2_ardour/audio_time_axis.cc
gtk2_ardour/automation_line.cc
gtk2_ardour/automation_line.h
gtk2_ardour/automation_time_axis.cc
gtk2_ardour/automation_time_axis.h
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_audio_import.cc
gtk2_ardour/editor_keyboard.cc
gtk2_ardour/editor_markers.cc
gtk2_ardour/editor_mouse.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_tempodisplay.cc
gtk2_ardour/editor_timefx.cc
gtk2_ardour/gain_automation_time_axis.cc
gtk2_ardour/location_ui.cc
gtk2_ardour/main.cc
gtk2_ardour/new_session_dialog.cc
gtk2_ardour/new_session_dialog.h
gtk2_ardour/opts.cc
gtk2_ardour/pan_automation_time_axis.cc
gtk2_ardour/plugin_selector.cc
gtk2_ardour/plugin_selector.h
gtk2_ardour/plugin_ui.cc
gtk2_ardour/plugin_ui.h
gtk2_ardour/redirect_automation_time_axis.cc
gtk2_ardour/redirect_box.cc
gtk2_ardour/region_editor.h
gtk2_ardour/region_gain_line.cc
gtk2_ardour/region_gain_line.h
gtk2_ardour/route_params_ui.cc
gtk2_ardour/route_time_axis.cc
gtk2_ardour/route_ui.cc
gtk2_ardour/time_axis_view.cc
gtk2_ardour/vst_pluginui.cc
libs/appleutility/AUOutputBL.cpp [new file with mode: 0644]
libs/appleutility/AUOutputBL.h [new file with mode: 0644]
libs/appleutility/CAAudioChannelLayout.cpp [new file with mode: 0644]
libs/appleutility/CAAudioChannelLayout.h [new file with mode: 0644]
libs/appleutility/CAAudioChannelLayoutObject.cpp [new file with mode: 0644]
libs/appleutility/CAAudioUnit.cpp [new file with mode: 0644]
libs/appleutility/CAAudioUnit.h [new file with mode: 0644]
libs/appleutility/CACFDictionary.cpp [new file with mode: 0644]
libs/appleutility/CACFDictionary.h [new file with mode: 0644]
libs/appleutility/CACFNumber.cpp [new file with mode: 0644]
libs/appleutility/CACFNumber.h [new file with mode: 0644]
libs/appleutility/CACFString.cpp [new file with mode: 0644]
libs/appleutility/CACFString.h [new file with mode: 0644]
libs/appleutility/CAComponent.cpp [new file with mode: 0644]
libs/appleutility/CAComponent.h [new file with mode: 0644]
libs/appleutility/CAComponentDescription.cpp [new file with mode: 0644]
libs/appleutility/CAComponentDescription.h [new file with mode: 0644]
libs/appleutility/CAConditionalMacros.h [new file with mode: 0644]
libs/appleutility/CADebugMacros.cpp [new file with mode: 0644]
libs/appleutility/CADebugMacros.h [new file with mode: 0644]
libs/appleutility/CAMath.h [new file with mode: 0644]
libs/appleutility/CAReferenceCounted.h [new file with mode: 0644]
libs/appleutility/CAStreamBasicDescription.cpp [new file with mode: 0644]
libs/appleutility/CAStreamBasicDescription.h [new file with mode: 0644]
libs/appleutility/SConscript [new file with mode: 0644]
libs/ardour/SConscript
libs/ardour/ardour/ardour.h
libs/ardour/ardour/audio_unit.h
libs/ardour/ardour/automation_event.h
libs/ardour/ardour/ladspa_plugin.h
libs/ardour/ardour/location.h
libs/ardour/ardour/playlist.h
libs/ardour/ardour/plugin.h
libs/ardour/ardour/plugin_manager.h
libs/ardour/ardour/route.h
libs/ardour/ardour/session.h
libs/ardour/ardour/state_manager.h
libs/ardour/ardour/tempo.h
libs/ardour/ardour/track.h
libs/ardour/ardour/vst_plugin.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_unit.cc
libs/ardour/automation_event.cc
libs/ardour/globals.cc
libs/ardour/insert.cc
libs/ardour/io.cc
libs/ardour/ladspa_plugin.cc
libs/ardour/plugin.cc
libs/ardour/plugin_manager.cc
libs/ardour/session.cc
libs/ardour/session_command.cc [new file with mode: 0644]
libs/ardour/session_state.cc
libs/ardour/session_transport.cc
libs/ardour/state_manager.cc
libs/ardour/track.cc
libs/ardour/vst_plugin.cc
libs/libsndfile/src/flac.c
libs/pbd/SConscript
libs/pbd/command.cc [new file with mode: 0644]
libs/pbd/id.cc
libs/pbd/pbd/command.h [new file with mode: 0644]
libs/pbd/pbd/id.h
libs/pbd/pbd/memento_command.h [new file with mode: 0644]
libs/pbd/pbd/undo.h
libs/pbd/undo.cc
libs/surfaces/control_protocol/basic_ui.cc

index 64aad2737ff29b1de9ec8a59da50cb824e473327..e7e43a1405bba2a8192fccd10dddb7ebee33fadf 100644 (file)
@@ -454,6 +454,9 @@ conf = Configure (libraries['flac'])
 conf.CheckLib ('FLAC', 'FLAC__stream_decoder_new', language='CXX')
 libraries['flac'] = conf.Finish ()
 
+# or if that fails...
+#libraries['flac']    = LibraryInfo (LIBS='FLAC')
+
 #
 # Check for liblo
 
@@ -547,6 +550,10 @@ if env['SYSLIBS']:
 #    libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
     libraries['soundtouch'] = LibraryInfo()
     libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
+
+    libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
+                                            LIBPATH='#libs/appleutility',
+                                            CPPPATH='#libs/appleutility')
     
     coredirs = [
         'templates'
@@ -561,6 +568,9 @@ if env['SYSLIBS']:
     
     if env['VST']:
         subdirs = ['libs/fst'] + subdirs + ['vst']
+
+    if env['COREAUDIO']:
+        subdirs = subdirs + ['libs/appleutility']
     
     gtk_subdirs = [
 #        'libs/flowcanvas',
@@ -600,7 +610,10 @@ else:
 #    libraries['libglademm'] = LibraryInfo(LIBS='libglademm',
 #                                          LIBPATH='#libs/libglademm',
 #                                          CPPPATH='#libs/libglademm')
-    
+    libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
+                                            LIBPATH='#libs/appleutility',
+                                            CPPPATH='#libs/appleutility')
+
     coredirs = [
         'libs/soundtouch',
         'templates'
@@ -616,6 +629,9 @@ else:
     
     if env['VST']:
         subdirs = ['libs/fst'] + subdirs + ['vst']
+
+    if env['COREAUDIO']:
+        subdirs = subdirs + ['libs/appleutility']
     
     gtk_subdirs = [
        'libs/glibmm2',
index 2ad51340df1265684218cf3a4661296961ba6097..0ff7c85a414307dc4d1961e3931020c803c772b7 100644 (file)
@@ -972,13 +972,13 @@ ENABLE_PREPROCESSING   = YES
 # compilation will be performed. Macro expansion can be done in a controlled 
 # way by setting EXPAND_ONLY_PREDEF to YES.
 
-MACRO_EXPANSION        = NO
+MACRO_EXPANSION        = YES
 
 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
 # then the macro expansion is limited to the macros specified with the 
 # PREDEFINED and EXPAND_AS_DEFINED tags.
 
-EXPAND_ONLY_PREDEF     = NO
+EXPAND_ONLY_PREDEF     = YES
 
 # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
 # in the INCLUDE_PATH (see below) will be search if a #include is found.
@@ -1006,7 +1006,7 @@ INCLUDE_FILE_PATTERNS  =
 # undefined via #undef or recursively expanded use the := operator 
 # instead of the = operator.
 
-PREDEFINED             = 
+PREDEFINED             = HAVE_COREAUDIO VST_SUPPORT HAVE_LIBLO FFT_ANALYSIS
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
 # this tag can be used to specify a list of macro names that should be expanded. 
diff --git a/au_pluginui.cc b/au_pluginui.cc
new file mode 100644 (file)
index 0000000..cbf493a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+    Copyright (C) 2006 Paul Davis 
+       Written by Taybin Rutkin
+
+    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 <ardour/insert.h>
+#include <ardour/audio_unit.h>
+
+#include "plugin_ui.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+
+AUPluginUI::AUPluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_ptr<AUPlugin> ap)
+       : PlugUIBase (pi),
+         au (ap)
+{
+       info << "AUPluginUI created" << endmsg;
+}
+
+AUPluginUI::~AUPluginUI ()
+{
+       // nothing to do here - plugin destructor destroys the GUI
+}
+
+int
+AUPluginUI::get_preferred_height ()
+{
+       return -1;
+}
index 33f2d3471b33e58c1e31d5c16956f4e82f21ccc3..2d59be1b5e2dd7f2909b6fb2085b919a2187e422 100644 (file)
@@ -59,6 +59,7 @@ if gtkardour['FFT_ANALYSIS']:
 
 if gtkardour['COREAUDIO']:
        gtkardour.Append(CCFLAGS='-DHAVE_COREAUDIO')
+       gtkardour.Merge([libraries['appleutility']])
 
 skipped_files=Split("""
 connection_editor.cc
index ce3b1935c50e71427c0b0e277a0a981d4ac55f6a..bf644f3e845d91ab2fd95cb679a700d496c0e355 100755 (executable)
@@ -2,7 +2,7 @@
 
 export ARDOUR_PATH=./glade:./pixmaps:.
 
-export LD_LIBRARY_PATH=../libs/surfaces/control_protocol:../libs/ardour:../libs/midi++2:../libs/pbd:../libs/soundtouch:../libs/gtkmm2ext:../libs/sigc++2:../libs/glibmm2:../libs/gtkmm2/atk:../libs/gtkmm2/pango:../libs/gtkmm2/gdk:../libs/gtkmm2/gtk:../libs/libgnomecanvasmm:../libs/libsndfile:$LD_LIBRARY_PATH
+export LD_LIBRARY_PATH=../libs/surfaces/control_protocol:../libs/ardour:../libs/midi++2:../libs/pbd:../libs/soundtouch:../libs/gtkmm2ext:../libs/sigc++2:../libs/glibmm2:../libs/gtkmm2/atk:../libs/gtkmm2/pango:../libs/gtkmm2/gdk:../libs/gtkmm2/gtk:../libs/libgnomecanvasmm:../libs/libsndfile:../libs/appleutility:$LD_LIBRARY_PATH
 
 # DYLD_LIBRARY_PATH is for darwin.
 export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
index 6945ea133836cf55687a94165ec25394313e90ad..d589f6ce5566632fc079d9ac3562ec4e614f8d41 100644 (file)
@@ -219,6 +219,14 @@ style "mute_button" = "small_button"
        fg[PRELIGHT] = { 0, 0, 0 }
 }
 
+
+style "multiline_combo" = "small_button"
+{
+       font_name = "sans 8"
+       xthickness = 0
+       ythickness = 0
+}
+
 style "mixer_mute_button" = "mute_button"
 {
        font_name = "sans 7"
@@ -951,6 +959,7 @@ widget "*TrackRecordEnableButton" style "track_rec_enable_button"
 widget "*TrackRecordEnableButton*" style "track_rec_enable_button"
 widget "*TrackMuteButton*" style "mute_button"
 widget "*TrackLoopButton*" style "track_loop_button"
+widget "*PanAutomationLineSelector*" style "multiline_combo"
 widget "*EditorTimeButton*" style "time_button"
 widget "*EditorMixerButton*" style "default_buttons_menus"
 widget "*SoloButton*" style "solo_button"
index 827a9673617c0df120f777bcdf41da3e11f3b60e..203d64c3c3501a800702f5d6336f079bd54fbe9f 100644 (file)
@@ -1326,6 +1326,7 @@ ARDOUR_UI::start_engine ()
                           settings for a new session 
                        */
                        session->save_state ("");
+                        session->save_history ();
                }
 
                /* there is too much going on, in too many threads, for us to 
@@ -1499,6 +1500,7 @@ ARDOUR_UI::save_state_canfail (string name)
                }
 
                if ((ret = session->save_state (name)) != 0) {
+                        session->save_history();
                        return ret;
                }
        }
index 25f3068a813d39c04d0b38157e98f79dee0e6c7c..d2cc3e1e1cc084779ca1cd6c7a7c3a32cc076271 100644 (file)
@@ -156,6 +156,7 @@ ARDOUR_UI::unload_session ()
                        
                case 1:
                        session->save_state ("");
+                        session->save_history();
                        break;
                }
        }
index b12713433b5541a2ca2648a928711e64bc6a6b77..dff2300529c9ce0f86358bc1effc60235a08cf6d 100644 (file)
@@ -28,6 +28,7 @@
 #include <ardour/audioregion.h>
 #include <ardour/audiosource.h>
 #include <ardour/audio_diskstream.h>
+#include <pbd/memento_command.h>
 
 #include "streamview.h"
 #include "audio_region_view.h"
@@ -896,18 +897,20 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
        gain_line->view_to_model_y (y);
 
        trackview.session().begin_reversible_command (_("add gain control point"));
-       trackview.session().add_undo (audio_region().envelope().get_memento());
+       XMLNode &before = audio_region().envelope().get_state();
 
 
        if (!audio_region().envelope_active()) {
-               trackview.session().add_undo( bind( mem_fun(audio_region(), &AudioRegion::set_envelope_active), false) );
+               XMLNode &before = audio_region().get_state();
                audio_region().set_envelope_active(true);
-               trackview.session().add_redo( bind( mem_fun(audio_region(), &AudioRegion::set_envelope_active), true) );
+               XMLNode &after = audio_region().get_state();
+               trackview.session().add_command (new MementoCommand<AudioRegion>(audio_region(), before, after));
        }
 
        audio_region().envelope().add (fx, y);
        
-       trackview.session().add_redo_no_execute (audio_region().envelope().get_memento());
+       XMLNode &after = audio_region().envelope().get_state();
+       trackview.session().add_command (new MementoCommand<Curve>(audio_region().envelope(), before, after));
        trackview.session().commit_reversible_command ();
 }
 
index 376e05aa4c7b6ac4ba48e0dec645154f9c10b073..9ae94d1fe0ac6c201fd9b3136236fb2b6a80951a 100644 (file)
@@ -31,6 +31,7 @@
 #include <pbd/error.h>
 #include <pbd/stl_delete.h>
 #include <pbd/whitespace.h>
+#include <pbd/memento_command.h>
 
 #include <gtkmm2ext/gtk_ui.h>
 #include <gtkmm2ext/selector.h>
index b87a71ca875aa1699dc861659856f08371a4ec0b..5c09ddd49b35e1c90d9d8e7f3dcfe07a81ef2394 100644 (file)
@@ -23,6 +23,7 @@
 #include <vector>
 
 #include <pbd/stl_delete.h>
+#include <pbd/memento_command.h>
 
 #include <ardour/automation_event.h>
 #include <ardour/curve.h>
@@ -887,7 +888,7 @@ AutomationLine::start_drag (ControlPoint* cp, float fraction)
        }
 
        trackview.editor.current_session()->begin_reversible_command (str);
-       trackview.editor.current_session()->add_undo (get_memento());
+       trackview.editor.current_session()->add_command (new MementoUndoCommand<AutomationLine>(*this, get_state()));
        
        first_drag_fraction = fraction;
        last_drag_fraction = fraction;
@@ -936,7 +937,7 @@ AutomationLine::end_drag (ControlPoint* cp)
 
                update_pending = false;
 
-               trackview.editor.current_session()->add_redo_no_execute (get_memento());
+               trackview.editor.current_session()->add_command (new MementoRedoCommand<AutomationLine>(*this, get_state()));
                trackview.editor.current_session()->commit_reversible_command ();
                trackview.editor.current_session()->set_dirty ();
        }
@@ -1013,11 +1014,11 @@ AutomationLine::remove_point (ControlPoint& cp)
        model_representation (cp, mr);
 
        trackview.editor.current_session()->begin_reversible_command (_("remove control point"));
-       trackview.editor.current_session()->add_undo (get_memento());
+        XMLNode &before = get_state();
 
        alist.erase (mr.start, mr.end);
 
-       trackview.editor.current_session()->add_redo_no_execute (get_memento());
+       trackview.editor.current_session()->add_command(new MementoCommand<AutomationLine>(*this, before, get_state()));
        trackview.editor.current_session()->commit_reversible_command ();
        trackview.editor.current_session()->set_dirty ();
 }
@@ -1225,9 +1226,9 @@ void
 AutomationLine::clear ()
 {
        /* parent must create command */
-       trackview.editor.current_session()->add_undo (get_memento());
+        XMLNode &before = get_state();
        alist.clear();
-       trackview.editor.current_session()->add_redo_no_execute (get_memento());
+       trackview.editor.current_session()->add_command (new MementoCommand<AutomationLine>(*this, before, get_state()));
        trackview.editor.current_session()->commit_reversible_command ();
        trackview.editor.current_session()->set_dirty ();
 }
@@ -1266,3 +1267,16 @@ AutomationLine::hide_all_but_selected_control_points ()
                }
        }
 }
+
+XMLNode &AutomationLine::get_state(void)
+{
+    // TODO
+    return alist.get_state();
+}
+
+int AutomationLine::set_state(const XMLNode &node)
+{
+    // TODO
+    alist.set_state(node);
+    return 0;
+}
index e922de6c8075e229e84093d4e0d112f819141de0..ec86b7455fd2cfddf4c6d3de4cd6997698abbe64 100644 (file)
@@ -94,7 +94,7 @@ class ControlPoint
        ShapeType _shape;
 };
 
-class AutomationLine : public sigc::trackable
+class AutomationLine : public sigc::trackable, public Stateful
 {
   public:
         AutomationLine (const string & name, TimeAxisView&, ArdourCanvas::Group&, ARDOUR::AutomationList&);
@@ -158,7 +158,12 @@ class AutomationLine : public sigc::trackable
        bool is_last_point (ControlPoint &);
        bool is_first_point (ControlPoint &);
 
+       XMLNode& get_state (void);
+       int set_state (const XMLNode&);
+
+        PBD::ID id() { return _id; }
   protected:
+        PBD::ID _id;
        string _name;
        guint32 _height;
        uint32_t _line_color;
index 02a88b578bb56d7c11c0e6542ee78fdd772b9d8b..7025a11178371dfef981b576f72e890af63a2dcd 100644 (file)
@@ -1,4 +1,5 @@
 #include <ardour/route.h>
+#include <pbd/memento_command.h>
 
 #include "ardour_ui.h"
 #include "automation_time_axis.h"
@@ -40,6 +41,7 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Ro
        auto_write_item = 0;
        auto_play_item = 0;
        ignore_state_request = false;
+       first_call_to_set_height = true;
 
        //      base_rect = gnome_canvas_item_new (GNOME_CANVAS_GROUP(canvas_display),
        //                       gnome_canvas_simplerect_get_type(),
@@ -72,6 +74,8 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Ro
        clear_button.set_name ("TrackVisualButton");
        hide_button.set_name ("TrackRemoveButton");
 
+       controls_table.set_no_show_all();
+
        ARDOUR_UI::instance()->tooltips().set_tip(height_button, _("track height"));
        ARDOUR_UI::instance()->tooltips().set_tip(auto_button, _("automation state"));
        ARDOUR_UI::instance()->tooltips().set_tip(clear_button, _("clear track"));
@@ -98,7 +102,7 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Ro
                }
        }
        name_label.set_text (shortpname);
-       name_label.set_alignment (1.0, 0.5);
+       name_label.set_alignment (Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
 
        if (nomparent.length()) {
 
@@ -114,7 +118,7 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Ro
 
                plugname = new Label (pname);
                plugname->set_name (X_("TrackPlugName"));
-               plugname->set_alignment (1.0, 0.5);
+               plugname->show();
                name_label.set_name (X_("TrackParameterName"));
                controls_table.remove (name_hbox);
                controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
@@ -138,8 +142,8 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Ro
        controls_table.attach (hide_button, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
        controls_table.attach (height_button, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
 
-       controls_table.attach (auto_button, 6, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-       controls_table.attach (clear_button, 6, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+       controls_table.attach (auto_button, 5, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+       controls_table.attach (clear_button, 5, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
 
        controls_table.show_all ();
 
@@ -281,11 +285,11 @@ AutomationTimeAxisView::set_height (TrackHeight ht)
        uint32_t h = height_to_pixels (ht);
        bool changed = (height != (uint32_t) h);
 
+       bool changed_between_small_and_normal = ( (ht == Small || ht == Smaller) ^ (height_style == Small || height_style == Smaller) );
+
        TimeAxisView* state_parent = get_parent_with_state ();
        XMLNode* xml_node = state_parent->get_child_xml_node (_state_name);
 
-       //controls_table.show_all ();
-
        TimeAxisView::set_height (ht);
        base_rect->property_y2() = h;
 
@@ -297,117 +301,88 @@ AutomationTimeAxisView::set_height (TrackHeight ht)
                (*i)->set_height ();
        }
 
+
        switch (ht) {
        case Largest:
                xml_node->add_property ("track_height", "largest");
-               controls_table.remove (name_hbox);
-               if (plugname) {
-                       if (plugname_packed) {
-                               controls_table.remove (*plugname);
-                               plugname_packed = false;
-                       }
-                       controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-                       plugname_packed = true;
-                       controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-               } else {
-                       controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-               }
-               controls_table.show_all ();
-
-               hide_name_entry ();
-               show_name_label ();
                break;
 
        case Large:
                xml_node->add_property ("track_height", "large");
-               controls_table.remove (name_hbox);
-               if (plugname) {
-                       if (plugname_packed) {
-                               controls_table.remove (*plugname);
-                               plugname_packed = false;
-                       }
-                       controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-                       plugname_packed = true;
-               } else {
-                       controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-               }
-               controls_table.show_all ();
-               hide_name_entry ();
-               show_name_label ();
                break;
 
        case Larger:
                xml_node->add_property ("track_height", "larger");
-               controls_table.remove (name_hbox);
-               if (plugname) {
-                       if (plugname_packed) {
-                               controls_table.remove (*plugname);
-                               plugname_packed = false;
-                       }
-                       controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-                       plugname_packed = true;
-               } else {
-                       controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-               }
-               controls_table.show_all ();
-               hide_name_entry ();
-               show_name_label ();
                break;
 
        case Normal:
                xml_node->add_property ("track_height", "normal");
-               controls_table.remove (name_hbox);
-               if (plugname) {
-                       if (plugname_packed) {
-                               controls_table.remove (*plugname);
-                               plugname_packed = false;
-                       }
-                       controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-                       plugname_packed = true;
-                       controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-               } else {
-                       controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-               }
-               controls_table.show_all ();
-               hide_name_entry ();
-               show_name_label ();
                break;
 
        case Smaller:
                xml_node->add_property ("track_height", "smaller");
-               controls_table.remove (name_hbox);
-               if (plugname) {
-                       if (plugname_packed) {
-                               controls_table.remove (*plugname);
-                               plugname_packed = false;
-                       }
-               }
-               controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-               controls_table.hide_all ();
-               hide_name_entry ();
-               show_name_label ();
-               name_hbox.show_all ();
-               controls_table.show ();
                break;
 
        case Small:
                xml_node->add_property ("track_height", "small");
-               controls_table.remove (name_hbox);
-               if (plugname) {
-                       if (plugname_packed) {
-                               controls_table.remove (*plugname);
-                               plugname_packed = false;
-                       }
-               } 
-               controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-               controls_table.hide_all ();
-               hide_name_entry ();
-               show_name_label ();
-               name_hbox.show_all ();
-               controls_table.show ();
                break;
        }
 
+       if (changed_between_small_and_normal || first_call_to_set_height) {
+               first_call_to_set_height = false;
+               switch (ht) {
+                       case Largest:
+                       case Large:
+                       case Larger:
+                       case Normal:
+
+                               controls_table.remove (name_hbox);
+
+                               if (plugname) {
+                                       if (plugname_packed) {
+                                               controls_table.remove (*plugname);
+                                               plugname_packed = false;
+                                       }
+                                       controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+                                       plugname_packed = true;
+                                       controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+                               } else {
+                                       controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+                               }
+                               hide_name_entry ();
+                               show_name_label ();
+                               name_hbox.show_all ();
+
+                               auto_button.show();
+                               height_button.show();
+                               clear_button.show();
+                               hide_button.show_all();
+                               break;
+
+                       case Smaller:
+                       case Small:
+
+                               controls_table.remove (name_hbox);
+                               if (plugname) {
+                                       if (plugname_packed) {
+                                               controls_table.remove (*plugname);
+                                               plugname_packed = false;
+                                       }
+                               }
+                               controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+                               controls_table.hide_all ();
+                               hide_name_entry ();
+                               show_name_label ();
+                               name_hbox.show_all ();
+
+                               auto_button.hide();
+                               height_button.hide();
+                               clear_button.hide();
+                               hide_button.hide();
+                               break;
+               }
+       }
+
        if (changed) {
                /* only emit the signal if the height really changed */
                route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
@@ -501,13 +476,13 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel
        AutomationList& alist (line.the_list());
        bool ret = false;
 
-       _session.add_undo (alist.get_memento());
+        XMLNode &before = alist.get_state();
 
        switch (op) {
        case Cut:
                if ((what_we_got = alist.cut (selection.time.front().start, selection.time.front().end)) != 0) {
                        editor.get_cut_buffer().add (what_we_got);
-                       _session.add_redo_no_execute (alist.get_memento());
+                       _session.add_command(new MementoCommand<AutomationList>(alist, before, alist.get_state()));
                        ret = true;
                }
                break;
@@ -519,7 +494,7 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel
 
        case Clear:
                if ((what_we_got = alist.cut (selection.time.front().start, selection.time.front().end)) != 0) {
-                       _session.add_redo_no_execute (alist.get_memento());
+                       _session.add_command(new MementoCommand<AutomationList>(alist, before, alist.get_state()));
                        delete what_we_got;
                        what_we_got = 0;
                        ret = true;
@@ -551,7 +526,7 @@ AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection&
 {
        AutomationList& alist (line.the_list());
 
-       _session.add_undo (alist.get_memento());
+       _session.add_command (new MementoUndoCommand<AutomationList>(alist, alist.get_state()));
 
        for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
 
@@ -582,7 +557,7 @@ AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointS
        AutomationList& alist (line.the_list());
        bool ret = false;
 
-       _session.add_undo (alist.get_memento());
+        XMLNode &before = alist.get_state();
 
        for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
 
@@ -594,7 +569,7 @@ AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointS
                case Cut:
                        if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) {
                                editor.get_cut_buffer().add (what_we_got);
-                               _session.add_redo_no_execute (alist.get_memento());
+                               _session.add_command (new MementoCommand<AutomationList>(alist, before, alist.get_state()));
                                ret = true;
                        }
                        break;
@@ -606,7 +581,7 @@ AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointS
                        
                case Clear:
                        if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) {
-                               _session.add_redo_no_execute (alist.get_memento());
+                               _session.add_command (new MementoCommand<AutomationList>(alist, before, alist.get_state()));
                                delete what_we_got;
                                what_we_got = 0;
                                ret = true;
@@ -663,9 +638,9 @@ AutomationTimeAxisView::paste_one (AutomationLine& line, jack_nframes_t pos, flo
                (*x)->value = foo;
        }
 
-       _session.add_undo (alist.get_memento());
+        XMLNode &before = alist.get_state();
        alist.paste (copy, pos, times);
-       _session.add_redo_no_execute (alist.get_memento());
+       _session.add_command (new MementoCommand<AutomationList>(alist, before, alist.get_state()));
 
        return true;
 }
index 6de11a7c6d90323f6312ea8f6d84284b2e2a728a..0cd9acc034c47a76ad5344a667516c01d8898cb7 100644 (file)
@@ -84,6 +84,8 @@ class AutomationTimeAxisView : public TimeAxisView {
        string _state_name;
        bool    in_destructor;
 
+       bool    first_call_to_set_height;
+
        Gtk::Button        hide_button;
        Gtk::Button        height_button;
        Gtk::Button        clear_button;
index 518ef7217a2933ede038639747015e010a453303..513251085c6d9f8c195bb684e400ae0e9c8762cc 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <pbd/convert.h>
 #include <pbd/error.h>
+#include <pbd/memento_command.h>
 
 #include <gtkmm/image.h>
 #include <gdkmm/color.h>
@@ -2878,8 +2879,8 @@ void
 Editor::begin_reversible_command (string name)
 {
        if (session) {
-               UndoAction ua = get_memento();
-               session->begin_reversible_command (name, &ua);
+                before = &get_state();
+               session->begin_reversible_command (name);
        }
 }
 
@@ -2887,8 +2888,7 @@ void
 Editor::commit_reversible_command ()
 {
        if (session) {
-               UndoAction ua = get_memento();
-               session->commit_reversible_command (&ua);
+               session->commit_reversible_command (new MementoCommand<Editor>(*this, *before, get_state()));
        }
 }
 
index 05a134157e6dd2f91748f664de2fa67fde68ac8a..3488c756ac4047c0a777a952791f8d7b0b6c07de 100644 (file)
@@ -142,6 +142,8 @@ class Editor : public PublicEditor
        XMLNode& get_state ();
        int set_state (const XMLNode& );
 
+        PBD::ID id() { return _id; }
+
        void set_mouse_mode (Editing::MouseMode, bool force=true);
        void step_mouse_mode (bool next);
        Editing::MouseMode current_mouse_mode () { return mouse_mode; }
@@ -346,6 +348,8 @@ class Editor : public PublicEditor
        ARDOUR::AudioEngine& engine;
        bool                 constructed;
 
+        PBD::ID _id;
+
        PlaylistSelector* _playlist_selector;
 
        void          set_frames_per_unit (double);
@@ -1595,13 +1599,14 @@ class Editor : public PublicEditor
 
        UndoAction get_memento() const;
 
+        XMLNode *before; /* used in *_reversible_command */
        void begin_reversible_command (string cmd_name);
        void commit_reversible_command ();
 
        /* visual history */
 
        UndoHistory visual_history;
-       UndoCommand current_visual_command;
+       UndoTransaction current_visual_command;
 
        void begin_reversible_visual_command (const string & cmd_name);
        void commit_reversible_visual_command ();
index f8c632f08a0fc4b0883c581849712b79d9112369..7524f9605cab34eb48c87c58b8fd9f9a61389157 100644 (file)
@@ -31,6 +31,7 @@
 #include <ardour/audio_track.h>
 #include <ardour/audioplaylist.h>
 #include <ardour/audiofilesource.h>
+#include <pbd/memento_command.h>
 
 #include "ardour_ui.h"
 #include "editor.h"
@@ -320,9 +321,9 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32
                        
                        AudioRegion* copy = new AudioRegion (region);
                        begin_reversible_command (_("insert sndfile"));
-                       session->add_undo (playlist->get_memento());
+                        XMLNode &before = playlist->get_state();
                        playlist->add_region (*copy, pos);
-                       session->add_redo_no_execute (playlist->get_memento());
+                       session->add_command (new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
                        commit_reversible_command ();
 
                        pos += region.length();
index d2b7c1160e5af6de11e273ebc47bdbe6528c4ca1..f48d860d15d54eb1bd01d50902cbd99e734310c8 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <ardour/audioregion.h>
 #include <ardour/playlist.h>
+#include <pbd/memento_command.h>
 
 #include "editor.h"
 #include "region_view.h"
@@ -102,11 +103,12 @@ Editor::kbd_mute_unmute_region ()
 {
        if (entered_regionview) {
                begin_reversible_command (_("mute region"));
-               session->add_undo (entered_regionview->region().playlist()->get_memento());
+               XMLNode &before = entered_regionview->region().playlist()->get_state();
                
            entered_regionview->region().set_muted (!entered_regionview->region().muted());
                
-               session->add_redo_no_execute (entered_regionview->region().playlist()->get_memento());
+               XMLNode &after = entered_regionview->region().playlist()->get_state();
+               session->add_command (new MementoCommand<ARDOUR::Playlist>(*(entered_regionview->region().playlist()), before, after));
                commit_reversible_command();
        }
 }
index f34b8590a48a9d0e079a67c7b290354b53ea5daf..ccc1415888449f1c92bfac39f810de0106c48f25 100644 (file)
@@ -26,6 +26,7 @@
 #include <gtkmm2ext/gtk_ui.h>
 
 #include <ardour/location.h>
+#include <pbd/memento_command.h>
 
 #include "editor.h"
 #include "marker.h"
@@ -290,9 +291,10 @@ Editor::mouse_add_new_marker (jack_nframes_t where)
        if (session) {
                Location *location = new Location (where, where, "mark", Location::IsMark);
                session->begin_reversible_command (_("add marker"));
-               session->add_undo (session->locations()->get_memento());
+                XMLNode &before = session->locations()->get_state();
                session->locations()->add (location, true);
-               session->add_redo_no_execute (session->locations()->get_memento());
+                XMLNode &after = session->locations()->get_state();
+               session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
                session->commit_reversible_command ();
        }
 }
@@ -329,9 +331,10 @@ gint
 Editor::really_remove_marker (Location* loc)
 {
        session->begin_reversible_command (_("remove marker"));
-       session->add_undo (session->locations()->get_memento());
+       XMLNode &before = session->locations()->get_state();
        session->locations()->remove (loc);
-       session->add_redo_no_execute (session->locations()->get_memento());
+       XMLNode &after = session->locations()->get_state();
+       session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
        session->commit_reversible_command ();
        return FALSE;
 }
@@ -838,12 +841,13 @@ Editor::marker_menu_rename ()
        }
 
        begin_reversible_command ( _("rename marker") );
-       session->add_undo( session->locations()->get_memento() );
+        XMLNode &before = session->locations()->get_state();
 
        dialog.get_result(txt);
        loc->set_name (txt);
        
-       session->add_redo_no_execute( session->locations()->get_memento() );
+        XMLNode &after = session->locations()->get_state();
+       session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
        commit_reversible_command ();
 }
 
@@ -868,16 +872,18 @@ Editor::new_transport_marker_menu_set_loop ()
 
        if ((tll = transport_loop_location()) == 0) {
                Location* loc = new Location (temp_location->start(), temp_location->end(), _("Loop"),  Location::IsAutoLoop);
-               session->add_undo (session->locations()->get_memento());
+                XMLNode &before = session->locations()->get_state();
                session->locations()->add (loc, true);
                session->set_auto_loop_location (loc);
-               session->add_redo_no_execute (session->locations()->get_memento());
+                XMLNode &after = session->locations()->get_state();
+               session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
        }
        else {
-               session->add_undo (retype_return<void>(bind (mem_fun (*tll, &Location::set), tll->start(), tll->end())));
-               session->add_redo (retype_return<void>(bind (mem_fun (*tll, &Location::set), temp_location->start(), temp_location->end())));
+                XMLNode &before = tll->get_state();
                tll->set_hidden (false, this);
                tll->set (temp_location->start(), temp_location->end());
+                XMLNode &after = tll->get_state();
+                session->add_command (new MementoCommand<Location>(*tll, before, after));
        }
        
        commit_reversible_command ();
@@ -894,15 +900,17 @@ Editor::new_transport_marker_menu_set_punch ()
 
        if ((tpl = transport_punch_location()) == 0) {
                tpl = new Location (temp_location->start(), temp_location->end(), _("Punch"), Location::IsAutoPunch);
-               session->add_undo (session->locations()->get_memento());
+                XMLNode &before = session->locations()->get_state();
                session->locations()->add (tpl, true);
                session->set_auto_punch_location (tpl);
-               session->add_redo_no_execute (session->locations()->get_memento());
+                XMLNode &after = session->locations()->get_state();
+               session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
        } else {
-               session->add_undo (retype_return<void>(bind (mem_fun (*tpl, &Location::set), tpl->start(), tpl->end())));
-               session->add_redo (retype_return<void>(bind (mem_fun (*tpl, &Location::set), temp_location->start(), temp_location->end())));
+                XMLNode &before = tpl->get_state();
                tpl->set_hidden(false, this);
                tpl->set(temp_location->start(), temp_location->end());
+                XMLNode &after = tpl->get_state();
+                session->add_command (new MementoCommand<Location>(*tpl, before, after));
        }
        
        commit_reversible_command ();
index 9b7ad99acb5b54168c4324fe685b996ae7786195..a05dcba9e3131101b636bed3fe2335d776817bd7 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <pbd/error.h>
 #include <gtkmm2ext/utils.h>
+#include <pbd/memento_command.h>
 
 #include "ardour_ui.h"
 #include "editor.h"
@@ -1818,9 +1819,14 @@ Editor::fade_in_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* even
        }
 
        begin_reversible_command (_("change fade in length"));
-       session->add_undo (arv->region().get_memento());
+        XMLNode &before = arv->audio_region().get_state();
+
        arv->audio_region().set_fade_in_length (fade_length);
-       session->add_redo_no_execute (arv->region().get_memento());
+
+        XMLNode &after = arv->audio_region().get_state();
+        session->add_command(new MementoCommand<ARDOUR::AudioRegion>(arv->audio_region(),
+                                                                     before,
+                                                                     after));
        commit_reversible_command ();
        fade_in_drag_motion_callback (item, event);
 }
@@ -1910,9 +1916,12 @@ Editor::fade_out_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* eve
        }
 
        begin_reversible_command (_("change fade out length"));
-       session->add_undo (arv->region().get_memento());
+        XMLNode &before = arv->region().get_state();
+
        arv->audio_region().set_fade_out_length (fade_length);
-       session->add_redo_no_execute (arv->region().get_memento());
+
+        XMLNode &after = arv->region().get_state();
+        session->add_command(new MementoCommand<ARDOUR::Region>(arv->region(), before, after));
        commit_reversible_command ();
 
        fade_out_drag_motion_callback (item, event);
@@ -2154,7 +2163,7 @@ Editor::marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
 
        begin_reversible_command ( _("move marker") );
-       session->add_undo( session->locations()->get_memento() );
+       XMLNode &before = session->locations()->get_state();
        
        Location * location = find_location_from_marker (marker, is_start);
        
@@ -2166,7 +2175,8 @@ Editor::marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                }
        }
 
-       session->add_redo_no_execute( session->locations()->get_memento() );
+       XMLNode &after = session->locations()->get_state();
+       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
        commit_reversible_command ();
        
        marker_drag_line->hide();
@@ -2280,9 +2290,10 @@ Editor::meter_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
        
        if (drag_info.copy == true) {
                begin_reversible_command (_("copy meter mark"));
-               session->add_undo (map.get_memento());
+                XMLNode &before = map.get_state();
                map.add_meter (marker->meter(), when);
-               session->add_redo_no_execute (map.get_memento());
+               XMLNode &after = map.get_state();
+                session->add_command(new MementoCommand<TempoMap>(map, before, after));
                commit_reversible_command ();
                
                // delete the dummy marker we used for visual representation of copying.
@@ -2290,9 +2301,10 @@ Editor::meter_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
                delete marker;
        } else {
                begin_reversible_command (_("move meter mark"));
-               session->add_undo (map.get_memento());
+               XMLNode &before = map.get_state();
                map.move_meter (marker->meter(), when);
-               session->add_redo_no_execute (map.get_memento());
+               XMLNode &after = map.get_state();
+                session->add_command(new MementoCommand<TempoMap>(map, before, after));
                commit_reversible_command ();
        }
 }
@@ -2407,12 +2419,13 @@ Editor::tempo_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
        
        TempoMap& map (session->tempo_map());
        map.bbt_time (drag_info.last_pointer_frame, when);
-       
+
        if (drag_info.copy == true) {
                begin_reversible_command (_("copy tempo mark"));
-               session->add_undo (map.get_memento());
+               XMLNode &before = map.get_state();
                map.add_tempo (marker->tempo(), when);
-               session->add_redo_no_execute (map.get_memento());
+               XMLNode &after = map.get_state();
+               session->add_command (new MementoCommand<TempoMap>(map, before, after));
                commit_reversible_command ();
                
                // delete the dummy marker we used for visual representation of copying.
@@ -2420,9 +2433,10 @@ Editor::tempo_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
                delete marker;
        } else {
                begin_reversible_command (_("move tempo mark"));
-               session->add_undo (map.get_memento());
+                XMLNode &before = map.get_state();
                map.move_tempo (marker->tempo(), when);
-               session->add_redo_no_execute (map.get_memento());
+                XMLNode &after = map.get_state();
+                session->add_command (new MementoCommand<TempoMap>(map, before, after));
                commit_reversible_command ();
        }
 }
@@ -2786,7 +2800,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        
                        insert_result = affected_playlists.insert (to_playlist);
                        if (insert_result.second) {
-                               session->add_undo (to_playlist->get_memento ());
+                               session->add_command (new MementoUndoCommand<Playlist>(*to_playlist, to_playlist->get_state()));
                        }
                        
                        latest_regionview = 0;
@@ -3224,7 +3238,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                                        insert_result = motion_frozen_playlists.insert (pl);
                                        if (insert_result.second) {
                                                pl->freeze();
-                                               session->add_undo(pl->get_memento());
+                                               session->add_command(new MementoUndoCommand<Playlist>(*pl, pl->get_state()));
                                        }
                                }
                        }
@@ -3352,7 +3366,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                        insert_result = motion_frozen_playlists.insert(to_playlist);
                        if (insert_result.second) {
                                to_playlist->freeze();
-                               session->add_undo(to_playlist->get_memento());
+                                session->add_command(new MementoUndoCommand<Playlist>(*to_playlist, to_playlist->get_state()));
                        }
 
                }
@@ -3434,7 +3448,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
   out:
        for (set<Playlist*>::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) {
                (*p)->thaw ();
-               session->add_redo_no_execute ((*p)->get_memento());
+               session->add_command (new MementoRedoCommand<Playlist>(*(*p), (*p)->get_state()));
        }
 
        motion_frozen_playlists.clear ();
@@ -3629,9 +3643,10 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
 
        Playlist* playlist = clicked_trackview->playlist();
 
-       session->add_undo (playlist->get_memento ());
+        before = &(playlist->get_state());
        clicked_trackview->playlist()->add_region (*region, selection->time[clicked_selection].start);
-       session->add_redo_no_execute (playlist->get_memento ());
+        XMLNode &after = playlist->get_state();
+       session->add_command(new MementoCommand<Playlist>(*playlist, *before, after));
 
        commit_reversible_command ();
        
@@ -3998,7 +4013,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        Playlist * pl = (*i)->region().playlist();
                        insert_result = motion_frozen_playlists.insert (pl);
                        if (insert_result.second) {
-                               session->add_undo (pl->get_memento());
+                                session->add_command(new MementoUndoCommand<Playlist>(*pl, pl->get_state()));
                        }
                }
        }
@@ -4188,8 +4203,8 @@ Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
                
                for (set<Playlist*>::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) {
                        //(*p)->thaw ();
-                       session->add_redo_no_execute ((*p)->get_memento());
-               }
+                        session->add_command (new MementoRedoCommand<Playlist>(*(*p), (*p)->get_state()));
+                }
                
                motion_frozen_playlists.clear ();
 
@@ -4222,18 +4237,22 @@ Editor::point_trim (GdkEvent* event)
                             i != selection->regions.by_layer().end(); ++i)
                        {
                                if (!(*i)->region().locked()) {
-                                       session->add_undo ((*i)->region().playlist()->get_memento());
+                                        Playlist *pl = (*i)->region().playlist();
+                                        XMLNode &before = pl->get_state();
                                        (*i)->region().trim_front (new_bound, this);    
-                                       session->add_redo_no_execute ((*i)->region().playlist()->get_memento());
+                                        XMLNode &after = pl->get_state();
+                                        session->add_command(new MementoCommand<Playlist>(*pl, before, after));
                                }
                        }
 
                } else {
 
                        if (!rv->region().locked()) {
-                               session->add_undo (rv->region().playlist()->get_memento());
+                                Playlist *pl = rv->region().playlist();
+                               XMLNode &before = pl->get_state();
                                rv->region().trim_front (new_bound, this);      
-                               session->add_redo_no_execute (rv->region().playlist()->get_memento());
+                                XMLNode &after = pl->get_state();
+                               session->add_command(new MementoCommand<Playlist>(*pl, before, after));
                        }
                }
 
@@ -4249,18 +4268,22 @@ Editor::point_trim (GdkEvent* event)
                        for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i)
                        {
                                if (!(*i)->region().locked()) {
-                                       session->add_undo ((*i)->region().playlist()->get_memento());
+                                        Playlist *pl = (*i)->region().playlist();
+                                       XMLNode &before = pl->get_state();
                                        (*i)->region().trim_end (new_bound, this);
-                                       session->add_redo_no_execute ((*i)->region().playlist()->get_memento());        
+                                       XMLNode &after = pl->get_state();
+                                       session->add_command(new MementoCommand<Playlist>(*pl, before, after));
                                }
                        }
 
                } else {
 
                        if (!rv->region().locked()) {
-                               session->add_undo (rv->region().playlist()->get_memento());
+                                Playlist *pl = rv->region().playlist();
+                               XMLNode &before = pl->get_state();
                                rv->region().trim_end (new_bound, this);
-                               session->add_redo_no_execute (rv->region().playlist()->get_memento());  
+                                XMLNode &after = pl->get_state();
+                               session->add_command (new MementoCommand<Playlist>(*pl, before, after));
                        }
                }
 
@@ -4282,7 +4305,8 @@ Editor::thaw_region_after_trim (RegionView& rv)
        }
 
        region.thaw (_("trimmed region"));
-       session->add_redo_no_execute (region.playlist()->get_memento());
+        XMLNode &after = region.playlist()->get_state();
+       session->add_command (new MementoRedoCommand<Playlist>(*(region.playlist()), after));
 
        AudioRegionView* arv = dynamic_cast<AudioRegionView*>(&rv);
        if (arv)
@@ -4421,16 +4445,19 @@ Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event)
 
                switch (range_marker_op) {
                case CreateRangeMarker:
+                   {
                        begin_reversible_command (_("new range marker"));
-                       session->add_undo (session->locations()->get_memento());
+                        XMLNode &before = session->locations()->get_state();
                        newloc = new Location(temp_location->start(), temp_location->end(), "unnamed", Location::IsRangeMarker);
                        session->locations()->add (newloc, true);
-                       session->add_redo_no_execute (session->locations()->get_memento());
+                        XMLNode &after = session->locations()->get_state();
+                       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
                        commit_reversible_command ();
                        
                        range_bar_drag_rect->hide();
                        range_marker_drag_rect->hide();
                        break;
+                   }
 
                case CreateTransportMarker:
                        // popup menu to pick loop or punch
@@ -4804,9 +4831,10 @@ Editor::mouse_brush_insert_region (RegionView* rv, jack_nframes_t pos)
        Playlist* playlist = atv->playlist();
        double speed = atv->get_diskstream()->speed();
        
-       session->add_undo (playlist->get_memento());
+        XMLNode &before = playlist->get_state();
        playlist->add_region (*(new AudioRegion (arv->audio_region())), (jack_nframes_t) (pos * speed));
-       session->add_redo_no_execute (playlist->get_memento());
+        XMLNode &after = playlist->get_state();
+       session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
        
        // playlist is frozen, so we have to update manually
        
index af366e18d0e2efd73d8aeb0dad29ede2f93d3719..9b69026a013c01279f6638bcba8d29cb36454227 100644 (file)
@@ -28,6 +28,7 @@
 #include <pbd/error.h>
 #include <pbd/basename.h>
 #include <pbd/pthread_utils.h>
+#include <pbd/memento_command.h>
 
 #include <gtkmm2ext/utils.h>
 #include <gtkmm2ext/choice.h>
@@ -209,9 +210,10 @@ Editor::split_regions_at (jack_nframes_t where, RegionSelection& regions)
                        _new_regionviews_show_envelope = arv->envelope_visible();
                
                if (pl) {
-                       session->add_undo (pl->get_memento());
+                        XMLNode &before = pl->get_state();
                        pl->split_region ((*a)->region(), where);
-                       session->add_redo_no_execute (pl->get_memento());
+                        XMLNode &after = pl->get_state();
+                        session->add_command(new MementoCommand<Playlist>(*pl, before, after));
                }
 
                a = tmp;
@@ -231,9 +233,10 @@ Editor::remove_clicked_region ()
        Playlist* playlist = clicked_audio_trackview->playlist();
        
        begin_reversible_command (_("remove region"));
-       session->add_undo (playlist->get_memento());
+        XMLNode &before = playlist->get_state();
        playlist->remove_region (&clicked_regionview->region());
-       session->add_redo_no_execute (playlist->get_memento());
+        XMLNode &after = playlist->get_state();
+       session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
        commit_reversible_command ();
 }
 
@@ -406,9 +409,10 @@ Editor::nudge_forward (bool next)
                                distance = next_distance;
                        }
 
-                       session->add_undo (r.playlist()->get_memento());
+                        XMLNode &before = r.playlist()->get_state();
                        r.set_position (r.position() + distance, this);
-                       session->add_redo_no_execute (r.playlist()->get_memento());
+                        XMLNode &after = r.playlist()->get_state();
+                       session->add_command (new MementoCommand<Playlist>(*(r.playlist()), before, after));
                }
 
                commit_reversible_command ();
@@ -440,14 +444,15 @@ Editor::nudge_backward (bool next)
                                distance = next_distance;
                        }
 
-                       session->add_undo (r.playlist()->get_memento());
+                        XMLNode &before = r.playlist()->get_state();
                        
                        if (r.position() > distance) {
                                r.set_position (r.position() - distance, this);
                        } else {
                                r.set_position (0, this);
                        }
-                       session->add_redo_no_execute (r.playlist()->get_memento());
+                        XMLNode &after = r.playlist()->get_state();
+                       session->add_command(new MementoCommand<Playlist>(*(r.playlist()), before, after));
                }
 
                commit_reversible_command ();
@@ -480,9 +485,10 @@ Editor::nudge_forward_capture_offset ()
                for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
                        Region& r ((*i)->region());
                        
-                       session->add_undo (r.playlist()->get_memento());
+                       XMLNode &before = r.playlist()->get_state();
                        r.set_position (r.position() + distance, this);
-                       session->add_redo_no_execute (r.playlist()->get_memento());
+                       XMLNode &after = r.playlist()->get_state();
+                       session->add_command(new MementoCommand<Playlist>(*(r.playlist()), before, after));
                }
 
                commit_reversible_command ();
@@ -506,14 +512,15 @@ Editor::nudge_backward_capture_offset ()
                for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
                        Region& r ((*i)->region());
 
-                       session->add_undo (r.playlist()->get_memento());
+                        XMLNode &before = r.playlist()->get_state();
                        
                        if (r.position() > distance) {
                                r.set_position (r.position() - distance, this);
                        } else {
                                r.set_position (0, this);
                        }
-                       session->add_redo_no_execute (r.playlist()->get_memento());
+                        XMLNode &after = r.playlist()->get_state();
+                       session->add_command(new MementoCommand<Playlist>(*(r.playlist()), before, after));
                }
 
                commit_reversible_command ();
@@ -1290,9 +1297,10 @@ Editor::add_location_from_selection ()
        Location *location = new Location (start, end, "selection");
 
        session->begin_reversible_command (_("add marker"));
-       session->add_undo (session->locations()->get_memento());
+        XMLNode &before = session->locations()->get_state();
        session->locations()->add (location, true);
-       session->add_redo_no_execute (session->locations()->get_memento());
+        XMLNode &after = session->locations()->get_state();
+       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
        session->commit_reversible_command ();
 }
 
@@ -1303,9 +1311,10 @@ Editor::add_location_from_playhead_cursor ()
        
        Location *location = new Location (where, where, "mark", Location::IsMark);
        session->begin_reversible_command (_("add marker"));
-       session->add_undo (session->locations()->get_memento());
+        XMLNode &before = session->locations()->get_state();
        session->locations()->add (location, true);
-       session->add_redo_no_execute (session->locations()->get_memento());
+        XMLNode &after = session->locations()->get_state();
+       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
        session->commit_reversible_command ();
 }
 
@@ -1321,9 +1330,10 @@ Editor::add_location_from_audio_region ()
        
        Location *location = new Location (region.position(), region.last_frame(), region.name());
        session->begin_reversible_command (_("add marker"));
-       session->add_undo (session->locations()->get_memento());
+        XMLNode &before = session->locations()->get_state();
        session->locations()->add (location, true);
-       session->add_redo_no_execute (session->locations()->get_memento());
+        XMLNode &after = session->locations()->get_state();
+       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
        session->commit_reversible_command ();
 }
 
@@ -1739,9 +1749,10 @@ Editor::clear_markers ()
 {
        if (session) {
                session->begin_reversible_command (_("clear markers"));
-               session->add_undo (session->locations()->get_memento());
+                XMLNode &before = session->locations()->get_state();
                session->locations()->clear_markers ();
-               session->add_redo_no_execute (session->locations()->get_memento());
+                XMLNode &after = session->locations()->get_state();
+               session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
                session->commit_reversible_command ();
        }
 }
@@ -1751,7 +1762,7 @@ Editor::clear_ranges ()
 {
        if (session) {
                session->begin_reversible_command (_("clear ranges"));
-               session->add_undo (session->locations()->get_memento());
+                XMLNode &before = session->locations()->get_state();
                
                Location * looploc = session->locations()->auto_loop_location();
                Location * punchloc = session->locations()->auto_punch_location();
@@ -1761,7 +1772,8 @@ Editor::clear_ranges ()
                if (looploc) session->locations()->add (looploc);
                if (punchloc) session->locations()->add (punchloc);
                
-               session->add_redo_no_execute (session->locations()->get_memento());
+                XMLNode &after = session->locations()->get_state();
+               session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
                session->commit_reversible_command ();
        }
 }
@@ -1770,9 +1782,10 @@ void
 Editor::clear_locations ()
 {
        session->begin_reversible_command (_("clear locations"));
-       session->add_undo (session->locations()->get_memento());
+        XMLNode &before = session->locations()->get_state();
        session->locations()->clear ();
-       session->add_redo_no_execute (session->locations()->get_memento());
+        XMLNode &after = session->locations()->get_state();
+       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
        session->commit_reversible_command ();
        session->locations()->clear ();
 }
@@ -1820,9 +1833,9 @@ Editor::insert_region_list_drag (AudioRegion& region, int x, int y)
        snap_to (where);
        
        begin_reversible_command (_("insert dragged region"));
-       session->add_undo (playlist->get_memento());
+        XMLNode &before = playlist->get_state();
        playlist->add_region (*(new AudioRegion (region)), where, 1.0);
-       session->add_redo_no_execute (playlist->get_memento());
+       session->add_command(new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
        commit_reversible_command ();
 }
 
@@ -1856,9 +1869,9 @@ Editor::insert_region_list_selection (float times)
        Region* region = (*i)[region_list_columns.region];
 
        begin_reversible_command (_("insert region"));
-       session->add_undo (playlist->get_memento());
+        XMLNode &before = playlist->get_state();
        playlist->add_region (*(createRegion (*region)), edit_cursor->current_frame, times);
-       session->add_redo_no_execute (playlist->get_memento());
+       session->add_command(new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
        commit_reversible_command ();
 }
 
@@ -2283,7 +2296,9 @@ Editor::separate_region_from_selection ()
                                                begin_reversible_command (_("separate"));
                                                doing_undo = true;
                                        }
-                                       if (doing_undo) session->add_undo ((playlist)->get_memento());
+                                        XMLNode *before;
+                                       if (doing_undo) 
+                                            before = &(playlist->get_state());
                        
                                        /* XXX need to consider musical time selections here at some point */
 
@@ -2293,7 +2308,8 @@ Editor::separate_region_from_selection ()
                                                playlist->partition ((jack_nframes_t)((*t).start * speed), (jack_nframes_t)((*t).end * speed), true);
                                        }
 
-                                       if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
+                                       if (doing_undo) 
+                                            session->add_command(new MementoCommand<Playlist>(*playlist, *before, playlist->get_state()));
                                }
                        }
                }
@@ -2328,11 +2344,14 @@ Editor::separate_regions_using_location (Location& loc)
                        if (atv->is_audio_track()) {
                                        
                                if ((playlist = atv->playlist()) != 0) {
+                                        XMLNode *before;
                                        if (!doing_undo) {
                                                begin_reversible_command (_("separate"));
                                                doing_undo = true;
                                        }
-                                       if (doing_undo) session->add_undo ((playlist)->get_memento());
+                                       if (doing_undo) 
+                                            before = &(playlist->get_state());
+                                            
                        
                                        /* XXX need to consider musical time selections here at some point */
 
@@ -2340,7 +2359,8 @@ Editor::separate_regions_using_location (Location& loc)
 
 
                                        playlist->partition ((jack_nframes_t)(loc.start() * speed), (jack_nframes_t)(loc.end() * speed), true);
-                                       if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
+                                       if (doing_undo) 
+                                            session->add_command(new MementoCommand<Playlist>(*playlist, *before, playlist->get_state()));
                                }
                        }
                }
@@ -2411,9 +2431,10 @@ Editor::crop_region_to_selection ()
                        end = min (selection->time.end_frame(), start + region->length() - 1);
                        cnt = end - start + 1;
 
-                       session->add_undo ((*i)->get_memento());
+                        XMLNode &before = (*i)->get_state();
                        region->trim_to (start, cnt, this);
-                       session->add_redo_no_execute ((*i)->get_memento());
+                        XMLNode &after = (*i)->get_state();
+                       session->add_command (new MementoCommand<Playlist>(*(*i), before, after));
                }
 
                commit_reversible_command ();
@@ -2454,9 +2475,9 @@ Editor::region_fill_track ()
                        return;
                }
 
-               session->add_undo (pl->get_memento());
+                XMLNode &before = pl->get_state();
                pl->add_region (*(new AudioRegion (*ar)), ar->last_frame(), times);
-               session->add_redo_no_execute (pl->get_memento());
+               session->add_command (new MementoCommand<Playlist>(*pl, before, pl->get_state()));
        }
 
        commit_reversible_command ();
@@ -2504,9 +2525,9 @@ Editor::region_fill_selection ()
                        continue;
                }               
                
-               session->add_undo (playlist->get_memento());
+                XMLNode &before = playlist->get_state();
                playlist->add_region (*(createRegion (*region)), start, times);
-               session->add_redo_no_execute (playlist->get_memento());
+               session->add_command (new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
        }
        
        commit_reversible_command ();                   
@@ -2521,9 +2542,10 @@ Editor::set_a_regions_sync_position (Region& region, jack_nframes_t position)
                return;
        }
        begin_reversible_command (_("set region sync position"));
-       session->add_undo (region.playlist()->get_memento());
+        XMLNode &before = region.playlist()->get_state();
        region.set_sync_position (position);
-       session->add_redo_no_execute (region.playlist()->get_memento());
+        XMLNode &after = region.playlist()->get_state();
+       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
        commit_reversible_command ();
 }
 
@@ -2541,9 +2563,10 @@ Editor::set_region_sync_from_edit_cursor ()
 
        Region& region (clicked_regionview->region());
        begin_reversible_command (_("set sync from edit cursor"));
-       session->add_undo (region.playlist()->get_memento());
+        XMLNode &before = region.playlist()->get_state();
        region.set_sync_position (edit_cursor->current_frame);
-       session->add_redo_no_execute (region.playlist()->get_memento());
+        XMLNode &after = region.playlist()->get_state();
+       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
        commit_reversible_command ();
 }
 
@@ -2553,9 +2576,10 @@ Editor::remove_region_sync ()
        if (clicked_regionview) {
                Region& region (clicked_regionview->region());
                begin_reversible_command (_("remove sync"));
-               session->add_undo (region.playlist()->get_memento());
+                XMLNode &before = region.playlist()->get_state();
                region.clear_sync_position ();
-               session->add_redo_no_execute (region.playlist()->get_memento());
+                XMLNode &after = region.playlist()->get_state();
+               session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
                commit_reversible_command ();
        }
 }
@@ -2568,9 +2592,10 @@ Editor::naturalize ()
        }
        begin_reversible_command (_("naturalize"));
        for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
-               session->add_undo ((*i)->region().get_memento());
+                XMLNode &before = (*i)->region().get_state();
                (*i)->region().move_to_natural_position (this);
-               session->add_redo_no_execute ((*i)->region().get_memento());
+                XMLNode &after = (*i)->region().get_state();
+               session->add_command (new MementoCommand<Region>((*i)->region(), before, after));
        }
        commit_reversible_command ();
 }
@@ -2636,7 +2661,7 @@ Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
 
                Region& region ((*i)->region());
 
-               session->add_undo (region.playlist()->get_memento());
+                XMLNode &before = region.playlist()->get_state();
                
                if (dir > 0) {
                        region.set_position (region.position() + distance, this);
@@ -2644,7 +2669,8 @@ Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
                        region.set_position (region.position() - distance, this);
                }
 
-               session->add_redo_no_execute (region.playlist()->get_memento());
+                XMLNode &after = region.playlist()->get_state();
+               session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
 
        }
 
@@ -2678,7 +2704,7 @@ Editor::align_region (Region& region, RegionPoint point, jack_nframes_t position
 void
 Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t position)
 {
-       session->add_undo (region.playlist()->get_memento());
+       XMLNode &before = region.playlist()->get_state();
 
        switch (point) {
        case SyncPoint:
@@ -2696,7 +2722,8 @@ Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t
                break;
        }
 
-       session->add_redo_no_execute (region.playlist()->get_memento());
+       XMLNode &after = region.playlist()->get_state();
+       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
 }      
 
 void
@@ -2718,9 +2745,10 @@ Editor::trim_region_to_edit_cursor ()
        }
 
        begin_reversible_command (_("trim to edit"));
-       session->add_undo (region.playlist()->get_memento());
+        XMLNode &before = region.playlist()->get_state();
        region.trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
-       session->add_redo_no_execute (region.playlist()->get_memento());
+        XMLNode &after = region.playlist()->get_state();
+       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
        commit_reversible_command ();
 }
 
@@ -2743,9 +2771,10 @@ Editor::trim_region_from_edit_cursor ()
        }
 
        begin_reversible_command (_("trim to edit"));
-       session->add_undo (region.playlist()->get_memento());
+        XMLNode &before = region.playlist()->get_state();
        region.trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
-       session->add_redo_no_execute (region.playlist()->get_memento());
+        XMLNode &after = region.playlist()->get_state();
+       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
        commit_reversible_command ();
 }
 
@@ -2857,9 +2886,10 @@ Editor::bounce_range_selection ()
                itt.cancel = false;
                itt.progress = false;
                
-               session->add_undo (playlist->get_memento());
+                XMLNode &before = playlist->get_state();
                atv->audio_track()->bounce_range (start, cnt, itt);
-               session->add_redo_no_execute (playlist->get_memento());
+                XMLNode &after = playlist->get_state();
+               session->add_command (new MementoCommand<Playlist> (*playlist, before, after));
        }
        
        commit_reversible_command ();
@@ -2977,7 +3007,7 @@ Editor::cut_copy_regions (CutCopyOp op)
                                insert_result = freezelist.insert (pl);
                                if (insert_result.second) {
                                        pl->freeze ();
-                                       session->add_undo (pl->get_memento());
+                                        session->add_command (new MementoUndoCommand<Playlist>(*pl, pl->get_state()));
                                }
                        }
                }
@@ -3041,7 +3071,7 @@ Editor::cut_copy_regions (CutCopyOp op)
        
        for (set<Playlist*>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
                (*pl)->thaw ();
-               session->add_redo_no_execute ((*pl)->get_memento());
+               session->add_command (new MementoRedoCommand<Playlist>(*(*pl), (*pl)->get_state()));
        }
 }
 
@@ -3154,9 +3184,9 @@ Editor::paste_named_selection (float times)
                tmp = chunk;
                ++tmp;
 
-               session->add_undo (apl->get_memento());
+                XMLNode &before = apl->get_state();
                apl->paste (**chunk, edit_cursor->current_frame, times);
-               session->add_redo_no_execute (apl->get_memento());
+               session->add_command(new MementoCommand<AudioPlaylist>(*apl, before, apl->get_state()));
 
                if (tmp != ns->playlists.end()) {
                        chunk = tmp;
@@ -3185,9 +3215,9 @@ Editor::duplicate_some_regions (RegionSelection& regions, float times)
                sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
                
                playlist = (*i)->region().playlist();
-               session->add_undo (playlist->get_memento());
+                XMLNode &before = playlist->get_state();
                playlist->duplicate (r, r.last_frame(), times);
-               session->add_redo_no_execute (playlist->get_memento());
+               session->add_command(new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
 
                c.disconnect ();
 
@@ -3225,9 +3255,10 @@ Editor::duplicate_selection (float times)
                if ((playlist = (*i)->playlist()) == 0) {
                        continue;
                }
-               session->add_undo (playlist->get_memento());
+                XMLNode &before = playlist->get_state();
                playlist->duplicate (**ri, selection->time[clicked_selection].end, times);
-               session->add_redo_no_execute (playlist->get_memento());
+                XMLNode &after = playlist->get_state();
+               session->add_command (new MementoCommand<Playlist>(*playlist, before, after));
 
                ++ri;
                if (ri == new_regions.end()) {
@@ -3275,9 +3306,10 @@ void
 Editor::clear_playlist (Playlist& playlist)
 {
        begin_reversible_command (_("clear playlist"));
-       session->add_undo (playlist.get_memento());
+        XMLNode &before = playlist.get_state();
        playlist.clear ();
-       session->add_redo_no_execute (playlist.get_memento());
+        XMLNode &after = playlist.get_state();
+       session->add_command (new MementoCommand<Playlist>(playlist, before, after));
        commit_reversible_command ();
 }
 
@@ -3311,9 +3343,10 @@ Editor::nudge_track (bool use_edit_cursor, bool forwards)
                        continue;
                }               
                
-               session->add_undo (playlist->get_memento());
+                XMLNode &before = playlist->get_state();
                playlist->nudge_after (start, distance, forwards);
-               session->add_redo_no_execute (playlist->get_memento());
+                XMLNode &after = playlist->get_state();
+               session->add_command (new MementoCommand<Playlist>(*playlist, before, after));
        }
        
        commit_reversible_command ();                   
@@ -3367,9 +3400,9 @@ Editor::normalize_region ()
                AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
                if (!arv)
                        continue;
-               session->add_undo (arv->region().get_memento());
+               XMLNode &before = arv->region().get_state();
                arv->audio_region().normalize_to (0.0f);
-               session->add_redo_no_execute (arv->region().get_memento());
+               session->add_command (new MementoCommand<Region>(arv->region(), before, arv->region().get_state()));
        }
 
        commit_reversible_command ();
@@ -3394,9 +3427,9 @@ Editor::denormalize_region ()
                AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
                if (!arv)
                        continue;
-               session->add_undo (arv->region().get_memento());
+               XMLNode &before = arv->region().get_state();
                arv->audio_region().set_scale_amplitude (1.0f);
-               session->add_redo_no_execute (arv->region().get_memento());
+               session->add_command (new MementoCommand<Region>(arv->region(), before, arv->region().get_state()));
        }
 
        commit_reversible_command ();
@@ -3440,9 +3473,10 @@ Editor::apply_filter (AudioFilter& filter, string command)
 
                if (arv->audio_region().apply (filter) == 0) {
 
-                       session->add_undo (playlist->get_memento());
+                        XMLNode &before = playlist->get_state();
                        playlist->replace_region (arv->region(), *(filter.results.front()), arv->region().position());
-                       session->add_redo_no_execute (playlist->get_memento());
+                        XMLNode &after = playlist->get_state();
+                       session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
                } else {
                        goto out;
                }
index 5f998ada9fa5a0602c39cb874a790d9b8e5ffb60..9f7fe7cf095c9f5e1aa289855c0c668716c0d46a 100644 (file)
@@ -27,6 +27,7 @@
 #include <libgnomecanvasmm.h>
 
 #include <pbd/error.h>
+#include <pbd/memento_command.h>
 
 #include <gtkmm2ext/utils.h>
 #include <gtkmm2ext/gtk_ui.h>
@@ -273,9 +274,10 @@ Editor::mouse_add_new_tempo_event (jack_nframes_t frame)
        tempo_dialog.get_bbt_time (requested);
        
        begin_reversible_command (_("add tempo mark"));
-       session->add_undo (map.get_memento());
+        XMLNode &before = map.get_state();
        map.add_tempo (Tempo (bpm), requested);
-       session->add_redo_no_execute (map.get_memento());
+        XMLNode &after = map.get_state();
+       session->add_command(new MementoCommand<TempoMap>(map, before, after));
        commit_reversible_command ();
        
        map.dump (cerr);
@@ -313,9 +315,9 @@ Editor::mouse_add_new_meter_event (jack_nframes_t frame)
        meter_dialog.get_bbt_time (requested);
        
        begin_reversible_command (_("add meter mark"));
-       session->add_undo (map.get_memento());
+        XMLNode &before = map.get_state();
        map.add_meter (Meter (bpb, note_type), requested);
-       session->add_redo_no_execute (map.get_memento());
+       session->add_command(new MementoCommand<TempoMap>(map, before, map.get_state()));
        commit_reversible_command ();
        
        map.dump (cerr);
@@ -364,9 +366,10 @@ Editor::edit_meter_section (MeterSection* section)
        double note_type = meter_dialog.get_note_type ();
 
        begin_reversible_command (_("replace tempo mark"));
-       session->add_undo (session->tempo_map().get_memento());
+        XMLNode &before = session->tempo_map().get_state();
        session->tempo_map().replace_meter (*section, Meter (bpb, note_type));
-       session->add_redo_no_execute (session->tempo_map().get_memento());
+        XMLNode &after = session->tempo_map().get_state();
+       session->add_command(new MementoCommand<TempoMap>(session->tempo_map(), before, after));
        commit_reversible_command ();
 }
 
@@ -392,10 +395,11 @@ Editor::edit_tempo_section (TempoSection* section)
        bpm = max (0.01, bpm);
        
        begin_reversible_command (_("replace tempo mark"));
-       session->add_undo (session->tempo_map().get_memento());
+        XMLNode &before = session->tempo_map().get_state();
        session->tempo_map().replace_tempo (*section, Tempo (bpm));
        session->tempo_map().move_tempo (*section, when);
-       session->add_redo_no_execute (session->tempo_map().get_memento());
+        XMLNode &after = session->tempo_map().get_state();
+       session->add_command (new MementoCommand<TempoMap>(session->tempo_map(), before, after));
        commit_reversible_command ();
 }
 
@@ -441,9 +445,10 @@ gint
 Editor::real_remove_tempo_marker (TempoSection *section)
 {
        begin_reversible_command (_("remove tempo mark"));
-       session->add_undo (session->tempo_map().get_memento());
+       XMLNode &before = session->tempo_map().get_state();
        session->tempo_map().remove_tempo (*section);
-       session->add_redo_no_execute (session->tempo_map().get_memento());
+       XMLNode &after = session->tempo_map().get_state();
+       session->add_command(new MementoCommand<TempoMap>(session->tempo_map(), before, after));
        commit_reversible_command ();
 
        return FALSE;
@@ -474,9 +479,10 @@ gint
 Editor::real_remove_meter_marker (MeterSection *section)
 {
        begin_reversible_command (_("remove tempo mark"));
-       session->add_undo (session->tempo_map().get_memento());
+       XMLNode &before = session->tempo_map().get_state();
        session->tempo_map().remove_meter (*section);
-       session->add_redo_no_execute (session->tempo_map().get_memento());
+       XMLNode &after = session->tempo_map().get_state();
+       session->add_command(new MementoCommand<TempoMap>(session->tempo_map(), before, after));
        commit_reversible_command ();
        return FALSE;
 }
index 79772090f6b61b86de2d540327c43c750b7dd169..3fe0023d07701cc326c5d769f1ef5757674ae275 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <pbd/error.h>
 #include <pbd/pthread_utils.h>
+#include <pbd/memento_command.h>
 
 #include "editor.h"
 #include "audio_time_axis.h"
@@ -206,9 +207,10 @@ Editor::do_timestretch (TimeStretchDialog& dialog)
                        return;
                }
 
-               session->add_undo (playlist->get_memento());
+               XMLNode &before = playlist->get_state();
                playlist->replace_region (region, *new_region, region.position());
-               session->add_redo_no_execute (playlist->get_memento());
+               XMLNode &after = playlist->get_state();
+               session->add_command (new MementoCommand<Playlist>(*playlist, before, after));
 
                i = tmp;
        }
index 5352015f11bb71acad241fb028ba18bca76ab1f7..c86c1390f33dd96ac7c44d86ac0c41b0b0d62c62 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <ardour/curve.h>
 #include <ardour/route.h>
+#include <pbd/memento_command.h>
 
 #include "gain_automation_time_axis.h"
 #include "automation_line.h"
@@ -63,9 +64,10 @@ GainAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkE
 
        _session.begin_reversible_command (_("add gain automation event"));
 
-       _session.add_undo (curve.get_memento());
+        XMLNode &before = curve.get_state();
        curve.add (when, y);
-       _session.add_redo_no_execute (curve.get_memento());
+        XMLNode &after = curve.get_state();
+        _session.add_command(new MementoCommand<ARDOUR::Curve>(curve, before, after));
        _session.commit_reversible_command ();
        _session.set_dirty ();
 }
index f0fe230b5720df95bbf84bd804e821d5ea5e83ac..deb4c1da36bf5408714863a7230f22361d83ddd2 100644 (file)
@@ -27,6 +27,7 @@
 #include <ardour/utils.h>
 #include <ardour/configuration.h>
 #include <ardour/session.h>
+#include <pbd/memento_command.h>
 
 #include "ardour_ui.h"
 #include "prompter.h"
@@ -654,9 +655,10 @@ gint LocationUI::do_location_remove (ARDOUR::Location *loc)
        }
 
        session->begin_reversible_command (_("remove marker"));
-       session->add_undo (session->locations()->get_memento());
+       XMLNode &before = session->locations()->get_state();
        session->locations()->remove (loc);
-       session->add_redo_no_execute (session->locations()->get_memento());
+       XMLNode &after = session->locations()->get_state();
+       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
        session->commit_reversible_command ();
 
        return FALSE;
@@ -772,9 +774,10 @@ LocationUI::add_new_location()
                jack_nframes_t where = session->audible_frame();
                Location *location = new Location (where, where, "mark", Location::IsMark);
                session->begin_reversible_command (_("add marker"));
-               session->add_undo (session->locations()->get_memento());
+               XMLNode &before = session->locations()->get_state();
                session->locations()->add (location, true);
-               session->add_redo_no_execute (session->locations()->get_memento());
+               XMLNode &after = session->locations()->get_state();
+               session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
                session->commit_reversible_command ();
        }
        
@@ -788,9 +791,10 @@ LocationUI::add_new_range()
                Location *location = new Location (where, where, "unnamed", 
                                                                                        Location::IsRangeMarker);
                session->begin_reversible_command (_("add range marker"));
-               session->add_undo (session->locations()->get_memento());
+               XMLNode &before = session->locations()->get_state();
                session->locations()->add (location, true);
-               session->add_redo_no_execute (session->locations()->get_memento());
+               XMLNode &after = session->locations()->get_state();
+               session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
                session->commit_reversible_command ();
        }
 }
index 778355c858414b1793c509ef36df39cbbd84b7e0..27dc57370676ccba34582c0c67618a8e7a9a3d6c 100644 (file)
@@ -293,60 +293,43 @@ Please consider the possibilities, and perhaps (re)start JACK."));
 static bool
 maybe_load_session ()
 {
+       /* If no session name is given: we're not loading a session yet, nor creating a new one */
+       if (!session_name.length()) {
+               ui->hide_splash ();
+               if (!Config->get_no_new_session_dialog()) {
+                      ui->new_session (true);
+               }
 
-       /* load session, if given */
-       string name, path;
-
-       if (session_name.length()){
-               bool isnew;
-
-               if (Session::find_session (session_name, path, name, isnew)) {
-                       error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
-               } else {
-
-                       if (new_session) {
-
-                               /* command line required that the session be new */
-
-                               if (isnew) {
-                                       
-                                       /* popup the new session dialog
-                                          once everything else is OK.
-                                       */
-
-                                       Glib::signal_idle().connect (bind (mem_fun (*ui, &ARDOUR_UI::cmdline_new_session), path));
-                                       ui->set_will_create_new_session_automatically (true);
-
-                               } else {
-
-                                       /* it wasn't new, but we require a new session */
+               return true;
+       }
 
-                                       error << string_compose (_("\n\nA session named \"%1\" already exists.\n\
-To avoid this message, start ardour as \"ardour %1"), path)
-                                             << endmsg;
-                                       return false;
-                               }
+       /* Load session or start the new session dialog */
+       string name, path;
 
-                       } else {
+       bool isnew;
 
-                               /* command line didn't require a new session */
-                               
-                               if (isnew) {
-                                       error << string_compose (_("\n\nNo session named \"%1\" exists.\n\
-To create it from the command line, start ardour as \"ardour --new %1"), path) 
-                                             << endmsg;
-                                       return false;
-                               }
+       if (Session::find_session (session_name, path, name, isnew)) {
+               error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
+               return false;
+       }
 
-                               ui->load_session (path, name);
-                       }
+       if (!new_session) {
+                       
+               /* Loading a session, but the session doesn't exist */
+               if (isnew) {
+                       error << string_compose (_("\n\nNo session named \"%1\" exists.\n\
+To create it from the command line, start ardour as \"ardour --new %1"), path) << endmsg;
+                       return false;
                }
 
-               if (no_splash) {
-                       ui->show();
-               }
+               ui->load_session (path, name);
 
        } else {
+       /*  TODO: This bit of code doesn't work properly yet
+               Glib::signal_idle().connect (bind (mem_fun (*ui, &ARDOUR_UI::cmdline_new_session), path));
+               ui->set_will_create_new_session_automatically (true); */
+
+               /* Show the NSD */
                ui->hide_splash ();
                if (!Config->get_no_new_session_dialog()) {
                       ui->new_session (true);
index d1059cebe08f76b204cccf62f0b84cced5fa0f5d..47a2b2b6d3d9960054b952d1ce23072dd7e9f93f 100644 (file)
 #include <gtkmm/filefilter.h>
 #include <gtkmm/stock.h>
 
+#include "opts.h"
 
 NewSessionDialog::NewSessionDialog()
        : ArdourDialog ("New Session Dialog")
 {
         session_name_label = Gtk::manage(new class Gtk::Label(_("New Session Name :")));
        m_name = Gtk::manage(new class Gtk::Entry());
+       m_name->set_text(GTK_ARDOUR::session_name);
+
        session_location_label = Gtk::manage(new class Gtk::Label(_("Create Session Directory In :")));
        m_folder = Gtk::manage(new class Gtk::FileChooserButton(Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER));
        session_template_label = Gtk::manage(new class Gtk::Label(_("Use Session Template :")));
@@ -324,13 +327,21 @@ NewSessionDialog::NewSessionDialog()
        m_folder->set_current_folder(getenv ("HOME"));
        m_folder->set_title(_("select directory"));
 
-       set_default_response (Gtk::RESPONSE_OK);
-       set_response_sensitive (Gtk::RESPONSE_OK, false);
-       set_response_sensitive (Gtk::RESPONSE_NONE, false);
+       on_new_session_page = true;
        m_notebook->set_current_page(0);
        m_notebook->show();
        m_notebook->show_all_children();
 
+
+       set_default_response (Gtk::RESPONSE_OK);
+       if (!GTK_ARDOUR::session_name.length()) {
+               set_response_sensitive (Gtk::RESPONSE_OK, false);
+               set_response_sensitive (Gtk::RESPONSE_NONE, false);
+       } else {
+               set_response_sensitive (Gtk::RESPONSE_OK, true);
+               set_response_sensitive (Gtk::RESPONSE_NONE, true);
+       }
+
        ///@ connect some signals
 
        m_connect_inputs->signal_clicked().connect (mem_fun (*this, &NewSessionDialog::connect_inputs_clicked));
@@ -501,11 +512,11 @@ NewSessionDialog::reset_name()
 bool
 NewSessionDialog::entry_key_release (GdkEventKey* ev)
 {
-        if (m_name->get_text() != "") {
-               set_response_sensitive (Gtk::RESPONSE_OK, true);
+       if (m_name->get_text() != "") {
+               set_response_sensitive (Gtk::RESPONSE_OK, true);
                set_response_sensitive (Gtk::RESPONSE_NONE, true);
        } else {
-               set_response_sensitive (Gtk::RESPONSE_OK, false);
+               set_response_sensitive (Gtk::RESPONSE_OK, false);
        }
        return true;
 }
@@ -513,25 +524,27 @@ NewSessionDialog::entry_key_release (GdkEventKey* ev)
 void
 NewSessionDialog::notebook_page_changed (GtkNotebookPage* np, uint pagenum)
 {
-        if (pagenum == 1) {
-              m_okbutton->set_label(_("Open"));
-              set_response_sensitive (Gtk::RESPONSE_NONE, false);
-              m_okbutton->set_image (*(new Gtk::Image (Gtk::Stock::OPEN, Gtk::ICON_SIZE_BUTTON)));
-              if (m_treeview->get_selection()->count_selected_rows() == 0) {
-                       set_response_sensitive (Gtk::RESPONSE_OK, false);
+       if (pagenum == 1) {
+               on_new_session_page = false;
+               m_okbutton->set_label(_("Open"));
+               set_response_sensitive (Gtk::RESPONSE_NONE, false);
+               m_okbutton->set_image (*(new Gtk::Image (Gtk::Stock::OPEN, Gtk::ICON_SIZE_BUTTON)));
+               if (m_treeview->get_selection()->count_selected_rows() == 0) {
+                       set_response_sensitive (Gtk::RESPONSE_OK, false);
                } else {
-                       set_response_sensitive (Gtk::RESPONSE_OK, true);
+                       set_response_sensitive (Gtk::RESPONSE_OK, true);
                }
        } else {
-               if (m_name->get_text() != "") {
-                 set_response_sensitive (Gtk::RESPONSE_NONE, true);
+               on_new_session_page = true;
+               if (m_name->get_text() != "") {
+                       set_response_sensitive (Gtk::RESPONSE_NONE, true);
                }
-               m_okbutton->set_label(_("New"));
-               m_okbutton->set_image (*(new Gtk::Image (Gtk::Stock::NEW, Gtk::ICON_SIZE_BUTTON)));
+               m_okbutton->set_label(_("New"));
+               m_okbutton->set_image (*(new Gtk::Image (Gtk::Stock::NEW, Gtk::ICON_SIZE_BUTTON)));
                if (m_name->get_text() == "") {
-                      set_response_sensitive (Gtk::RESPONSE_OK, false);
+                       set_response_sensitive (Gtk::RESPONSE_OK, false);
                } else {
-                       set_response_sensitive (Gtk::RESPONSE_OK, true);
+                       set_response_sensitive (Gtk::RESPONSE_OK, true);
                }
        }
 }
@@ -540,35 +553,37 @@ void
 NewSessionDialog::treeview_selection_changed ()
 {
        if (m_treeview->get_selection()->count_selected_rows() == 0) {
-               if (!m_open_filechooser->get_filename().empty()) {
-                       set_response_sensitive (Gtk::RESPONSE_OK, true);
+               if (!m_open_filechooser->get_filename().empty()) {
+                       set_response_sensitive (Gtk::RESPONSE_OK, true);
                } else {
-                       set_response_sensitive (Gtk::RESPONSE_OK, false);
+                       set_response_sensitive (Gtk::RESPONSE_OK, false);
                }
        } else {
-                set_response_sensitive (Gtk::RESPONSE_OK, true);
+               set_response_sensitive (Gtk::RESPONSE_OK, true);
        }
 }
 
 void
 NewSessionDialog::file_chosen ()
 {
-        m_treeview->get_selection()->unselect_all();
+       if (on_new_session_page) return;
+
+       m_treeview->get_selection()->unselect_all();
 
        if (!m_open_filechooser->get_filename().empty()) {
-                 set_response_sensitive (Gtk::RESPONSE_OK, true);
+               set_response_sensitive (Gtk::RESPONSE_OK, true);
        } else {
-                 set_response_sensitive (Gtk::RESPONSE_OK, false);
+               set_response_sensitive (Gtk::RESPONSE_OK, false);
        }
 }
 
 void
 NewSessionDialog::template_chosen ()
 {
-        if (m_template->get_filename() != "" ) {;
-               set_response_sensitive (Gtk::RESPONSE_NONE, true);
+       if (m_template->get_filename() != "" ) {;
+               set_response_sensitive (Gtk::RESPONSE_NONE, true);
        } else {
-               set_response_sensitive (Gtk::RESPONSE_NONE, false);
+               set_response_sensitive (Gtk::RESPONSE_NONE, false);
        }
 }
 
index 366805d31fc488c6bc5be2c6d12d77051d5a5de2..5d652fd1222e20c3f1e8e84d67a84186c1f963b0 100644 (file)
@@ -182,6 +182,8 @@ protected:
        void master_bus_button_clicked ();
        void monitor_bus_button_clicked ();
 
+       bool on_new_session_page;
+
        
 };
 
index 69b812882411f25fc36780962bdeedad8c3561de..fcd62de51280404b6b76e03cdd99f472d24202f1 100644 (file)
@@ -143,14 +143,19 @@ GTK_ARDOUR::parse_opts (int argc, char *argv[])
                        break;
 
                default:
-                       break;
+                       return print_help(execname);
                }
        }
 
        if (optind < argc) {
+               if (new_session) {
+                       cerr << "Illogical combination: you can either create a new session, or a load an existing session but not both!" << endl;
+                       return print_help(execname);
+               }
                session_name = argv[optind++];
        }
 
+
        return 0;
 }
 
index fcef6f812c9e45bdb6e420fec3085f6449ae00f5..ec884151b5d46653fb5161888ab996d92af061a7 100644 (file)
 #include <ardour/panner.h>
 
 #include <gtkmm2ext/popup.h>
+#include <pbd/memento_command.h>
 
 #include "pan_automation_time_axis.h"
 #include "automation_line.h"
 #include "canvas_impl.h"
+#include "route_ui.h"
 
 #include "i18n.h"
 
@@ -42,7 +44,7 @@ PanAutomationTimeAxisView::PanAutomationTimeAxisView (Session& s, boost::shared_
 {
        multiline_selector.set_name ("PanAutomationLineSelector");
        
-       controls_table.attach (multiline_selector, 1, 5, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+       controls_table.attach (multiline_selector, 1, 5, 1, 2, Gtk::EXPAND, Gtk::EXPAND);
 }
 
 PanAutomationTimeAxisView::~PanAutomationTimeAxisView ()
@@ -87,9 +89,10 @@ PanAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEv
        AutomationList& alist (lines[line_index]->the_list());
 
        _session.begin_reversible_command (_("add pan automation event"));
-       _session.add_undo (alist.get_memento());
+       XMLNode &before = alist.get_state();
        alist.add (when, y);
-       _session.add_redo_no_execute (alist.get_memento());
+       XMLNode &after = alist.get_state();
+        _session.add_command(new MementoCommand<AutomationList>(alist, before, after));
        _session.commit_reversible_command ();
        _session.set_dirty ();
 }
@@ -105,15 +108,18 @@ void
 PanAutomationTimeAxisView::add_line (AutomationLine& line)
 {
        char buf[32];
-       snprintf(buf,32,"Line %ld",lines.size()+1);
+       snprintf(buf,32,"Line %zu",lines.size()+1);
        multiline_selector.append_text(buf);
 
        if (lines.empty()) {
                multiline_selector.set_active(0);
        }
 
-       if (lines.size() + 1 > 1) {
+       if (lines.size() + 1 > 1 && (height_style != Small && height_style != Smaller)) {
                multiline_selector.show();
+       } else {
+               multiline_selector.hide();
+
        }
 
        AutomationTimeAxisView::add_line(line);
@@ -129,9 +135,10 @@ PanAutomationTimeAxisView::set_height (TimeAxisView::TrackHeight th)
                case Large:
                case Larger:
                case Normal:
-                       multiline_selector.show();
-                       break;
-
+                       if (lines.size() > 1) {
+                               multiline_selector.show();
+                               break;
+                       } 
                default:
                        multiline_selector.hide();
        }
index a34533ade9ef51fa1ad412222181dca77f17a5a7..e0a62b177f18711ed8f759036e018dfbee28cb62 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2000-2006 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
@@ -48,8 +48,6 @@ PluginSelector::PluginSelector (PluginManager *mgr)
 
        manager = mgr;
        session = 0;
-       o_selected_plug = -1;
-       i_selected_plug = 0;
        
        current_selection = PluginInfo::LADSPA;
 
@@ -305,7 +303,7 @@ void
 PluginSelector::au_refiller ()
 {
        guint row;
-       PluginInfoList &plugs = manager->au_plugin_info ();
+       PluginInfoList plugs (AUPluginInfo::discover ());
        PluginInfoList::iterator i;
        char ibuf[16], obuf[16];
        aumodel->clear();
@@ -346,7 +344,7 @@ PluginSelector::use_plugin (PluginInfoPtr pi)
                return;
        }
 
-       boost::shared_ptr<Plugin> plugin = manager->load (*session, pi);
+       PluginPtr plugin = pi->load (*session);
 
        if (plugin) {
                PluginCreated (plugin);
index 06c2f1d18ebcb55a4d9c9cc2bc43361ef9043034..583506972a896b80b9f6d26c0b08957895f80214 100644 (file)
@@ -30,7 +30,6 @@
 namespace ARDOUR {
        class Session;
        class PluginManager;
-       class PluginInfo;
 }
 
 class PluginSelector : public ArdourDialog
@@ -134,12 +133,6 @@ class PluginSelector : public ArdourDialog
        void au_display_selection_changed();
 #endif //HAVE_COREAUDIO
 
-       ARDOUR::PluginInfo* i_selected_plug;
-
-       // We need an integer for the output side because
-       // the name isn't promised to be unique.
-       gint o_selected_plug;
-
        ARDOUR::PluginManager *manager;
 
        static void _input_refiller (void *);
index beddad4e165fd0a35160065ea54df0b41140960f..edc94864f2a916d51fb934f1f0088f5509d9d8d3 100644 (file)
@@ -90,13 +90,13 @@ PluginUIWindow::PluginUIWindow (AudioEngine &engine, boost::shared_ptr<PluginIns
 
        } else {
 
-               PluginUI*  pu  = new PluginUI (engine, insert, scrollable);
+               LadspaPluginUI*  pu  = new LadspaPluginUI (engine, insert, scrollable);
                
                _pluginui = pu;
                get_vbox()->add (*pu);
                
-               signal_map_event().connect (mem_fun (*pu, &PluginUI::start_updating));
-               signal_unmap_event().connect (mem_fun (*pu, &PluginUI::stop_updating));
+               signal_map_event().connect (mem_fun (*pu, &LadspaPluginUI::start_updating));
+               signal_unmap_event().connect (mem_fun (*pu, &LadspaPluginUI::stop_updating));
        }
 
        set_position (Gtk::WIN_POS_MOUSE);
@@ -117,7 +117,7 @@ PluginUIWindow::~PluginUIWindow ()
 {
 }
 
-PluginUI::PluginUI (AudioEngine &engine, boost::shared_ptr<PluginInsert> pi, bool scrollable)
+LadspaPluginUI::LadspaPluginUI (AudioEngine &engine, boost::shared_ptr<PluginInsert> pi, bool scrollable)
        : PlugUIBase (pi),
          engine(engine),
          button_table (initial_button_rows, initial_button_cols),
@@ -165,13 +165,13 @@ PluginUI::PluginUI (AudioEngine &engine, boost::shared_ptr<PluginInsert> pi, boo
                pack_start (hpacker, false, false);
        }
 
-       insert->active_changed.connect (mem_fun(*this, &PluginUI::redirect_active_changed));
+       insert->active_changed.connect (mem_fun(*this, &LadspaPluginUI::redirect_active_changed));
        bypass_button.set_active (!insert->active());
        
        build (engine);
 }
 
-PluginUI::~PluginUI ()
+LadspaPluginUI::~LadspaPluginUI ()
 {
        if (output_controls.size() > 0) {
                screen_update_connection.disconnect();
@@ -179,7 +179,7 @@ PluginUI::~PluginUI ()
 }
 
 void
-PluginUI::build (AudioEngine &engine)
+LadspaPluginUI::build (AudioEngine &engine)
 
 {
        guint32 i = 0;
@@ -326,8 +326,8 @@ PluginUI::build (AudioEngine &engine)
                } 
        }
 
-       n_ins = plugin->get_info().n_inputs;
-       n_outs = plugin->get_info().n_outputs;
+       n_ins = plugin->get_info()->n_inputs;
+       n_outs = plugin->get_info()->n_outputs;
 
        if (box->children().empty()) {
                hpacker.remove (*frame);
@@ -350,7 +350,7 @@ PluginUI::build (AudioEngine &engine)
        button_table.show_all ();
 }
 
-PluginUI::ControlUI::ControlUI ()
+LadspaPluginUI::ControlUI::ControlUI ()
        : automate_button (X_("")) // force creation of a label 
 {
        automate_button.set_name ("PluginAutomateButton");
@@ -370,7 +370,7 @@ PluginUI::ControlUI::ControlUI ()
        meterinfo = 0;
 }
 
-PluginUI::ControlUI::~ControlUI() 
+LadspaPluginUI::ControlUI::~ControlUI() 
 {
        if (adjustment) {
                delete adjustment;
@@ -383,7 +383,7 @@ PluginUI::ControlUI::~ControlUI()
 }
 
 void
-PluginUI::automation_state_changed (ControlUI* cui)
+LadspaPluginUI::automation_state_changed (ControlUI* cui)
 {
        /* update button label */
 
@@ -413,13 +413,13 @@ static void integer_printer (char buf[32], Adjustment &adj, void *arg)
 }
 
 void
-PluginUI::print_parameter (char *buf, uint32_t len, uint32_t param)
+LadspaPluginUI::print_parameter (char *buf, uint32_t len, uint32_t param)
 {
        plugin->print_parameter (param, buf, len);
 }
 
-PluginUI::ControlUI*
-PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::Controllable* mcontrol)
+LadspaPluginUI::ControlUI*
+LadspaPluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::Controllable* mcontrol)
 
 {
        ControlUI* control_ui;
@@ -452,8 +452,8 @@ PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::Contro
                                control_ui->combo = new Gtk::ComboBoxText;
                                //control_ui->combo->set_value_in_list(true, false);
                                set_popdown_strings (*control_ui->combo, setup_scale_values(port_index, control_ui));
-                               control_ui->combo->signal_changed().connect (bind (mem_fun(*this, &PluginUI::control_combo_changed), control_ui));
-                               plugin->ParameterChanged.connect (bind (mem_fun (*this, &PluginUI::parameter_changed), control_ui));
+                               control_ui->combo->signal_changed().connect (bind (mem_fun(*this, &LadspaPluginUI::control_combo_changed), control_ui));
+                               plugin->ParameterChanged.connect (bind (mem_fun (*this, &LadspaPluginUI::parameter_changed), control_ui));
                                control_ui->pack_start(control_ui->label, true, true);
                                control_ui->pack_start(*control_ui->combo, false, true);
                                
@@ -476,7 +476,7 @@ PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::Contro
                        control_ui->pack_start (*control_ui->button, false, true);
                        control_ui->pack_start (control_ui->automate_button, false, false);
 
-                       control_ui->button->signal_clicked().connect (bind (mem_fun(*this, &PluginUI::control_port_toggled), control_ui));
+                       control_ui->button->signal_clicked().connect (bind (mem_fun(*this, &LadspaPluginUI::control_port_toggled), control_ui));
                
                        if(plugin->get_parameter (port_index) == 1){
                                control_ui->button->set_active(true);
@@ -514,7 +514,7 @@ PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::Contro
                        Gtkmm2ext::set_size_request_to_display_given_text (*control_ui->clickbox, "g9999999", 2, 2);
                        control_ui->clickbox->set_print_func (integer_printer, 0);
                } else {
-                       sigc::slot<void,char*,uint32_t> pslot = sigc::bind (mem_fun(*this, &PluginUI::print_parameter), (uint32_t) port_index);
+                       sigc::slot<void,char*,uint32_t> pslot = sigc::bind (mem_fun(*this, &LadspaPluginUI::print_parameter), (uint32_t) port_index);
 
                        control_ui->control = new BarController (*control_ui->adjustment, *mcontrol, pslot);
                        // should really match the height of the text in the automation button+label
@@ -523,8 +523,8 @@ PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::Contro
                        control_ui->control->set_style (BarController::LeftToRight);
                        control_ui->control->set_use_parent (true);
 
-                       control_ui->control->StartGesture.connect (bind (mem_fun(*this, &PluginUI::start_touch), control_ui));
-                       control_ui->control->StopGesture.connect (bind (mem_fun(*this, &PluginUI::stop_touch), control_ui));
+                       control_ui->control->StartGesture.connect (bind (mem_fun(*this, &LadspaPluginUI::start_touch), control_ui));
+                       control_ui->control->StopGesture.connect (bind (mem_fun(*this, &LadspaPluginUI::stop_touch), control_ui));
                        
                }
 
@@ -547,14 +547,14 @@ PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::Contro
                }
 
                control_ui->pack_start (control_ui->automate_button, false, false);
-               control_ui->adjustment->signal_value_changed().connect (bind (mem_fun(*this, &PluginUI::control_adjustment_changed), control_ui));
-               control_ui->automate_button.signal_clicked().connect (bind (mem_fun(*this, &PluginUI::astate_clicked), control_ui, (uint32_t) port_index));
+               control_ui->adjustment->signal_value_changed().connect (bind (mem_fun(*this, &LadspaPluginUI::control_adjustment_changed), control_ui));
+               control_ui->automate_button.signal_clicked().connect (bind (mem_fun(*this, &LadspaPluginUI::astate_clicked), control_ui, (uint32_t) port_index));
 
                automation_state_changed (control_ui);
 
-               plugin->ParameterChanged.connect (bind (mem_fun(*this, &PluginUI::parameter_changed), control_ui));
+               plugin->ParameterChanged.connect (bind (mem_fun(*this, &LadspaPluginUI::parameter_changed), control_ui));
                insert->automation_list (port_index).automation_state_changed.connect 
-                       (bind (mem_fun(*this, &PluginUI::automation_state_changed), control_ui));
+                       (bind (mem_fun(*this, &LadspaPluginUI::automation_state_changed), control_ui));
 
        } else if (plugin->parameter_is_output (port_index)) {
 
@@ -603,24 +603,24 @@ PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::Contro
                output_controls.push_back (control_ui);
        }
        
-       plugin->ParameterChanged.connect (bind (mem_fun(*this, &PluginUI::parameter_changed), control_ui));
+       plugin->ParameterChanged.connect (bind (mem_fun(*this, &LadspaPluginUI::parameter_changed), control_ui));
        return control_ui;
 }
 
 void
-PluginUI::start_touch (PluginUI::ControlUI* cui)
+LadspaPluginUI::start_touch (LadspaPluginUI::ControlUI* cui)
 {
        insert->automation_list (cui->port_index).start_touch ();
 }
 
 void
-PluginUI::stop_touch (PluginUI::ControlUI* cui)
+LadspaPluginUI::stop_touch (LadspaPluginUI::ControlUI* cui)
 {
        insert->automation_list (cui->port_index).stop_touch ();
 }
 
 void
-PluginUI::astate_clicked (ControlUI* cui, uint32_t port)
+LadspaPluginUI::astate_clicked (ControlUI* cui, uint32_t port)
 {
        using namespace Menu_Helpers;
 
@@ -633,25 +633,25 @@ PluginUI::astate_clicked (ControlUI* cui, uint32_t port)
 
        items.clear ();
        items.push_back (MenuElem (_("Off"), 
-                                  bind (mem_fun(*this, &PluginUI::set_automation_state), (AutoState) Off, cui)));
+                                  bind (mem_fun(*this, &LadspaPluginUI::set_automation_state), (AutoState) Off, cui)));
        items.push_back (MenuElem (_("Play"),
-                                  bind (mem_fun(*this, &PluginUI::set_automation_state), (AutoState) Play, cui)));
+                                  bind (mem_fun(*this, &LadspaPluginUI::set_automation_state), (AutoState) Play, cui)));
        items.push_back (MenuElem (_("Write"),
-                                  bind (mem_fun(*this, &PluginUI::set_automation_state), (AutoState) Write, cui)));
+                                  bind (mem_fun(*this, &LadspaPluginUI::set_automation_state), (AutoState) Write, cui)));
        items.push_back (MenuElem (_("Touch"),
-                                  bind (mem_fun(*this, &PluginUI::set_automation_state), (AutoState) Touch, cui)));
+                                  bind (mem_fun(*this, &LadspaPluginUI::set_automation_state), (AutoState) Touch, cui)));
 
        automation_menu->popup (1, 0);
 }
 
 void
-PluginUI::set_automation_state (AutoState state, ControlUI* cui)
+LadspaPluginUI::set_automation_state (AutoState state, ControlUI* cui)
 {
        insert->set_port_automation_state (cui->port_index, state);
 }
 
 void
-PluginUI::control_adjustment_changed (ControlUI* cui)
+LadspaPluginUI::control_adjustment_changed (ControlUI* cui)
 {
        if (cui->ignore_change) {
                return;
@@ -667,18 +667,18 @@ PluginUI::control_adjustment_changed (ControlUI* cui)
 }
 
 void
-PluginUI::parameter_changed (uint32_t abs_port_id, float val, ControlUI* cui)
+LadspaPluginUI::parameter_changed (uint32_t abs_port_id, float val, ControlUI* cui)
 {
        if (cui->port_index == abs_port_id) {
                if (!cui->update_pending) {
                        cui->update_pending = true;
-                       Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &PluginUI::update_control_display), cui));
+                       Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &LadspaPluginUI::update_control_display), cui));
                }
        }
 }
 
 void
-PluginUI::update_control_display (ControlUI* cui)      
+LadspaPluginUI::update_control_display (ControlUI* cui)        
 {
        /* XXX how do we handle logarithmic stuff here ? */
        
@@ -715,7 +715,7 @@ PluginUI::update_control_display (ControlUI* cui)
 }
 
 void
-PluginUI::control_port_toggled (ControlUI* cui)
+LadspaPluginUI::control_port_toggled (ControlUI* cui)
 {
        if (!cui->ignore_change) {
                insert->set_parameter (cui->port_index, cui->button->get_active());
@@ -723,7 +723,7 @@ PluginUI::control_port_toggled (ControlUI* cui)
 }
 
 void
-PluginUI::control_combo_changed (ControlUI* cui)
+LadspaPluginUI::control_combo_changed (ControlUI* cui)
 {
        if (!cui->ignore_change) {
                string value = cui->combo->get_active_text();
@@ -743,26 +743,26 @@ PluginUIWindow::plugin_going_away (ARDOUR::Redirect* ignored)
 }
 
 void
-PluginUI::redirect_active_changed (Redirect* r, void* src)
+LadspaPluginUI::redirect_active_changed (Redirect* r, void* src)
 {
-       ENSURE_GUI_THREAD(bind (mem_fun(*this, &PluginUI::redirect_active_changed), r, src));
+       ENSURE_GUI_THREAD(bind (mem_fun(*this, &LadspaPluginUI::redirect_active_changed), r, src));
        
        bypass_button.set_active (!r->active());
 }
 
 bool
-PluginUI::start_updating (GdkEventAny* ignored)
+LadspaPluginUI::start_updating (GdkEventAny* ignored)
 {
        if (output_controls.size() > 0 ) {
                screen_update_connection.disconnect();
                screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect 
-                       (mem_fun(*this, &PluginUI::output_update));
+                       (mem_fun(*this, &LadspaPluginUI::output_update));
        }
        return false;
 }
 
 bool
-PluginUI::stop_updating (GdkEventAny* ignored)
+LadspaPluginUI::stop_updating (GdkEventAny* ignored)
 {
        if (output_controls.size() > 0 ) {
                screen_update_connection.disconnect();
@@ -771,7 +771,7 @@ PluginUI::stop_updating (GdkEventAny* ignored)
 }
 
 void
-PluginUI::output_update ()
+LadspaPluginUI::output_update ()
 {
        for (vector<ControlUI*>::iterator i = output_controls.begin(); i != output_controls.end(); ++i) {
                float val = plugin->get_parameter ((*i)->port_index);
@@ -805,7 +805,7 @@ PluginUI::output_update ()
 }
 
 vector<string> 
-PluginUI::setup_scale_values(guint32 port_index, ControlUI* cui)
+LadspaPluginUI::setup_scale_values(guint32 port_index, ControlUI* cui)
 {
        vector<string> enums;
        boost::shared_ptr<LadspaPlugin> lp = boost::dynamic_pointer_cast<LadspaPlugin> (plugin);
index 570a224b66d5baf61320b2c4db18b56c30d167f7..dc1e61887b2f3c76fcd9401bbc08b83e459a4e5d 100644 (file)
@@ -50,6 +50,7 @@ namespace ARDOUR {
        class Plugin;
        class VSTPlugin;
        class Redirect;
+       class AUPlugin;
 }
 
 namespace PBD {
@@ -86,11 +87,11 @@ class PlugUIBase : public virtual sigc::trackable
        void bypass_toggled();
 };
 
-class PluginUI : public PlugUIBase, public Gtk::VBox 
+class LadspaPluginUI : public PlugUIBase, public Gtk::VBox 
 {
   public:
-       PluginUI (ARDOUR::AudioEngine &, boost::shared_ptr<ARDOUR::PluginInsert> plug, bool scrollable=false);
-       ~PluginUI ();
+       LadspaPluginUI (ARDOUR::AudioEngine &, boost::shared_ptr<ARDOUR::PluginInsert> plug, bool scrollable=false);
+       ~LadspaPluginUI ();
        
        gint get_preferred_height () { return prefheight; }
 
@@ -231,6 +232,22 @@ class VSTPluginUI : public PlugUIBase, public Gtk::VBox
        bool configure_handler (GdkEventConfigure*, Gtk::Socket*);
        void save_plugin_setting ();
 };
-#endif
+#endif // VST_SUPPORT
+
+#ifdef HAVE_COREAUDIO
+class AUPluginUI : public PlugUIBase
+{
+  public:
+       AUPluginUI (boost::shared_ptr<ARDOUR::PluginInsert>, boost::shared_ptr<ARDOUR::AUPlugin>);
+       ~AUPluginUI ();
+       
+       gint get_preferred_height ();
+       bool start_updating(GdkEventAny*) {return false;}
+       bool stop_updating(GdkEventAny*) {return false;}
+
+  private:
+       boost::shared_ptr<ARDOUR::AUPlugin> au;
+};
+#endif // HAVE_COREAUDIO
 
 #endif /* __ardour_plugin_ui_h__ */
index a53c1a20e48539e01da67878bc09a3da0f6ccd84..e527fd1d5e9123fee2cdc8e2e6389fd6da1b4ce7 100644 (file)
@@ -21,6 +21,7 @@
 #include <ardour/redirect.h>
 #include <ardour/session.h>
 #include <cstdlib>
+#include <pbd/memento_command.h>
 
 #include "redirect_automation_time_axis.h"
 #include "automation_line.h"
@@ -98,9 +99,10 @@ RedirectAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item,
                lines.front()->view_to_model_y (y);
                
                _session.begin_reversible_command (description);
-               _session.add_undo (alist.get_memento());
+                XMLNode &before = alist.get_state();
                alist.add (when, y);
-               _session.add_redo_no_execute (alist.get_memento());
+                XMLNode &after = alist.get_state();
+                _session.add_command(new MementoCommand<AutomationList>(alist, before, after));
                _session.commit_reversible_command ();
                _session.set_dirty ();
        }
index 0455dfdeb4028307db90391e72f4ee32db3bcdc0..74198265d9e82cb34b9707e7cb061a500b237e81 100644 (file)
@@ -378,7 +378,7 @@ RedirectBox::wierd_plugin_dialog (Plugin& p, uint32_t streams, boost::shared_ptr
 
        /* i hate this kind of code */
 
-       if (streams > p.get_info().n_inputs) {
+       if (streams > p.get_info()->n_inputs) {
                label.set_text (string_compose (_(
 "You attempted to add a plugin (%1).\n"
 "The plugin has %2 inputs\n"
@@ -388,9 +388,9 @@ RedirectBox::wierd_plugin_dialog (Plugin& p, uint32_t streams, boost::shared_ptr
 "This makes no sense - you are throwing away\n"
 "part of the signal."),
                                         p.name(),
-                                        p.get_info().n_inputs,
+                                        p.get_info()->n_inputs,
                                         streams));
-       } else if (streams < p.get_info().n_inputs) {
+       } else if (streams < p.get_info()->n_inputs) {
                label.set_text (string_compose (_(
 "You attempted to add a plugin (%1).\n"
 "The plugin has %2 inputs\n"
@@ -401,7 +401,7 @@ RedirectBox::wierd_plugin_dialog (Plugin& p, uint32_t streams, boost::shared_ptr
 "side-chain inputs. A future version of Ardour will\n"
 "support this type of configuration."),
                                         p.name(),
-                                        p.get_info().n_inputs,
+                                        p.get_info()->n_inputs,
                                         streams));
        } else {
                label.set_text (string_compose (_(
@@ -415,8 +415,8 @@ RedirectBox::wierd_plugin_dialog (Plugin& p, uint32_t streams, boost::shared_ptr
 "\n"
 "Ardour does not understand what to do in such situations.\n"),
                                         p.name(),
-                                        p.get_info().n_inputs,
-                                        p.get_info().n_outputs,
+                                        p.get_info()->n_inputs,
+                                        p.get_info()->n_outputs,
                                         io->n_inputs(),
                                         io->n_outputs(),
                                         streams));
index 176ced0792a874666a201ecc3c1c04de66f75b34..70590b0db5886e155507c0e17e7e09da343e1d2c 100644 (file)
@@ -15,7 +15,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: region_editor.h 231 2006-01-03 14:16:27Z karstenweise $
+    $Id: /local/undo/gtk2_ardour/region_editor.h 5 2006-05-31T02:48:48.738745Z paul  $
 */
 
 #ifndef __gtk_ardour_region_edit_h__
index a542be054e115676c1e0e95fcbda0d70faffff3a..0a4a3d29eaf48e47f9048b1e616a7c5b92c99c35 100644 (file)
@@ -1,5 +1,6 @@
 #include <ardour/curve.h>
 #include <ardour/audioregion.h>
+#include <pbd/memento_command.h>
 
 #include "region_gain_line.h"
 #include "audio_region_view.h"
@@ -47,7 +48,8 @@ AudioRegionGainLine::start_drag (ControlPoint* cp, float fraction)
 {
        AutomationLine::start_drag(cp,fraction);
        if (!rv.audio_region().envelope_active()) {
-               trackview.session().add_undo( bind( mem_fun(rv.audio_region(), &AudioRegion::set_envelope_active), false) );
+                trackview.session().add_command(new MementoUndoCommand<AudioRegion>(rv.audio_region(), rv.audio_region().get_state()));
+                rv.audio_region().set_envelope_active(false);
        }
 }
 
@@ -60,17 +62,18 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
        model_representation (cp, mr);
 
        trackview.editor.current_session()->begin_reversible_command (_("remove control point"));
-       trackview.editor.current_session()->add_undo (get_memento());
+        XMLNode &before = get_state();
 
        if (!rv.audio_region().envelope_active()) {
-               trackview.session().add_undo( bind( mem_fun(rv.audio_region(), &AudioRegion::set_envelope_active), false) );
-               trackview.session().add_redo( bind( mem_fun(rv.audio_region(), &AudioRegion::set_envelope_active), true) );
+                XMLNode &before = rv.audio_region().get_state();
                rv.audio_region().set_envelope_active(true);
+                XMLNode &after = rv.audio_region().get_state();
+                trackview.session().add_command(new MementoCommand<AudioRegion>(rv.audio_region(), before, after));
        }
 
        alist.erase (mr.start, mr.end);
 
-       trackview.editor.current_session()->add_redo_no_execute (get_memento());
+       trackview.editor.current_session()->add_command (new MementoCommand<AudioRegionGainLine>(*this, before, get_state()));
        trackview.editor.current_session()->commit_reversible_command ();
        trackview.editor.current_session()->set_dirty ();
 }
@@ -79,8 +82,8 @@ void
 AudioRegionGainLine::end_drag (ControlPoint* cp) 
 {
        if (!rv.audio_region().envelope_active()) {
-               trackview.session().add_redo( bind( mem_fun(rv.audio_region(), &AudioRegion::set_envelope_active), true) );
                rv.audio_region().set_envelope_active(true);
+                trackview.session().add_command(new MementoRedoCommand<AudioRegion>(rv.audio_region(), rv.audio_region().get_state()));
        }
        AutomationLine::end_drag(cp);
 }
index bf6de0d8103d96fca526b83f4146cee4c09be69e..02340c8bae29e49feae6b77dccf36b1a140b8a4c 100644 (file)
@@ -26,6 +26,7 @@ class AudioRegionGainLine : public AutomationLine
 
        void remove_point (ControlPoint&);
 
+        PBD::ID id() { return _id; }
 
 
   private:
@@ -33,6 +34,8 @@ class AudioRegionGainLine : public AutomationLine
        AudioRegionView& rv;
 
        UndoAction get_memento();
+
+        PBD::ID _id;
 };
 
 
index 8b47a17511540f2f142a3fd29ec1588354bd6e18..86ac1e035ed997c9975bec4b3fa1f79367238079 100644 (file)
@@ -287,9 +287,9 @@ void
 RouteParams_UI::cleanup_pre_view (bool stopupdate)
 {
        if (_active_pre_view) {
-               PluginUI *   plugui = 0;
+               LadspaPluginUI *   plugui = 0;
                
-               if (stopupdate && (plugui = dynamic_cast<PluginUI*>(_active_pre_view)) != 0) {
+               if (stopupdate && (plugui = dynamic_cast<LadspaPluginUI*>(_active_pre_view)) != 0) {
                          plugui->stop_updating (0);
                }
 
@@ -304,9 +304,9 @@ void
 RouteParams_UI::cleanup_post_view (bool stopupdate)
 {
        if (_active_post_view) {
-               PluginUI *   plugui = 0;
+               LadspaPluginUI *   plugui = 0;
                
-               if (stopupdate && (plugui = dynamic_cast<PluginUI*>(_active_post_view)) != 0) {
+               if (stopupdate && (plugui = dynamic_cast<LadspaPluginUI*>(_active_post_view)) != 0) {
                          plugui->stop_updating (0);
                }
                _post_plugin_conn.disconnect();
@@ -556,7 +556,7 @@ RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Redirect> redirect,
                                
                if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (insert)) != 0) {                                
 
-                       PluginUI *plugin_ui = new PluginUI (session->engine(), plugin_insert, true);
+                       LadspaPluginUI *plugin_ui = new LadspaPluginUI (session->engine(), plugin_insert, true);
 
                        if (place == PreFader) {
                                cleanup_pre_view();
index cb9883b8e6acf9f8835ac5e8272927510eafd6a2..82d5b53cbab3b6fa58d7face68748f92ac41f356 100644 (file)
@@ -29,6 +29,7 @@
 #include <pbd/error.h>
 #include <pbd/stl_delete.h>
 #include <pbd/whitespace.h>
+#include <pbd/memento_command.h>
 
 #include <gtkmm/menu.h>
 #include <gtkmm/menuitem.h>
@@ -575,46 +576,88 @@ RouteTimeAxisView::set_height (TrackHeight h)
        switch (height_style) {
        case Largest:
                xml_node->add_property ("track_height", "largest");
-               show_name_entry ();
-               hide_name_label ();
-               controls_table.show_all();
                break;
+
        case Large:
                xml_node->add_property ("track_height", "large");
-               show_name_entry ();
-               hide_name_label ();
-               controls_table.show_all();
                break;
+
        case Larger:
                xml_node->add_property ("track_height", "larger");
-               show_name_entry ();
-               hide_name_label ();
-               controls_table.show_all();
                break;
+
        case Normal:
                xml_node->add_property ("track_height", "normal");
+               break;
+
+       case Smaller:
+               xml_node->add_property ("track_height", "smaller");
+               break;
+
+       case Small:
+               xml_node->add_property ("track_height", "small");
+               break;
+       }
+
+       switch (height_style) {
+       case Largest:
+       case Large:
+       case Larger:
+       case Normal:
                show_name_entry ();
                hide_name_label ();
-               controls_table.show_all();
+
+               mute_button->show_all();
+               solo_button->show_all();
+               if (rec_enable_button)
+                       rec_enable_button->show_all();
+
+               edit_group_button.show_all();
+               hide_button.show_all();
+               visual_button.show_all();
+               size_button.show_all();
+               automation_button.show_all();
+               
+               if (is_track() && track()->mode() == ARDOUR::Normal) {
+                       playlist_button.show_all();
+               }
                break;
+
        case Smaller:
-               xml_node->add_property ("track_height", "smaller");
-               controls_table.show_all ();
                show_name_entry ();
                hide_name_label ();
+
+               mute_button->show_all();
+               solo_button->show_all();
+               if (rec_enable_button)
+                       rec_enable_button->show_all();
+
                edit_group_button.hide ();
                hide_button.hide ();
                visual_button.hide ();
                size_button.hide ();
                automation_button.hide ();
-               playlist_button.hide ();
+               
+               if (is_track() && track()->mode() == ARDOUR::Normal) {
+                       playlist_button.hide ();
+               }
                break;
+
        case Small:
-               xml_node->add_property ("track_height", "small");
-               controls_table.hide_all ();
-               controls_table.show ();
                hide_name_entry ();
                show_name_label ();
+
+               mute_button->hide();
+               solo_button->hide();
+               if (rec_enable_button)
+                       rec_enable_button->hide();
+
+               edit_group_button.hide ();
+               hide_button.hide ();
+               visual_button.hide ();
+               size_button.hide ();
+               automation_button.hide ();
+               playlist_button.hide ();
                name_label.set_text (_route->name());
                break;
        }
@@ -1008,12 +1051,12 @@ RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
                }
        }
        
+       XMLNode &before = playlist->get_state();
        switch (op) {
        case Cut:
-               _session.add_undo (playlist->get_memento());
                if ((what_we_got = playlist->cut (time)) != 0) {
                        editor.get_cut_buffer().add (what_we_got);
-                       _session.add_redo_no_execute (playlist->get_memento());
+                       _session.add_command( new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
                        ret = true;
                }
                break;
@@ -1024,9 +1067,8 @@ RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
                break;
 
        case Clear:
-               _session.add_undo (playlist->get_memento());
                if ((what_we_got = playlist->cut (time)) != 0) {
-                       _session.add_redo_no_execute (playlist->get_memento());
+                       _session.add_command( new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
                        what_we_got->unref ();
                        ret = true;
                }
@@ -1055,9 +1097,9 @@ RouteTimeAxisView::paste (jack_nframes_t pos, float times, Selection& selection,
        if (get_diskstream()->speed() != 1.0f)
                pos = session_frame_to_track_frame(pos, get_diskstream()->speed() );
        
-       _session.add_undo (playlist->get_memento());
+       XMLNode &before = playlist->get_state();
        playlist->paste (**p, pos, times);
-       _session.add_redo_no_execute (playlist->get_memento());
+       _session.add_command( new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
 
        return true;
 }
index f4b602d39cfc5291b374c3c97a7f9a877df3a7de..e90355fd0af2ba124a1ccc8bb8c57edf078f7d50 100644 (file)
@@ -25,6 +25,7 @@
 #include <gtkmm2ext/bindable_button.h>
 
 #include <ardour/route_group.h>
+#include <pbd/memento_command.h>
 
 #include "route_ui.h"
 #include "keyboard.h"
@@ -130,9 +131,10 @@ RouteUI::mute_press(GdkEventButton* ev)
                                        /* ctrl-shift-click applies change to all routes */
 
                                        _session.begin_reversible_command (_("mute change"));
-                                       _session.add_undo (_session.global_mute_memento(this));
+                                        Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
                                        _session.set_all_mute (!_route->muted());
-                                       _session.add_redo_no_execute (_session.global_mute_memento(this));
+                                        cmd->mark();
+                                       _session.add_command(cmd);
                                        _session.commit_reversible_command ();
 
                                } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
@@ -205,9 +207,10 @@ RouteUI::solo_press(GdkEventButton* ev)
                                        /* ctrl-shift-click applies change to all routes */
 
                                        _session.begin_reversible_command (_("solo change"));
-                                       _session.add_undo (_session.global_solo_memento(this));
+                                        Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
                                        _session.set_all_solo (!_route->soloed());
-                                       _session.add_redo_no_execute (_session.global_solo_memento(this));
+                                        cmd->mark();
+                                       _session.add_command (cmd);
                                        _session.commit_reversible_command ();
                                        
                                } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
@@ -215,10 +218,11 @@ RouteUI::solo_press(GdkEventButton* ev)
                                        // ctrl-alt-click: exclusively solo this track, not a toggle */
 
                                        _session.begin_reversible_command (_("solo change"));
-                                       _session.add_undo (_session.global_solo_memento(this));
+                                        Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand (_session, this);
                                        _session.set_all_solo (false);
                                        _route->set_solo (true, this);
-                                       _session.add_redo_no_execute (_session.global_solo_memento(this));
+                                        cmd->mark();
+                                       _session.add_command(cmd);
                                        _session.commit_reversible_command ();
 
                                } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
@@ -278,7 +282,7 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
                else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
 
                        _session.begin_reversible_command (_("rec-enable change"));
-                       _session.add_undo (_session.global_record_enable_memento(this));
+                        Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
 
                        if (rec_enable_button->get_active()) {
                                _session.record_disenable_all ();
@@ -286,7 +290,8 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
                                _session.record_enable_all ();
                        }
 
-                       _session.add_redo_no_execute (_session.global_record_enable_memento(this));
+                        cmd->mark();
+                       _session.add_command(cmd);
                        _session.commit_reversible_command ();
 
                } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
@@ -555,9 +560,10 @@ RouteUI::set_mix_group_solo(boost::shared_ptr<Route> route, bool yn)
 
        if((mix_group = route->mix_group()) != 0){
                _session.begin_reversible_command (_("mix group solo  change"));
-               _session.add_undo (_session.global_solo_memento (this));
+                Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
                mix_group->apply(&Route::set_solo, yn, this);
-               _session.add_redo_no_execute (_session.global_solo_memento(this));
+                cmd->mark();
+               _session.add_command (cmd);
                _session.commit_reversible_command ();
        } else {
                reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
@@ -568,8 +574,10 @@ void
 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
 {
        _session.begin_reversible_command (name);
-       _session.add_undo (bind (mem_fun (*_route, func), !yn, (void *) arg));
-       _session.add_redo (bind (mem_fun (*_route, func), yn, (void *) arg));
+        XMLNode &before = _route->get_state();
+        bind(mem_fun(*_route, func), yn, arg)();
+        XMLNode &after = _route->get_state();
+        _session.add_command (new MementoCommand<Route>(*_route, before, after));
        _session.commit_reversible_command ();
 }
 
@@ -577,8 +585,10 @@ void
 RouteUI::reversibly_apply_audio_track_boolean (string name, void (AudioTrack::*func)(bool, void *), bool yn, void *arg)
 {
        _session.begin_reversible_command (name);
-       _session.add_undo (bind (mem_fun (*audio_track(), func), !yn, (void *) arg));
-       _session.add_redo (bind (mem_fun (*audio_track(), func), yn, (void *) arg));
+        XMLNode &before = audio_track()->get_state();
+       bind (mem_fun (*audio_track(), func), yn, arg)();
+        XMLNode &after = audio_track()->get_state();
+       _session.add_command (new MementoCommand<AudioTrack>(*audio_track(), before, after));
        _session.commit_reversible_command ();
 }
 
@@ -589,9 +599,10 @@ RouteUI::set_mix_group_mute(boost::shared_ptr<Route> route, bool yn)
 
        if((mix_group = route->mix_group()) != 0){
                _session.begin_reversible_command (_("mix group mute change"));
-               _session.add_undo (_session.global_mute_memento (this));
+                Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
                mix_group->apply(&Route::set_mute, yn, this);
-               _session.add_redo_no_execute (_session.global_mute_memento(this));
+                cmd->mark();
+               _session.add_command(cmd);
                _session.commit_reversible_command ();
        } else {
                reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
@@ -605,9 +616,10 @@ RouteUI::set_mix_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
 
        if((mix_group = route->mix_group()) != 0){
                _session.begin_reversible_command (_("mix group rec-enable change"));
-               _session.add_undo (_session.global_record_enable_memento (this));
+                Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
                mix_group->apply (&Route::set_record_enable, yn, this);
-               _session.add_redo_no_execute (_session.global_record_enable_memento(this));
+                cmd->mark();
+               _session.add_command(cmd);
                _session.commit_reversible_command ();
        } else {
                reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
index 842d4046d8a5ada75070c902f05ca41b4a74cd10..2e1f3c5273114210ce52d9a56116fcf4b5f0f039 100644 (file)
@@ -128,6 +128,7 @@ TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisVie
 
        controls_table.attach (name_hbox, 0, 4, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
        controls_table.show_all ();
+       controls_table.set_no_show_all ();
 
        controls_vbox.pack_start (controls_table, false, false);
        controls_vbox.show ();
index 7adf702f4d38a843fbeb7a3f75188623e96ad0a5..5e65475c46acbcb155a89bffa22363eb05f39481 100644 (file)
@@ -31,17 +31,17 @@ using namespace Gtk;
 using namespace ARDOUR;
 using namespace PBD;
 
-VSTPluginUI::VSTPluginUI (PluginInsert& pi, VSTPlugin& vp)
+VSTPluginUI::VSTPluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_ptr<VSTPlugin> vp)
        : PlugUIBase (pi),
          vst (vp)
 {
-       fst_run_editor (vst.fst());
+       fst_run_editor (vst->fst());
 
        preset_box.pack_end (bypass_button, false, false, 10);
        preset_box.pack_end (save_button, false, false);
        preset_box.pack_end (combo, false, false);
 
-       bypass_button.set_active (!insert.active());
+       bypass_button.set_active (!insert->active());
        
        pack_start (preset_box, false, false);
        pack_start (socket, true, true);
@@ -55,7 +55,7 @@ VSTPluginUI::~VSTPluginUI ()
 int
 VSTPluginUI::get_preferred_height ()
 {
-       return vst.fst()->height;
+       return vst->fst()->height;
 }
 
 int
@@ -69,7 +69,7 @@ VSTPluginUI::package (Gtk::Window& win)
           this assumes that the window's owner understands the XEmbed protocol.
        */
        
-       socket.add_id (fst_get_XID (vst.fst()));
+       socket.add_id (fst_get_XID (vst->fst()));
 
        return 0;
 }
diff --git a/libs/appleutility/AUOutputBL.cpp b/libs/appleutility/AUOutputBL.cpp
new file mode 100644 (file)
index 0000000..8509f46
--- /dev/null
@@ -0,0 +1,160 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       AUOutputBL.h
+       
+=============================================================================*/
+#include "AUOutputBL.h"
+
+/*
+struct AudioBufferList
+{
+       UInt32          mNumberBuffers;
+       AudioBuffer     mBuffers[1];
+};
+struct AudioBuffer
+{
+       UInt32  mNumberChannels;        //      number of interleaved channels in the buffer
+       UInt32  mDataByteSize;          //      the size of the buffer pointed to by mData
+       void*   mData;                          //      the pointer to the buffer
+};
+*/
+
+AUOutputBL::AUOutputBL (const CAStreamBasicDescription &inDesc, UInt32 inDefaultNumFrames) 
+               : mFormat (inDesc),
+                 mBufferMemory(NULL),
+                 mBufferList (NULL),
+                 mNumberBuffers (0), // keep this here, so can ensure integrity of ABL
+                 mBufferSize (0),
+                 mFrames(inDefaultNumFrames)
+{
+       mNumberBuffers = mFormat.IsInterleaved() ? 1 : mFormat.NumberChannels();
+       mBufferList = reinterpret_cast<AudioBufferList*>(new Byte[sizeof(UInt32) + (mNumberBuffers * sizeof(AudioBuffer))]);
+}
+
+AUOutputBL::~AUOutputBL()
+{
+       if (mBufferMemory)
+               delete[] mBufferMemory;
+
+       if (mBufferList)
+               delete [] mBufferList;
+}
+
+void   AUOutputBL::Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated) 
+{
+       UInt32 channelsPerBuffer = mFormat.IsInterleaved() ? mFormat.NumberChannels() : 1;
+       
+       if (mBufferMemory == NULL || inWantNullBufferIfAllocated)
+       {
+               mBufferList->mNumberBuffers = mNumberBuffers;
+               AudioBuffer *buf = &mBufferList->mBuffers[0];
+               for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) {
+                       buf->mNumberChannels = channelsPerBuffer;
+                       buf->mDataByteSize = mFormat.FramesToBytes (inNumFrames);
+                       buf->mData = NULL;
+               }
+       }
+       else
+       {
+               UInt32 nBytes = mFormat.FramesToBytes (inNumFrames);
+               if ((nBytes * mNumberBuffers) > AllocatedBytes())
+                       throw OSStatus(-10874);//(kAudioUnitErr_TooManyFramesToProcess);
+                       
+               mBufferList->mNumberBuffers = mNumberBuffers;
+               AudioBuffer *buf = &mBufferList->mBuffers[0];
+               Byte* p = mBufferMemory;
+               for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) {
+                       buf->mNumberChannels = channelsPerBuffer;
+                       buf->mDataByteSize = nBytes;
+                       buf->mData = p;
+                       p += mBufferSize;
+               }
+       }
+}
+
+
+void   AUOutputBL::Allocate (UInt32 inNumFrames)
+{
+       if (inNumFrames) 
+       {
+               UInt32 nBytes = mFormat.FramesToBytes (inNumFrames);
+               
+               if (nBytes <= AllocatedBytes()) 
+                       return;
+               
+                       // align successive buffers for Altivec and to take alternating
+                       // cache line hits by spacing them by odd multiples of 16
+               if (mNumberBuffers > 1)
+                       nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10;
+               
+               mBufferSize = nBytes;
+               
+               UInt32 memorySize = mBufferSize * mNumberBuffers;
+               Byte *newMemory = new Byte[memorySize];
+               memset(newMemory, 0, memorySize);       // make buffer "hot"
+               
+               Byte *oldMemory = mBufferMemory;
+               mBufferMemory = newMemory;
+               delete[] oldMemory;
+               
+               mFrames = inNumFrames;
+       } 
+       else 
+       {
+               if (mBufferMemory) {
+                       delete [] mBufferMemory;
+                       mBufferMemory = NULL;
+               }
+               mBufferSize = 0;
+               mFrames = 0;
+       }
+}
+
+#if DEBUG
+void                   AUOutputBL::Print()
+{
+       printf ("AUOutputBL::Print\n");
+       mFormat.Print();
+       printf ("Num Buffers:%ld, mFrames:%ld, allocatedMemory:%c\n", mBufferList->mNumberBuffers, mFrames, (mBufferMemory != NULL ? 'T' : 'F'));
+       AudioBuffer *buf = &mBufferList->mBuffers[0];
+       for (UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i, ++buf)
+               printf ("\tBuffer:%ld, Size:%ld, Chans:%ld, Buffer:%X\n", i, buf->mDataByteSize, buf->mNumberChannels, int(buf->mData));
+}
+#endif
+
diff --git a/libs/appleutility/AUOutputBL.h b/libs/appleutility/AUOutputBL.h
new file mode 100644 (file)
index 0000000..b80588a
--- /dev/null
@@ -0,0 +1,115 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       AUOutputBL.h
+       
+=============================================================================*/
+
+#ifndef __AUOutputBL_h__
+#define __AUOutputBL_h__
+
+#include "CAStreamBasicDescription.h"
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <CoreServices/CoreServices.h>
+#else
+       #include <AssertMacros.h>
+#endif
+
+// ____________________________________________________________________________
+//
+//     AUOutputBL - Simple Buffer List wrapper targetted to use with retrieving AU output
+// Works in one of two ways (both adjustable)... Can use it with NULL pointers, or allocate
+// memory to receive the data in.
+
+// Before using this with any call to AudioUnitRender, it needs to be Prepared
+// as some calls to AudioUnitRender can reset the ABL
+
+class AUOutputBL {
+public:
+                                                                                       
+                                                                                       // you CANNOT use one of these - it will crash!
+//                                                                             AUOutputBL ();
+                                                                               
+                                                                                       // this is the constructor that you use
+                                                                                       // it can't be reset once you've constructed it
+                                                                               AUOutputBL (const CAStreamBasicDescription &inDesc, UInt32 inDefaultNumFrames = 512);
+                                                                               ~AUOutputBL();
+
+       void                                                            Prepare ()
+                                                                               {
+                                                                                       Prepare (mFrames);
+                                                                               }
+                                                                       
+                                                               // this version can throw if this is an allocted ABL and inNumFrames is > AllocatedFrames()
+                                                               // you can set the bool to true if you want a NULL buffer list even if allocated
+                                                               // inNumFrames must be a valid number (will throw if inNumFrames is 0)
+       void                                                            Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated = false);
+       
+       AudioBufferList*                                        ABL() { return mBufferList; }
+                                                               
+                                                               // You only need to call this if you want to allocate a buffer list
+                                                               // if you want an empty buffer list, just call Prepare()
+                                                               // if you want to dispose previously allocted memory, pass in 0
+                                                               // then you either have an empty buffer list, or you can re-allocate
+                                                               // Memory is kept around if an Allocation request is less than what is currently allocated
+       void                                                            Allocate (UInt32 inNumberFrames);
+       
+       UInt32                                                          AllocatedFrames() const { return mFrames; }
+       
+       const CAStreamBasicDescription&         GetFormat() const { return mFormat; }
+
+#if DEBUG
+       void                                                            Print();
+#endif
+       
+private:
+       UInt32                                          AllocatedBytes () const { return (mBufferSize * mNumberBuffers); }
+
+       CAStreamBasicDescription        mFormat;
+       Byte*                                           mBufferMemory;
+       AudioBufferList*                        mBufferList;
+       UInt32                                          mNumberBuffers;
+       UInt32                                          mBufferSize;
+       UInt32                                          mFrames;
+
+// don't want to copy these.. can if you want, but more code to write!
+       AUOutputBL (const AUOutputBL &c) {}
+       AUOutputBL& operator= (const AUOutputBL& c) { return *this; }
+};
+
+#endif // __AUOutputBL_h__
diff --git a/libs/appleutility/CAAudioChannelLayout.cpp b/libs/appleutility/CAAudioChannelLayout.cpp
new file mode 100644 (file)
index 0000000..585ff44
--- /dev/null
@@ -0,0 +1,138 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CAAudioChannelLayout.cpp
+
+=============================================================================*/
+
+//=============================================================================
+//     Includes
+//=============================================================================
+
+//     Self Include
+#include "CAAudioChannelLayout.h"
+#include <stdlib.h>
+#include <string.h>
+
+//=============================================================================
+//     CAAudioChannelLayout
+//=============================================================================
+
+AudioChannelLayout*    CAAudioChannelLayout::Create(UInt32 inNumberChannelDescriptions)
+{
+       UInt32 theSize = CalculateByteSize(inNumberChannelDescriptions);
+       AudioChannelLayout* theAnswer = static_cast<AudioChannelLayout*>(calloc(1, theSize));
+       if(theAnswer != NULL)
+       {
+               SetAllToUnknown(*theAnswer, inNumberChannelDescriptions);
+       }
+       return theAnswer;
+}
+
+void   CAAudioChannelLayout::Destroy(AudioChannelLayout* inChannelLayout)
+{
+       free(inChannelLayout);
+}
+
+void   CAAudioChannelLayout::SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions)
+{
+       outChannelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
+       outChannelLayout.mChannelBitmap = 0;
+       outChannelLayout.mNumberChannelDescriptions = inNumberChannelDescriptions;
+       for(UInt32 theChannelIndex = 0; theChannelIndex < inNumberChannelDescriptions; ++theChannelIndex)
+       {
+               outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelLabel = kAudioChannelLabel_Unknown;
+               outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelFlags = 0;
+               outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[0] = 0;
+               outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[1] = 0;
+               outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[2] = 0;
+       }
+}
+
+bool   operator== (const AudioChannelLayout &x, const AudioChannelLayout &y)
+{
+       // compare based on the number of channel descriptions present
+       // (this may be too strict a comparison if all you care about are matching layout tags)
+       UInt32 theSize1 = CAAudioChannelLayout::CalculateByteSize(x.mNumberChannelDescriptions);
+       UInt32 theSize2 = CAAudioChannelLayout::CalculateByteSize(y.mNumberChannelDescriptions);
+       
+       if (theSize1 != theSize2)
+               return false;
+               
+       return !memcmp (&x, &y, theSize1);
+}
+
+// counting the one bits in a word
+inline UInt32 CountOnes(UInt32 x)
+{
+       // secret magic algorithm for counting bits in a word.
+       UInt32 t;
+       x = x - ((x >> 1) & 0x55555555);
+       t = ((x >> 2) & 0x33333333);
+       x = (x & 0x33333333) + t;
+       x = (x + (x >> 4)) & 0x0F0F0F0F;
+       x = x + (x << 8);
+       x = x + (x << 16);
+       return x >> 24;
+}
+
+UInt32 CAAudioChannelLayout::NumberChannels (const AudioChannelLayout& inLayout)
+{
+       if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
+               return inLayout.mNumberChannelDescriptions;
+       
+       if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
+               return CountOnes (inLayout.mChannelBitmap);
+
+       return AudioChannelLayoutTag_GetNumberOfChannels(inLayout.mChannelLayoutTag);
+}
+
+void   CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout)
+{
+       fprintf (file, "\tTag=0x%lX, ", layout->mChannelLayoutTag);
+       if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
+               fprintf (file, "Using Bitmap:0x%lX\n", layout->mChannelBitmap);
+       else {
+               fprintf (file, "Num Chan Descs=%ld\n", layout->mNumberChannelDescriptions);
+               const AudioChannelDescription *desc = layout->mChannelDescriptions;
+               for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; ++i, ++desc) {
+                       fprintf (file, "\t\tLabel=%ld, Flags=0x%lX, ", desc->mChannelLabel, desc->mChannelFlags);
+                       fprintf (file, "[az=%f,el=%f,dist=%f]\n", desc->mCoordinates[0], desc->mCoordinates[1], desc->mCoordinates[2]);
+               }
+       }
+}
diff --git a/libs/appleutility/CAAudioChannelLayout.h b/libs/appleutility/CAAudioChannelLayout.h
new file mode 100644 (file)
index 0000000..8f995b8
--- /dev/null
@@ -0,0 +1,162 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CAAudioChannelLayout.h
+
+=============================================================================*/
+#if !defined(__CAAudioChannelLayout_h__)
+#define __CAAudioChannelLayout_h__
+
+//=============================================================================
+//     Includes
+//=============================================================================
+
+//     System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <CoreAudio/CoreAudioTypes.h>
+       #include <CoreFoundation/CoreFoundation.h>
+#else
+       #include <CoreAudioTypes.h>
+       #include <CoreFoundation.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !HAL_Build
+       #include "CAReferenceCounted.h"
+#endif
+
+//=============================================================================
+//     CAAudioChannelLayout
+//=============================================================================
+
+bool   operator== (const AudioChannelLayout &x, const AudioChannelLayout &y);
+
+extern "C" void        CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout);
+
+class CAAudioChannelLayout
+{
+//     static Construction/Destruction
+public:
+       static AudioChannelLayout*      Create(UInt32 inNumberChannelDescriptions);
+       static void                                     Destroy(AudioChannelLayout* inChannelLayout);
+       static UInt32                           CalculateByteSize(UInt32 inNumberChannelDescriptions) { 
+                                                                       return offsetof(AudioChannelLayout, mChannelDescriptions) + inNumberChannelDescriptions * sizeof(AudioChannelDescription);
+                                                               }
+       static void                                     SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions);
+       static UInt32                           NumberChannels(const AudioChannelLayout& inLayout);
+       
+#if !HAL_Build
+// object methods      
+public:
+                                                               CAAudioChannelLayout ();
+
+                                                               CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround);
+                                                                       // if inChooseSurround is false, then symmetrical speaker arrangements
+                                                                       // are chosen in place of surround layouts if there is a choice
+                                                                       // This call chooses layouts based on the expected defaults in 
+                                                                       // AudioUnit usage
+                                                               CAAudioChannelLayout (AudioChannelLayoutTag inTag);
+                                                               CAAudioChannelLayout (const CAAudioChannelLayout &c);
+                                                               CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout);
+                                                               ~CAAudioChannelLayout();
+       
+       CAAudioChannelLayout&           operator= (const AudioChannelLayout* inChannelLayout);
+       CAAudioChannelLayout&           operator= (const CAAudioChannelLayout& c);
+       bool                                            operator== (const CAAudioChannelLayout &c) const;
+
+       void                                            SetWithTag(AudioChannelLayoutTag inTag);
+
+       bool                                            IsValid() const { return NumberChannels() > 0; }
+       UInt32                                          Size() const { return mLayoutHolder ? mLayoutHolder->Size() : 0; }
+       
+       UInt32                                          NumberChannels() const { return NumberChannels(Layout()); }
+       
+       AudioChannelLayoutTag           Tag() const { return Layout().mChannelLayoutTag; }
+       const AudioChannelLayout&       Layout() const { return mLayoutHolder->Layout(); }
+       operator const AudioChannelLayout *() const { return &Layout(); }
+       
+       void                                            Print () const { Print (stdout); }
+       void                                            Print (FILE* file) const;
+
+       OSStatus                                        Save (CFPropertyListRef *outData) const;
+       OSStatus                                        Restore (CFPropertyListRef &inData);
+       
+private:
+       class ACLRefCounter : public CAReferenceCounted {
+       public:
+                               ACLRefCounter (UInt32 inDataSize) 
+                               { 
+                                       if (inDataSize < offsetof(AudioChannelLayout, mChannelDescriptions))
+                                               inDataSize = offsetof(AudioChannelLayout, mChannelDescriptions);
+                                               
+                                       mLayout = static_cast<AudioChannelLayout*>(malloc (inDataSize));
+                                       memset (mLayout, 0, inDataSize);
+                                       mByteSize = inDataSize;
+                               }
+       
+               const AudioChannelLayout &      Layout() const { return *mLayout; }
+               
+               UInt32                                          Size () const { return mByteSize; }
+               
+       private:
+               AudioChannelLayout      *mLayout;
+               UInt32                          mByteSize;
+               
+                       // only the constructors can change the actual state of the layout
+               friend CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround);
+               friend OSStatus CAAudioChannelLayout::Restore (CFPropertyListRef &inData);
+               friend CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout);
+               friend void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag);
+               
+               AudioChannelLayout *    GetLayout() { return mLayout; }
+               ~ACLRefCounter() { if (mLayout) { free(mLayout); mLayout = NULL; } }
+       
+       private:
+               ACLRefCounter () : mLayout(NULL) { }
+               ACLRefCounter(const ACLRefCounter& c) : mLayout(NULL) { }
+               ACLRefCounter& operator=(const ACLRefCounter& c) { return *this; }
+       };
+       
+       ACLRefCounter                           *mLayoutHolder;
+#endif //      HAL_Build
+
+};
+
+#endif
diff --git a/libs/appleutility/CAAudioChannelLayoutObject.cpp b/libs/appleutility/CAAudioChannelLayoutObject.cpp
new file mode 100644 (file)
index 0000000..8c40300
--- /dev/null
@@ -0,0 +1,199 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+    CAAudioChannelLayoutObject.cpp
+=============================================================================*/
+
+#include "CAAudioChannelLayout.h"
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <CoreServices/CoreServices.h>
+       #include <AudioToolbox/AudioFormat.h>
+#else
+       #include <CoreServices.h>
+       #include <AudioFormat.h>
+#endif
+
+
+CAAudioChannelLayout::CAAudioChannelLayout ()
+{
+       mLayoutHolder = new ACLRefCounter (offsetof(AudioChannelLayout, mChannelDescriptions));
+}
+
+//=============================================================================
+//     CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround)
+{              
+               // this chooses default layouts based on the number of channels...
+       UInt32 theSize = CalculateByteSize (inNumberChannels);
+               
+       mLayoutHolder = new ACLRefCounter (theSize);
+       
+       AudioChannelLayout* layout = mLayoutHolder->GetLayout();
+
+       layout->mNumberChannelDescriptions = inNumberChannels;
+       
+       switch (inNumberChannels) 
+       {
+               case 1:
+                       layout->mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
+                       break;
+               case 2:
+                       layout->mChannelLayoutTag = inChooseSurround ? kAudioChannelLayoutTag_Binaural : kAudioChannelLayoutTag_Stereo;
+                       break;
+               case 4:
+                       layout->mChannelLayoutTag = inChooseSurround ? kAudioChannelLayoutTag_Ambisonic_B_Format : kAudioChannelLayoutTag_AudioUnit_4;
+                       break;
+               case 5:
+                       layout->mChannelLayoutTag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_5_0 : kAudioChannelLayoutTag_AudioUnit_5;
+                       break;
+               case 6:
+                       layout->mChannelLayoutTag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_6_0 : kAudioChannelLayoutTag_AudioUnit_6;
+                       break;
+               case 7:
+                       layout->mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_7_0;
+                       break;
+               case 8:
+                       layout->mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_8;
+                       break;
+               default:
+                       // here we have a "broken" layout, in the sense that we haven't any idea how to lay this out
+                       // the layout itself is all set to zeros
+                       // ### no longer true ###
+                       SetAllToUnknown(*layout, inNumberChannels);
+                       break;
+       }
+}
+
+//=============================================================================
+//     CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (AudioChannelLayoutTag inLayoutTag)
+       : mLayoutHolder(NULL)
+{
+       SetWithTag(inLayoutTag);
+}
+
+//=============================================================================
+//     CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (const CAAudioChannelLayout &c)
+       : mLayoutHolder(NULL)
+{
+       *this = c;
+}
+
+
+//=============================================================================
+//     CAAudioChannelLayout::AudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout)
+       : mLayoutHolder(NULL)
+{
+       *this = inChannelLayout;
+}
+
+//=============================================================================
+//     CAAudioChannelLayout::~CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout::~CAAudioChannelLayout ()
+{
+       if (mLayoutHolder) {
+               mLayoutHolder->release();
+               mLayoutHolder = NULL;
+       }
+}
+
+//=============================================================================
+//     CAAudioChannelLayout::CAAudioChannelLayout
+//=============================================================================
+CAAudioChannelLayout& CAAudioChannelLayout::operator= (const CAAudioChannelLayout &c)
+{
+       if (mLayoutHolder != c.mLayoutHolder) {
+               if (mLayoutHolder)
+                       mLayoutHolder->release();
+       
+               if ((mLayoutHolder = c.mLayoutHolder) != NULL)
+                       mLayoutHolder->retain();
+       }
+       
+       return *this;
+}
+
+CAAudioChannelLayout&  CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout)
+{
+       if (mLayoutHolder)
+               mLayoutHolder->release();
+
+       UInt32 theSize = CalculateByteSize (inChannelLayout->mNumberChannelDescriptions);
+       
+       mLayoutHolder = new ACLRefCounter (theSize);
+       
+       memcpy(mLayoutHolder->mLayout, inChannelLayout, theSize);
+       return *this;
+}
+
+void   CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag)
+{
+       if (mLayoutHolder)
+               mLayoutHolder->release();
+       
+       mLayoutHolder = new ACLRefCounter(offsetof(AudioChannelLayout, mChannelDescriptions[0]));
+       AudioChannelLayout* layout = mLayoutHolder->GetLayout();
+       layout->mChannelLayoutTag = inTag;
+}
+
+//=============================================================================
+//     CAAudioChannelLayout::operator==
+//=============================================================================
+bool           CAAudioChannelLayout::operator== (const CAAudioChannelLayout &c) const
+{
+       if (mLayoutHolder == c.mLayoutHolder)
+               return true;
+       return Layout() == c.Layout();
+}
+
+//=============================================================================
+//     CAAudioChannelLayout::Print
+//=============================================================================
+void           CAAudioChannelLayout::Print (FILE* file) const
+{
+       CAShowAudioChannelLayout (file, &Layout());
+}
+
diff --git a/libs/appleutility/CAAudioUnit.cpp b/libs/appleutility/CAAudioUnit.cpp
new file mode 100644 (file)
index 0000000..9244877
--- /dev/null
@@ -0,0 +1,1202 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CAAudioUnit.cpp
+=============================================================================*/
+
+#include "CAAudioUnit.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <AudioUnit/MusicDevice.h>
+#else
+       #include <MusicDevice.h>
+#endif
+
+#include "CAReferenceCounted.h"
+#include "AUOutputBL.h" //this is for the Preroll only
+
+
+struct StackAUChannelInfo {
+               StackAUChannelInfo (UInt32 inSize) : mChanInfo ((AUChannelInfo*)malloc (inSize)) {}
+               ~StackAUChannelInfo() { free (mChanInfo); }
+               
+       AUChannelInfo* mChanInfo;
+};
+
+
+
+class CAAudioUnit::AUState : public CAReferenceCounted  {
+public:
+       AUState (Component inComp)
+                                               : mUnit(0), mNode (0)
+                                               { 
+                                                       OSStatus result = ::OpenAComponent (inComp, &mUnit); 
+                                                       if (result)
+                                                               throw result;
+                                                       Init();
+                                               }
+
+       AUState (const AUNode &inNode, const AudioUnit& inUnit)
+                                               : mUnit (inUnit), mNode (inNode) 
+                                               {
+                                                       Init();
+                                               }
+                                               
+       ~AUState();
+                                                                                       
+       AudioUnit                       mUnit;
+       AUNode                          mNode;
+
+       OSStatus                        GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+                                                                                       Float32 &outValue) const
+       {
+                       if (mGetParamProc != NULL) {
+                               return reinterpret_cast<AudioUnitGetParameterProc>(mGetParamProc) (mConnInstanceStorage, 
+                                                                               inID, scope, element, &outValue);
+                       }                                                       
+               return AudioUnitGetParameter(mUnit, inID, scope, element, &outValue);
+       }
+
+       OSStatus                        SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+                                                                                       Float32 value, UInt32 bufferOffsetFrames)
+       {
+                       if (mSetParamProc != NULL) {
+                               return reinterpret_cast<AudioUnitSetParameterProc>(mSetParamProc) (mConnInstanceStorage, 
+                                                                               inID, scope, element, value, bufferOffsetFrames);
+                       }                                                       
+                       return AudioUnitSetParameter(mUnit, inID, scope, element, value, bufferOffsetFrames);
+       }
+       
+       OSStatus                        Render (AudioUnitRenderActionFlags *  ioActionFlags,
+                                                               const AudioTimeStamp *        inTimeStamp,
+                                                               UInt32                        inOutputBusNumber,
+                                                               UInt32                        inNumberFrames,
+                                                               AudioBufferList *             ioData)
+       {
+               if (mRenderProc != NULL) {
+                       return reinterpret_cast<AudioUnitRenderProc>(mRenderProc) (mConnInstanceStorage, 
+                                                                       ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
+               }                                                       
+               return AudioUnitRender(mUnit, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
+       }
+       
+       OSStatus                MIDIEvent (UInt32                                       inStatus,
+                                                               UInt32                                  inData1,
+                                                               UInt32                                  inData2,
+                                                               UInt32                                  inOffsetSampleFrame)
+       {
+#if !TARGET_OS_WIN32
+               if (mMIDIEventProc != NULL) {
+                       return reinterpret_cast<MusicDeviceMIDIEventProc>(mMIDIEventProc) (mConnInstanceStorage, 
+                                                                       inStatus, inData1, inData2, inOffsetSampleFrame);
+               }
+               return MusicDeviceMIDIEvent (mUnit, inStatus, inData1, inData2, inOffsetSampleFrame);
+#else
+               return paramErr;
+#endif
+       }
+
+       OSStatus                                StartNote (MusicDeviceInstrumentID      inInstrument,
+                                                                       MusicDeviceGroupID                      inGroupID,
+                                                                       NoteInstanceID *                        outNoteInstanceID,
+                                                                       UInt32                                          inOffsetSampleFrame,
+                                                                       const MusicDeviceNoteParams * inParams)
+       {
+#if !TARGET_OS_WIN32
+               return MusicDeviceStartNote (mUnit, inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams);
+#else
+               return paramErr;
+#endif
+       }
+       OSStatus                                StopNote (MusicDeviceGroupID            inGroupID,
+                                                                       NoteInstanceID                          inNoteInstanceID,
+                                                                       UInt32                                          inOffsetSampleFrame)
+       {
+#if !TARGET_OS_WIN32
+               return MusicDeviceStopNote (mUnit, inGroupID, inNoteInstanceID, inOffsetSampleFrame);
+#else
+               return paramErr;
+#endif
+       }
+
+private:
+       // get the fast dispatch pointers
+       void Init() 
+       {
+               UInt32 size = sizeof(AudioUnitRenderProc);
+               if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
+                                                               kAudioUnitScope_Global, kAudioUnitRenderSelect,
+                                                               &mRenderProc, &size) != noErr)
+                       mRenderProc = NULL;
+               if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
+                                                               kAudioUnitScope_Global, kAudioUnitGetParameterSelect,
+                                                               &mGetParamProc, &size) != noErr)
+                       mGetParamProc = NULL;
+               if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
+                                                               kAudioUnitScope_Global, kAudioUnitSetParameterSelect,
+                                                               &mSetParamProc, &size) != noErr)
+                       mSetParamProc = NULL;
+
+               if (AudioUnitGetProperty(mUnit, kAudioUnitProperty_FastDispatch,
+                                                               kAudioUnitScope_Global, kMusicDeviceMIDIEventSelect,
+                                                               &mMIDIEventProc, &size) != noErr)
+                       mMIDIEventProc = NULL;
+               
+               if (mRenderProc || mGetParamProc || mSetParamProc || mMIDIEventProc)
+                       mConnInstanceStorage = GetComponentInstanceStorage(mUnit);
+               else
+                       mConnInstanceStorage = NULL;
+       }
+       
+       ProcPtr                                         mRenderProc, mGetParamProc, mSetParamProc, mMIDIEventProc;
+
+       void *                                          mConnInstanceStorage;
+
+private:
+               // get the compiler to tell us when we do a bad thing!!!
+       AUState () {}
+       AUState (const AUState&) {}
+       AUState& operator= (const AUState&) { return *this; } 
+};                                             
+                                               
+                                               
+CAAudioUnit::AUState::~AUState ()
+{
+       if (mUnit && (mNode == 0)) {
+               ::CloseComponent (mUnit);
+       }
+       mNode = 0;
+       mUnit = 0;
+}
+
+OSStatus               CAAudioUnit::Open (const CAComponent& inComp, CAAudioUnit &outUnit)
+{
+       try {
+               outUnit = inComp; 
+               return noErr;
+       } catch (OSStatus res) {
+               return res;
+       } catch (...) {
+               return -1;
+       }
+}
+
+CAAudioUnit::CAAudioUnit (const AudioUnit& inUnit)
+       : mComp (inUnit), mDataPtr (new AUState (-1, inUnit))
+{
+}
+
+CAAudioUnit::CAAudioUnit (const CAComponent& inComp)
+       : mComp (inComp), mDataPtr (0)
+{
+       mDataPtr = new AUState (mComp.Comp());
+}
+
+CAAudioUnit::CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit)
+       : mComp (inUnit), mDataPtr(new AUState (inNode, inUnit)) 
+{
+}
+
+CAAudioUnit::~CAAudioUnit ()
+{
+       if (mDataPtr) {
+               mDataPtr->release();
+               mDataPtr = NULL;
+       }
+}
+
+CAAudioUnit&   CAAudioUnit::operator= (const CAAudioUnit &a)
+{
+       if (mDataPtr != a.mDataPtr) {
+               if (mDataPtr)
+                       mDataPtr->release();
+       
+               if ((mDataPtr = a.mDataPtr) != NULL)
+                       mDataPtr->retain();
+               
+               mComp = a.mComp;
+       }
+       
+       return *this;
+}
+
+bool                   CAAudioUnit::operator== (const CAAudioUnit& y) const
+{
+       if (mDataPtr == y.mDataPtr) return true;
+       AudioUnit au1 = mDataPtr ? mDataPtr->mUnit : 0;
+       AudioUnit au2 = y.mDataPtr ? y.mDataPtr->mUnit : 0;
+       return au1 == au2;
+}
+
+bool                   CAAudioUnit::operator== (const AudioUnit& y) const
+{
+       if (!mDataPtr) return false;
+       return mDataPtr->mUnit == y;
+}
+
+#pragma mark __State Management        
+
+bool                   CAAudioUnit::IsValid () const 
+{ 
+       return mDataPtr ? mDataPtr->mUnit != 0 : false; 
+}
+       
+AudioUnit              CAAudioUnit::AU() const 
+{ 
+       return mDataPtr ? mDataPtr->mUnit : 0; 
+}
+
+AUNode                 CAAudioUnit::GetAUNode () const
+{
+       return mDataPtr ? mDataPtr->mNode : 0; 
+}
+
+#pragma mark __Format Handling
+       
+bool           CAAudioUnit::CanDo (    int                             inChannelsIn, 
+                                                                       int                             inChannelsOut) const
+{              
+       // this is the default assumption of an audio effect unit
+       Boolean* isWritable = 0;
+       UInt32  dataSize = 0;
+               // lets see if the unit has any channel restrictions
+       OSStatus result = AudioUnitGetPropertyInfo (AU(),
+                                                                       kAudioUnitProperty_SupportedNumChannels,
+                                                                       kAudioUnitScope_Global, 0,
+                                                                       &dataSize, isWritable); //don't care if this is writable
+               
+               // if this property is NOT implemented an FX unit
+               // is expected to deal with same channel valance in and out
+       if (result) 
+       {
+               if (Comp().Desc().IsEffect() && (inChannelsIn == inChannelsOut)
+                       || Comp().Desc().IsOffline() && (inChannelsIn == inChannelsOut))
+               {
+                       return true;
+               }
+               else 
+               {
+                       // the au should either really tell us about this
+                       // or we will assume the worst
+                       return false;
+               }
+       }
+       
+       StackAUChannelInfo info (dataSize);
+       
+       result = GetProperty (kAudioUnitProperty_SupportedNumChannels,
+                                                       kAudioUnitScope_Global, 0,
+                                                       info.mChanInfo, &dataSize);
+       if (result) { return false; }
+       
+       return ValidateChannelPair (inChannelsIn, inChannelsOut, info.mChanInfo, (dataSize / sizeof (AUChannelInfo)));
+}
+
+bool   CAAudioUnit::ValidateChannelPair (int                           inChannelsIn, 
+                                                                               int                             inChannelsOut,
+                                                                               const AUChannelInfo * info,
+                                                                               UInt32                          numChanInfo) const
+{
+// we've the following cases (some combinations) to test here:
+/*
+>0             An explicit number of channels on either side
+0              that side (generally input!) has no elements
+-1             wild card:
+-1,-1  any num channels as long as same channels on in and out
+-1,-2  any num channels channels on in and out - special meaning
+-2+    indicates total num channs AU can handle 
+                       - elements configurable to any num channels, 
+                       - element count in scope must be writable
+*/
+
+       //now chan layout can contain -1 for either scope (ie. doesn't care)
+       for (unsigned int i = 0; i < numChanInfo; ++i)
+       {
+                       //less than zero on both sides - check for special attributes
+               if ((info[i].inChannels < 0) && (info[i].outChannels < 0))
+               {
+                               // these are our wild card matches
+                       if (info[i].inChannels == -1 && info[i].outChannels == -1) {
+                               if (inChannelsOut == inChannelsIn) {
+                                       return true;
+                               }
+                       }
+                       else if ((info[i].inChannels == -1 && info[i].outChannels == -2)
+                                       || (info[i].inChannels == -2 && info[i].outChannels == -1)) 
+                       {
+                               return true;
+                       }
+                               // these are our total num channels matches
+                               // element count MUST be writable
+                       else {
+                               bool outWrite = false; bool inWrite = false;
+                               IsElementCountWritable (kAudioUnitScope_Output, outWrite);
+                               IsElementCountWritable (kAudioUnitScope_Input, inWrite);
+                               if (inWrite && outWrite) {
+                                       if ((inChannelsOut <= abs(info[i].outChannels))
+                                               && (inChannelsIn <= abs(info[i].inChannels))) 
+                                       {
+                                               return true;
+                                       }
+                               }
+                       }
+               }
+                       
+                       // special meaning on input, specific num on output
+               else if (info[i].inChannels < 0) {
+                       if (info[i].outChannels == inChannelsOut) 
+                       {
+                                       // can do any in channels
+                               if (info[i].inChannels == -1) {
+                                       return true;
+                               } 
+                                       // total chans on input
+                               else {
+                                       bool inWrite = false;
+                                       IsElementCountWritable (kAudioUnitScope_Input, inWrite);
+                                       if (inWrite && (inChannelsIn <= abs(info[i].inChannels))) {
+                                               return true;
+                                       }
+                               }
+                       }
+               }
+               
+                       // special meaning on output, specific num on input
+               else if (info[i].outChannels < 0) {
+                       if (info[i].inChannels == inChannelsIn) 
+                       {
+                                       // can do any out channels
+                               if (info[i].outChannels == -1) {
+                                       return true;
+                               } 
+                                       // total chans on output
+                               else {
+                                       bool outWrite = false;
+                                       IsElementCountWritable (kAudioUnitScope_Output, outWrite);
+                                       if (outWrite && (inChannelsOut <= abs(info[i].outChannels))) {
+                                               return true;
+                                       }
+                               }
+                       }
+               }
+
+                       // both chans in struct >= 0 - thus has to explicitly match
+               else if ((info[i].inChannels == inChannelsIn) && (info[i].outChannels == inChannelsOut)) {
+                       return true;
+               } 
+               
+                       // now check to see if a wild card on the args (inChannelsIn or inChannelsOut chans is zero) is found 
+                       // tells us to match just one side of the scopes
+               else if (inChannelsIn == 0) {
+                       if (info[i].outChannels == inChannelsOut) {
+                               return true;
+                       }
+               }
+               else if (inChannelsOut == 0) {
+                       if (info[i].inChannels == inChannelsIn) {
+                               return true;
+                       }
+               }
+       }
+       
+       return false;
+}
+
+bool CheckDynCount (SInt32 inTotalChans, const CAAUChanHelper &inHelper)
+{
+       int totalChans = 0;
+       for (unsigned int i = 0; i < inHelper.mNumEls; ++i)
+               totalChans += inHelper.mChans[i];
+       return (totalChans <= inTotalChans);
+}
+
+bool   CAAudioUnit::CheckOneSide (const CAAUChanHelper         &inHelper, 
+                                                                       bool                                    checkOutput, 
+                                                                       const AUChannelInfo             *info, 
+                                                                       UInt32                                  numInfo) const
+{
+               // now we can use the wildcard option (see above impl) to see if this matches
+       for (unsigned int el = 0; el < inHelper.mNumEls; ++el) {
+               bool testAlready = false;
+               for (unsigned int i = 0; i < el; ++i) {
+                       if (inHelper.mChans[i] == inHelper.mChans[el]) {
+                               testAlready = true;
+                               break;
+                       }
+               }
+               if (!testAlready) {
+                       if (checkOutput) {
+                               if (!ValidateChannelPair (0, inHelper.mChans[el], info, numInfo)) return false;
+                       } else {
+                               if (!ValidateChannelPair (inHelper.mChans[el], 0, info, numInfo)) return false;
+                       }
+               }
+       }
+       return true;
+}
+
+bool           CAAudioUnit::CanDo (const CAAUChanHelper                &inputs,  
+                                                               const CAAUChanHelper            &outputs) const
+
+{
+// first check our state
+               // huh!
+       if (inputs.mNumEls == 0 && outputs.mNumEls == 0) return false;
+       
+       UInt32 elCount;
+       if (GetElementCount (kAudioUnitScope_Input, elCount)) { return false; }
+       if (elCount != inputs.mNumEls) return false;
+
+       if (GetElementCount (kAudioUnitScope_Output, elCount)) { return false; }
+       if (elCount != outputs.mNumEls) return false;
+               
+// (1) special cases (effects and sources (generators and instruments) only)
+       UInt32  dataSize = 0;
+       if (GetPropertyInfo (kAudioUnitProperty_SupportedNumChannels,
+                                                                       kAudioUnitScope_Global, 0, &dataSize, NULL) != noErr) 
+       {
+               if (Comp().Desc().IsEffect() || Comp().Desc().IsOffline()) {
+                       UInt32 numChan = outputs.mNumEls > 0 ? outputs.mChans[0] : inputs.mChans[0];
+                       for (unsigned int in = 0; in < inputs.mNumEls; ++in)
+                               if (numChan != inputs.mChans[in]) return false;
+                       for (unsigned int out = 0; out < outputs.mNumEls; ++out)
+                               if (numChan != outputs.mChans[out]) return false;
+                       return true;
+               }
+               
+                       // in this case, all the channels have to match the current config
+               if (Comp().Desc().IsGenerator() || Comp().Desc().IsMusicDevice()) {
+                       for (unsigned int in = 0; in < inputs.mNumEls; ++in) {
+                               UInt32 chan;
+                               if (NumberChannels (kAudioUnitScope_Input, in, chan)) return false;
+                               if (chan != UInt32(inputs.mChans[in])) return false;
+                       }
+                       for (unsigned int out = 0; out < outputs.mNumEls; ++out) {
+                               UInt32 chan;
+                               if (NumberChannels (kAudioUnitScope_Output, out, chan)) return false;
+                               if (chan != UInt32(outputs.mChans[out])) return false;
+                       }
+                       return true;
+               }
+               
+                       // if we get here we can't determine anything about channel capabilities
+               return false;
+       }
+
+       StackAUChannelInfo info (dataSize);
+       
+       if (GetProperty (kAudioUnitProperty_SupportedNumChannels,
+                                                       kAudioUnitScope_Global, 0,
+                                                       info.mChanInfo, &dataSize) != noErr)
+       { 
+               return false; 
+       }
+       
+       int numInfo = dataSize / sizeof(AUChannelInfo);
+       
+// (2) Test for dynamic capability (or no elements on that scope)
+       SInt32 dynInChans = 0;
+       if (ValidateDynamicScope (kAudioUnitScope_Input, dynInChans, info.mChanInfo, numInfo)) {
+               if (CheckDynCount (dynInChans, inputs) == false) return false;
+       }
+
+       SInt32 dynOutChans = 0;
+       if (ValidateDynamicScope (kAudioUnitScope_Output, dynOutChans, info.mChanInfo, numInfo)) {
+               if (CheckDynCount (dynOutChans, outputs) == false) return false;
+       }
+
+       if (dynOutChans && dynInChans) { return true; }
+
+// (3) Just need to test one side
+       if (dynInChans || (inputs.mNumEls == 0)) {
+               return CheckOneSide (outputs, true, info.mChanInfo, numInfo);
+       }
+
+       if (dynOutChans || (outputs.mNumEls == 0)) {
+               return CheckOneSide (inputs, false, info.mChanInfo, numInfo);
+       }
+
+// (4) - not a dynamic AU, has ins and outs, and has channel constraints so we test every possible pairing
+       for (unsigned int in = 0; in < inputs.mNumEls; ++in) 
+       {
+               bool testInAlready = false;
+               for (unsigned int i = 0; i < in; ++i) {
+                       if (inputs.mChans[i] == inputs.mChans[in]) {
+                               testInAlready = true;
+                               break;
+                       }
+               }
+               if (!testInAlready) {
+                       for (unsigned int out = 0; out < outputs.mNumEls; ++out) {
+                                       // try to save a little bit and not test the same pairing multiple times...
+                               bool testOutAlready = false;
+                               for (unsigned int i = 0; i < out; ++i) {
+                                       if (outputs.mChans[i] == outputs.mChans[out]) {
+                                               testOutAlready = true;
+                                               break;
+                                       }
+                               }
+                               if (!testOutAlready) {
+                                       if (!ValidateChannelPair (inputs.mChans[in], outputs.mChans[out],info.mChanInfo, numInfo)) {
+                                               return false;
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       return true;
+}
+
+bool           CAAudioUnit::SupportsNumChannels () const
+{
+       // this is the default assumption of an audio effect unit
+       Boolean* isWritable = 0;
+       UInt32  dataSize = 0;
+               // lets see if the unit has any channel restrictions
+       OSStatus result = AudioUnitGetPropertyInfo (AU(),
+                                                                       kAudioUnitProperty_SupportedNumChannels,
+                                                                       kAudioUnitScope_Global, 0,
+                                                                       &dataSize, isWritable); //don't care if this is writable
+               
+               // if this property is NOT implemented an FX unit
+               // is expected to deal with same channel valance in and out
+       if (result) {
+               if (Comp().Desc().IsEffect() || Comp().Desc().IsOffline())
+                       return true;
+       }
+       return result == noErr;
+}
+
+bool           CAAudioUnit::GetChannelLayouts (AudioUnitScope                  inScope,
+                                                                               AudioUnitElement                        inEl,
+                                                                               ChannelTagVector                        &outChannelVector) const
+{
+       if (HasChannelLayouts (inScope, inEl) == false) return false; 
+
+       UInt32 dataSize;
+       OSStatus result = AudioUnitGetPropertyInfo (AU(),
+                                                               kAudioUnitProperty_SupportedChannelLayoutTags,
+                                                               inScope, inEl,
+                                                               &dataSize, NULL);
+
+       if (result == kAudioUnitErr_InvalidProperty) {
+               // if we get here we can do layouts but we've got the speaker config property
+               outChannelVector.erase (outChannelVector.begin(), outChannelVector.end());
+               outChannelVector.push_back (kAudioChannelLayoutTag_Stereo);
+               outChannelVector.push_back (kAudioChannelLayoutTag_StereoHeadphones);
+               outChannelVector.push_back (kAudioChannelLayoutTag_Quadraphonic);
+               outChannelVector.push_back (kAudioChannelLayoutTag_AudioUnit_5_0);
+               return true;
+       }
+
+       if (result) return false;
+       
+       bool canDo = false;
+               // OK lets get our channel layouts and see if the one we want is present
+       AudioChannelLayoutTag* info = (AudioChannelLayoutTag*)malloc (dataSize);
+       result = AudioUnitGetProperty (AU(),
+                                                       kAudioUnitProperty_SupportedChannelLayoutTags,
+                                                       inScope, inEl,
+                                                       info, &dataSize);
+       if (result) goto home;
+       
+       outChannelVector.erase (outChannelVector.begin(), outChannelVector.end());
+       for (unsigned int i = 0; i < (dataSize / sizeof (AudioChannelLayoutTag)); ++i)
+               outChannelVector.push_back (info[i]);
+
+home:
+       free (info);
+       return canDo;
+}
+
+bool           CAAudioUnit::HasChannelLayouts (AudioUnitScope          inScope, 
+                                                                               AudioUnitElement                inEl) const
+{
+       OSStatus result = AudioUnitGetPropertyInfo (AU(),
+                                                                       kAudioUnitProperty_SupportedChannelLayoutTags,
+                                                                       inScope, inEl,
+                                                                       NULL, NULL);
+       return !result;
+}
+
+OSStatus       CAAudioUnit::GetChannelLayout (AudioUnitScope           inScope,
+                                                                               AudioUnitElement                inEl,
+                                                                               CAAudioChannelLayout    &outLayout) const
+{
+       UInt32 size;
+       OSStatus result = AudioUnitGetPropertyInfo (AU(), kAudioUnitProperty_AudioChannelLayout,
+                                                                       inScope, inEl, &size, NULL);
+       if (result) return result;
+       
+       AudioChannelLayout *layout = (AudioChannelLayout*)malloc (size);
+
+       require_noerr (result = AudioUnitGetProperty (AU(), kAudioUnitProperty_AudioChannelLayout,
+                                                                       inScope, inEl, layout, &size), home);
+
+       outLayout = CAAudioChannelLayout (layout);
+       
+home:
+       free (layout);
+       return result;
+}
+
+OSStatus       CAAudioUnit::SetChannelLayout (AudioUnitScope           inScope,
+                                                                       AudioUnitElement                        inEl,
+                                                                       CAAudioChannelLayout            &inLayout)
+{
+       OSStatus result = AudioUnitSetProperty (AU(),
+                                                                       kAudioUnitProperty_AudioChannelLayout,
+                                                                       inScope, inEl,
+                                                                       inLayout, inLayout.Size());
+       return result;
+}
+
+OSStatus       CAAudioUnit::SetChannelLayout (AudioUnitScope                   inScope, 
+                                                                                       AudioUnitElement                inEl,
+                                                                                       AudioChannelLayout              &inLayout,
+                                                                                       UInt32                                  inSize)
+{
+       OSStatus result = AudioUnitSetProperty (AU(),
+                                                                       kAudioUnitProperty_AudioChannelLayout,
+                                                                       inScope, inEl,
+                                                                       &inLayout, inSize);
+       return result;
+}
+
+OSStatus               CAAudioUnit::ClearChannelLayout (AudioUnitScope inScope,
+                                                                                       AudioUnitElement        inEl)
+{
+       return AudioUnitSetProperty (AU(),
+                                                       kAudioUnitProperty_AudioChannelLayout,
+                                                       inScope, inEl, NULL, 0);
+}
+
+OSStatus       CAAudioUnit::GetFormat (AudioUnitScope                          inScope,
+                                                                       AudioUnitElement                        inEl,
+                                                                       AudioStreamBasicDescription     &outFormat) const
+{
+       UInt32 dataSize = sizeof (AudioStreamBasicDescription);
+       return AudioUnitGetProperty (AU(), kAudioUnitProperty_StreamFormat,
+                                                               inScope, inEl, 
+                                                               &outFormat, &dataSize);
+}
+
+OSStatus       CAAudioUnit::SetFormat (AudioUnitScope                                          inScope,
+                                                                       AudioUnitElement                                        inEl,
+                                                                       const AudioStreamBasicDescription       &inFormat)
+{
+       return AudioUnitSetProperty (AU(), kAudioUnitProperty_StreamFormat,
+                                                               inScope, inEl,
+                                                               const_cast<AudioStreamBasicDescription*>(&inFormat), 
+                                                               sizeof (AudioStreamBasicDescription));
+}
+
+OSStatus       CAAudioUnit::GetSampleRate (AudioUnitScope              inScope,
+                                                                               AudioUnitElement        inEl,
+                                                                               Float64                         &outRate) const
+{
+       UInt32 dataSize = sizeof (Float64);
+       return AudioUnitGetProperty (AU(), kAudioUnitProperty_SampleRate,
+                                                               inScope, inEl, 
+                                                               &outRate, &dataSize);
+}
+
+OSStatus       CAAudioUnit::SetSampleRate (AudioUnitScope              inScope,
+                                                                               AudioUnitElement        inEl,
+                                                                               Float64                         inRate)
+{
+       AudioStreamBasicDescription desc;
+       OSStatus result = GetFormat (inScope, inEl, desc);
+       if (result) return result;
+       desc.mSampleRate = inRate;
+       return SetFormat (inScope, inEl, desc);
+}
+
+OSStatus       CAAudioUnit::SetSampleRate (Float64                     inSampleRate)
+{
+       OSStatus result;
+       
+       UInt32 elCount;
+       require_noerr (result = GetElementCount(kAudioUnitScope_Input, elCount), home);
+       if (elCount) {
+               for (unsigned int i = 0; i < elCount; ++i) {
+                       require_noerr (result = SetSampleRate (kAudioUnitScope_Input, i, inSampleRate), home);
+               }
+       }
+
+       require_noerr (result = GetElementCount(kAudioUnitScope_Output, elCount), home);
+       if (elCount) {
+               for (unsigned int i = 0; i < elCount; ++i) {
+                       require_noerr (result = SetSampleRate (kAudioUnitScope_Output, i, inSampleRate), home);
+               }
+       }
+       
+home:
+       return result;
+}
+
+OSStatus       CAAudioUnit::NumberChannels (AudioUnitScope             inScope,
+                                                                               AudioUnitElement        inEl,
+                                                                               UInt32                          &outChans) const
+{
+       AudioStreamBasicDescription desc;
+       OSStatus result = GetFormat (inScope, inEl, desc);
+       if (!result)
+               outChans = desc.mChannelsPerFrame;
+       return result;
+}
+
+OSStatus       CAAudioUnit::SetNumberChannels (AudioUnitScope  inScope,
+                                                                               AudioUnitElement        inEl,
+                                                                               UInt32                          inChans)
+{
+                       // set this as the output of the AU
+       CAStreamBasicDescription desc;
+       OSStatus result = GetFormat (inScope, inEl, desc);
+               if (result) return result;
+       desc.SetCanonical (inChans, desc.IsInterleaved());
+       result = SetFormat (inScope, inEl, desc);
+       return result;
+}
+
+OSStatus               CAAudioUnit::IsElementCountWritable (AudioUnitScope inScope, bool &outWritable) const
+{
+       Boolean isWritable;
+       UInt32 outDataSize;
+       OSStatus result = GetPropertyInfo (kAudioUnitProperty_ElementCount, inScope, 0, &outDataSize, &isWritable);
+       if (result)
+               return result;
+       outWritable = isWritable ? true : false;
+       return noErr;   
+}
+
+OSStatus               CAAudioUnit::GetElementCount (AudioUnitScope inScope, UInt32 &outCount) const
+{
+       UInt32 propSize = sizeof(outCount);
+       return GetProperty (kAudioUnitProperty_ElementCount, inScope, 0, &outCount, &propSize);
+}
+
+OSStatus               CAAudioUnit::SetElementCount (AudioUnitScope inScope, UInt32 inCount)
+{
+       return SetProperty (kAudioUnitProperty_ElementCount, inScope, 0, &inCount, sizeof(inCount));
+}
+
+bool                   CAAudioUnit::HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNumChannels) const
+{
+       // ok - now we need to check the AU's capability here.
+       // this is the default assumption of an audio effect unit
+       Boolean* isWritable = 0;
+       UInt32  dataSize = 0;
+       OSStatus result = GetPropertyInfo (kAudioUnitProperty_SupportedNumChannels,
+                                                               kAudioUnitScope_Global, 0,
+                                                               &dataSize, isWritable); //don't care if this is writable
+               
+               // AU has to explicitly tell us about this.
+       if (result) return false;
+
+       StackAUChannelInfo info (dataSize);
+       
+       result = GetProperty (kAudioUnitProperty_SupportedNumChannels,
+                                                       kAudioUnitScope_Global, 0,
+                                                       info.mChanInfo, &dataSize);
+       if (result) return false;
+
+       return ValidateDynamicScope (inScope, outTotalNumChannels, info.mChanInfo, (dataSize / sizeof(AUChannelInfo)));
+}
+
+// as we've already checked that the element count is writable
+// the following conditions will match this..
+/*
+-1, -2 ->      signifies no restrictions
+-2, -1 ->      signifies no restrictions -> in this case outTotalNumChannels == -1 (any num channels)
+
+-N     (where N is less than -2), signifies the total channel count on the scope side (in or out)
+*/
+bool   CAAudioUnit::ValidateDynamicScope (AudioUnitScope               inScope, 
+                                                                                       SInt32                          &outTotalNumChannels, 
+                                                                                       const AUChannelInfo *info, 
+                                                                                       UInt32                          numInfo) const
+{
+       bool writable = false;
+       OSStatus result = IsElementCountWritable (inScope, writable);
+       if (result || (writable == false))
+               return false;
+
+       //now chan layout can contain -1 for either scope (ie. doesn't care)
+       for (unsigned int i = 0; i < numInfo; ++i)
+       {
+               // lets test the special wild card case first...
+               // this says the AU can do any num channels on input or output - for eg. Matrix Mixer
+               if (((info[i].inChannels == -1) && (info[i].outChannels == -2))
+                       || ((info[i].inChannels == -2) && (info[i].outChannels == -1)))
+               {
+                       outTotalNumChannels = -1;
+                       return true;
+               }
+               
+               // ok lets now test our special case....
+               if (inScope == kAudioUnitScope_Input) {
+                               // isn't dynamic on this side at least
+                       if (info[i].inChannels >= 0)
+                               continue;
+                               
+                       if (info[i].inChannels < -2) {
+                               outTotalNumChannels = abs (info[i].inChannels);
+                               return true;
+                       }
+               } 
+               
+               else if (inScope == kAudioUnitScope_Output) {
+                               // isn't dynamic on this side at least
+                       if (info[i].outChannels >= 0)
+                               continue;
+                               
+                       if (info[i].outChannels < -2) {
+                               outTotalNumChannels = abs (info[i].outChannels);
+                               return true;
+                       }
+               } 
+               
+               else {
+                       break; // wrong scope was specified
+               }
+       }
+       
+       return false;   
+}
+
+OSStatus       CAAudioUnit::ConfigureDynamicScope (AudioUnitScope              inScope, 
+                                                                                       UInt32                                  inNumElements, 
+                                                                                       UInt32                                  *inChannelsPerElement, 
+                                                                                       Float64                                 inSampleRate)
+{
+       SInt32 numChannels = 0;
+       bool isDyamic = HasDynamicScope (inScope, numChannels);
+       if (isDyamic == false)
+               return kAudioUnitErr_InvalidProperty;
+       
+       //lets to a sanity check...
+       // if numChannels == -1, then it can do "any"...
+       if (numChannels > 0) {
+               SInt32 count = 0;
+               for (unsigned int i = 0; i < inNumElements; ++i)
+                       count += inChannelsPerElement[i];
+               if (count > numChannels)
+                       return kAudioUnitErr_InvalidPropertyValue;
+       }
+       
+       OSStatus result = SetElementCount (inScope, inNumElements);
+       if (result)
+               return result;
+               
+       CAStreamBasicDescription desc;
+       desc.mSampleRate = inSampleRate;
+       for (unsigned int i = 0; i < inNumElements; ++i) {
+               desc.SetCanonical (inChannelsPerElement[i], false);
+               result = SetFormat (inScope, i, desc);
+               if (result)
+                       return result;
+       }
+       return noErr;
+}
+
+#pragma mark __Properties
+
+bool           CAAudioUnit::CanBypass () const
+{
+       Boolean outWritable;
+       OSStatus result = AudioUnitGetPropertyInfo (AU(), kAudioUnitProperty_BypassEffect,
+                                                                       kAudioUnitScope_Global, 0,
+                                                                       NULL, &outWritable);
+       return (!result && outWritable);
+}
+
+bool           CAAudioUnit::GetBypass          () const
+{
+       UInt32 dataSize = sizeof (UInt32);
+       UInt32 outBypass;
+       OSStatus result = AudioUnitGetProperty (AU(), kAudioUnitProperty_BypassEffect,
+                                                               kAudioUnitScope_Global, 0,
+                                                               &outBypass, &dataSize);
+       return (result ? false : outBypass);
+}
+
+OSStatus       CAAudioUnit::SetBypass          (bool   inBypass) const
+{      
+       UInt32 bypass = inBypass ? 1 : 0;
+       return AudioUnitSetProperty (AU(), kAudioUnitProperty_BypassEffect,
+                                                               kAudioUnitScope_Global, 0,
+                                                               &bypass, sizeof (UInt32));
+}
+
+Float64                CAAudioUnit::Latency () const
+{
+       Float64 secs;
+       UInt32 size = sizeof(secs);
+       if (GetProperty (kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0, &secs, &size))
+               return 0;
+       return secs;
+}
+
+OSStatus       CAAudioUnit::GetAUPreset (CFPropertyListRef &outData) const
+{
+       UInt32 dataSize = sizeof(outData);
+       return AudioUnitGetProperty (AU(), kAudioUnitProperty_ClassInfo,
+                                                               kAudioUnitScope_Global, 0,
+                                                               &outData, &dataSize);
+}
+
+OSStatus       CAAudioUnit::SetAUPreset (CFPropertyListRef &inData)
+{
+       return AudioUnitSetProperty (AU(), kAudioUnitProperty_ClassInfo,
+                                                               kAudioUnitScope_Global, 0,
+                                                               &inData, sizeof (CFPropertyListRef));
+}
+
+OSStatus       CAAudioUnit::GetPresentPreset (AUPreset &outData) const
+{
+       UInt32 dataSize = sizeof(outData);
+       OSStatus result = AudioUnitGetProperty (AU(), kAudioUnitProperty_PresentPreset,
+                                                               kAudioUnitScope_Global, 0,
+                                                               &outData, &dataSize);
+       if (result == kAudioUnitErr_InvalidProperty) {
+               dataSize = sizeof(outData);
+               result = AudioUnitGetProperty (AU(), kAudioUnitProperty_CurrentPreset,
+                                                                       kAudioUnitScope_Global, 0,
+                                                                       &outData, &dataSize);
+               if (result == noErr) {
+                       // we now retain the CFString in the preset so for the client of this API
+                       // it is consistent (ie. the string should be released when done)
+                       if (outData.presetName)
+                               CFRetain (outData.presetName);
+               }
+       }
+       return result;
+}
+       
+OSStatus       CAAudioUnit::SetPresentPreset (AUPreset &inData)
+{
+       OSStatus result = AudioUnitSetProperty (AU(), kAudioUnitProperty_PresentPreset,
+                                                               kAudioUnitScope_Global, 0,
+                                                               &inData, sizeof (AUPreset));
+       if (result == kAudioUnitErr_InvalidProperty) {
+               result = AudioUnitSetProperty (AU(), kAudioUnitProperty_CurrentPreset,
+                                                               kAudioUnitScope_Global, 0,
+                                                               &inData, sizeof (AUPreset));
+       }
+       return result;
+}
+
+bool           CAAudioUnit::HasCustomView () const
+{
+       UInt32 dataSize = 0;
+       OSStatus result = GetPropertyInfo(kAudioUnitProperty_GetUIComponentList,
+                                        kAudioUnitScope_Global, 0,
+                                        &dataSize, NULL);
+       if (result || !dataSize) {
+               dataSize = 0;
+               result = GetPropertyInfo(kAudioUnitProperty_CocoaUI,
+                                        kAudioUnitScope_Global, 0,
+                                        &dataSize, NULL);
+               if (result || !dataSize)
+                       return false;
+       }
+       return true;
+}
+
+OSStatus               CAAudioUnit::GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+                                                                                       Float32 &outValue) const
+{
+       return mDataPtr ? mDataPtr->GetParameter (inID, scope, element, outValue) : paramErr;
+}
+
+OSStatus               CAAudioUnit::SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+                                                                                       Float32 value, UInt32 bufferOffsetFrames)
+{
+       return mDataPtr ? mDataPtr->SetParameter (inID, scope, element, value, bufferOffsetFrames) : paramErr;
+}
+
+OSStatus               CAAudioUnit::MIDIEvent (UInt32                  inStatus,
+                                                               UInt32                                  inData1,
+                                                               UInt32                                  inData2,
+                                                               UInt32                                  inOffsetSampleFrame)
+{
+       return mDataPtr ? mDataPtr->MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame) : paramErr;
+}
+
+OSStatus       CAAudioUnit::StartNote (MusicDeviceInstrumentID         inInstrument,
+                                                                       MusicDeviceGroupID                      inGroupID,
+                                                                       NoteInstanceID *                        outNoteInstanceID,
+                                                                       UInt32                                          inOffsetSampleFrame,
+                                                                       const MusicDeviceNoteParams * inParams)
+{
+       return mDataPtr ? mDataPtr->StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, inParams) 
+                                       : paramErr;
+}
+
+OSStatus       CAAudioUnit::StopNote (MusicDeviceGroupID               inGroupID,
+                                                                       NoteInstanceID                          inNoteInstanceID,
+                                                                       UInt32                                          inOffsetSampleFrame)
+{
+       return mDataPtr ? mDataPtr->StopNote (inGroupID, inNoteInstanceID, inOffsetSampleFrame) : paramErr;
+}
+
+#pragma mark __Render
+
+OSStatus               CAAudioUnit::Render (AudioUnitRenderActionFlags                         * ioActionFlags,
+                                                                                               const AudioTimeStamp            * inTimeStamp,
+                                                                                               UInt32                                          inOutputBusNumber,
+                                                                                               UInt32                                          inNumberFrames,
+                                                                                               AudioBufferList                         * ioData)
+{
+       return mDataPtr ? mDataPtr->Render (ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData) : paramErr;
+}
+
+static AURenderCallbackStruct sRenderCallback;
+static OSStatus PrerollRenderProc (    void                                            * /*inRefCon*/, 
+                                                               AudioUnitRenderActionFlags              * /*inActionFlags*/,
+                                                               const AudioTimeStamp                    * /*inTimeStamp*/, 
+                                                               UInt32                                                  /*inBusNumber*/,
+                                                               UInt32                                                  /*inNumFrames*/, 
+                                                               AudioBufferList                                 *ioData)
+{
+       AudioBuffer *buf = ioData->mBuffers;
+       for (UInt32 i = ioData->mNumberBuffers; i--; ++buf)
+               memset((Byte *)buf->mData, 0, buf->mDataByteSize);
+
+       return noErr;
+}
+
+OSStatus       CAAudioUnit::Preroll (UInt32 inFrameSize)
+{
+       CAStreamBasicDescription desc;
+       OSStatus result = GetFormat (kAudioUnitScope_Input, 0, desc);
+       bool hasInput = false;
+                       //we have input 
+       if (result == noErr) 
+       {
+               sRenderCallback.inputProc = PrerollRenderProc;
+               sRenderCallback.inputProcRefCon = 0;
+               
+               result = SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 
+                                                               0, &sRenderCallback, sizeof(sRenderCallback));
+               if (result) return result;
+               hasInput = true;
+       }
+       
+       AudioUnitRenderActionFlags flags = 0;
+       AudioTimeStamp time;
+       memset (&time, 0, sizeof(time));
+       time.mFlags = kAudioTimeStampSampleTimeValid;
+
+       CAStreamBasicDescription outputFormat;
+       require_noerr (result = GetFormat (kAudioUnitScope_Output, 0, outputFormat), home);
+       {
+               AUOutputBL list (outputFormat, inFrameSize);
+               list.Prepare ();
+               
+               require_noerr (result = Render (&flags, &time, 0, inFrameSize, list.ABL()), home);
+               require_noerr (result = GlobalReset(), home);
+       }
+
+home:
+       if (hasInput) {
+            // remove our installed callback
+               sRenderCallback.inputProc = 0;
+               sRenderCallback.inputProcRefCon = 0;
+               
+               SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 
+                                                               0, &sRenderCallback, sizeof(sRenderCallback));
+       }
+       return result;
+}
+
+#pragma mark __CAAUChanHelper
+
+CAAUChanHelper::CAAUChanHelper(const CAAudioUnit &inAU, AudioUnitScope inScope)
+       :mChans(NULL), mNumEls(0), mDidAllocate(false)
+{
+       UInt32 elCount;
+       if (inAU.GetElementCount (inScope, elCount)) return;
+       if (elCount > 8) {
+               mChans = new UInt32[elCount];
+               mDidAllocate = true;
+               memset (mChans, 0, sizeof(int) * elCount);
+       } else {
+               mChans = mStaticChans;
+               memset (mChans, 0, sizeof(int) * 8);
+       }
+       for (unsigned int i = 0; i < elCount; ++i) {
+               UInt32 numChans;
+               if (inAU.NumberChannels (inScope, i, numChans)) return;
+               mChans[i] = numChans;
+       }
+       mNumEls = elCount;
+}
+
+CAAUChanHelper::~CAAUChanHelper()
+{
+       if (mDidAllocate) delete [] mChans;
+}
+
+CAAUChanHelper&                CAAUChanHelper::operator= (const CAAUChanHelper &c) 
+{ 
+       if (mDidAllocate) delete [] mChans;
+       if (c.mDidAllocate) {
+               mChans = new UInt32[c.mNumEls];
+               mDidAllocate = true;
+       } else {
+               mDidAllocate = false;
+               mChans = mStaticChans;
+       }
+       memcpy (mChans, c.mChans, c.mNumEls * sizeof(int));
+       
+       return *this; 
+}
+
+#pragma mark __Print Utilities
+
+void           CAAudioUnit::Print (FILE* file) const
+{
+       fprintf (file, "AudioUnit:%p\n", AU());
+       if (IsValid()) { 
+               fprintf (file, "\tnode=%ld\t", (long)GetAUNode()); Comp().Print (file);
+       }
+}
diff --git a/libs/appleutility/CAAudioUnit.h b/libs/appleutility/CAAudioUnit.h
new file mode 100644 (file)
index 0000000..6bc31bf
--- /dev/null
@@ -0,0 +1,383 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CAAudioUnit.h
+=============================================================================*/
+
+#ifndef __CAAudioUnit_h__
+#define __CAAudioUnit_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <CoreServices/CoreServices.h>
+       #include <CoreAudio/CoreAudio.h>
+       #include <AudioUnit/AudioUnit.h>
+       #include <AudioToolbox/AUGraph.h>
+#else
+       #include <ConditionalMacros.h>
+       #include <CoreServices.h>
+       #include <CoreAudioTypes.h>
+       #include <AudioUnit.h>
+       #include <AUGraph.h>
+#endif
+
+#include <vector>
+#include "CAStreamBasicDescription.h"
+#include "CAComponent.h"
+#include "CAAudioChannelLayout.h"
+
+// defined below
+class CAAUChanHelper;
+
+// These constructors will NOT throw exceptions - so "check" after creation if AU IsValid()
+// The destructor will NOT automatically close the AU down
+// This state should be managed by the Caller
+// once closed, the unit represented by this object is no longer valid
+// it is up to the user of this object to ensure its validity is in sync 
+// if it is removed from a graph
+
+// methods that can significantly change the state of the AU (like its format) are
+// NOT const whereas those that don't change the externally related state of the AU are not const
+
+class CAAudioUnit {
+public:
+       typedef std::vector<AudioChannelLayoutTag>      ChannelTagVector;
+       typedef ChannelTagVector::iterator                      ChannelTagVectorIter;
+
+public:
+                                                       CAAudioUnit () 
+                                                               : mDataPtr(0) {}
+
+                                                       CAAudioUnit (const AudioUnit& inUnit);
+
+                                                       CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit);
+
+                                                       CAAudioUnit (const CAAudioUnit& y)
+                                                               : mDataPtr(0) { *this = y; }
+
+       static OSStatus                 Open (const CAComponent& inComp, CAAudioUnit &outUnit);
+
+                                                       ~CAAudioUnit ();
+
+       
+       CAAudioUnit&                    operator= (const CAAudioUnit& y);
+
+       bool                                    operator== (const CAAudioUnit& y) const;
+
+       bool                                    operator== (const AudioUnit& y) const;
+
+#pragma mark __State Management        
+       bool                                    IsValid () const;
+       
+       AudioUnit                               AU() const;
+       operator AudioUnit () const { return AU(); }
+
+       const CAComponent&              Comp() const { return mComp; }
+       
+       bool                                    FromAUGraph () const { return GetAUNode() != 0 || GetAUNode() != -1; }
+       
+       AUNode                                  GetAUNode () const;
+       operator AUNode () const { return GetAUNode(); }
+       
+#pragma mark __API Wrapper
+       OSStatus                                Initialize() const { return AudioUnitInitialize(AU()); }
+       OSStatus                                Uninitialize() const { return AudioUnitUninitialize(AU()); }
+       OSStatus                                GetPropertyInfo(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
+                                                                                       UInt32 *outDataSize, Boolean *outWritable) const
+                                                       {
+                                                               return AudioUnitGetPropertyInfo(AU(), propID, scope, element, outDataSize, outWritable);
+                                                       }
+       OSStatus                                GetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
+                                                                                       void *outData, UInt32 *ioDataSize) const
+                                                       {
+                                                               return AudioUnitGetProperty(AU(), propID, scope, element, outData, ioDataSize);
+                                                       }
+       OSStatus                                SetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
+                                                                                       const void *inData, UInt32 inDataSize)
+                                                       {
+                                                               return AudioUnitSetProperty(AU(), propID, scope, element, inData, inDataSize);
+                                                       }
+       OSStatus                                SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+                                                                                       Float32 value, UInt32 bufferOffsetFrames=0);
+                                                       
+       OSStatus                                GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
+                                                                                       Float32 &outValue) const;
+
+       OSStatus                                Render (AudioUnitRenderActionFlags                              * ioActionFlags,
+                                                                                               const AudioTimeStamp            * inTimeStamp,
+                                                                                               UInt32                                          inOutputBusNumber,
+                                                                                               UInt32                                          inNumberFrames,
+                                                                                               AudioBufferList                         * ioData);
+                                                                                                                       
+       OSStatus                                Reset (AudioUnitScope scope, AudioUnitElement element)
+                                                       {
+                                                               return AudioUnitReset (AU(), scope, element);
+                                                       }
+       OSStatus                                GlobalReset ()
+                                                       {
+                                                               return AudioUnitReset (AU(), kAudioUnitScope_Global, 0);
+                                                       }
+
+       OSStatus                                Preroll (UInt32 inFrameSize);
+
+       OSStatus                                AddRenderNotify (AURenderCallback   inProc, void *inProcRefCon)
+                                                       {
+                                                               return AudioUnitAddRenderNotify (AU(), inProc, inProcRefCon);
+                                                       }
+       
+       OSStatus                                RemoveRenderNotify (AURenderCallback   inProc, void *inProcRefCon)
+                                                       {
+                                                               return AudioUnitRemoveRenderNotify (AU(), inProc, inProcRefCon);
+                                                       }
+       
+
+// Fast dispatch support for MIDI Effects or Music Devices     
+       OSStatus                                MIDIEvent (UInt32                                       inStatus,
+                                                                               UInt32                                  inData1,
+                                                                               UInt32                                  inData2,
+                                                                               UInt32                                  inOffsetSampleFrame);
+                                                               
+                                                               // uses the default VoiceForGroup value - this is the normal case
+       OSStatus                                StartNote (MusicDeviceGroupID           inGroupID,
+                                                                       NoteInstanceID *                        outNoteInstanceID,
+                                                                       UInt32                                          inOffsetSampleFrame,
+                                                                       const MusicDeviceNoteParams * inParams)
+                                                       {
+                                                               return StartNote (kMusicNoteEvent_UseGroupInstrument, 
+                                                                                                       inGroupID, outNoteInstanceID, 
+                                                                                                       inOffsetSampleFrame, inParams);
+                                                       }
+
+       OSStatus                                StartNote (MusicDeviceInstrumentID      inInstrument,
+                                                                       MusicDeviceGroupID                      inGroupID,
+                                                                       NoteInstanceID *                        outNoteInstanceID,
+                                                                       UInt32                                          inOffsetSampleFrame,
+                                                                       const MusicDeviceNoteParams * inParams);
+
+       OSStatus                                StopNote (MusicDeviceGroupID            inGroupID,
+                                                                       NoteInstanceID                          inNoteInstanceID,
+                                                                       UInt32                                          inOffsetSampleFrame);
+
+#pragma mark __Format Utilities
+               // typically you ask this about an AU
+               // These Questions are asking about Input and Output...
+
+               // These ones just say whether an AU can do a single combination of channels
+               // and is fine if the AU has a single output (and if an input, a single input)
+       bool                                    CanDo (int inChannelsInOut) const
+                                                       {
+                                                               return CanDo (inChannelsInOut, inChannelsInOut);
+                                                       }
+                                                       
+       bool                                    CanDo (         int                             inChannelsIn, 
+                                                                               int                             inChannelsOut) const;
+               
+               // This version does a more thorough test for ANY AU with ANY ins/outs
+               // you pass in the channel helper (for the current element count on that scope)
+               
+       bool                                    CanDo (         const CAAUChanHelper            &input,
+                                                                               const CAAUChanHelper            &output) const;
+       
+       bool                                    SupportsNumChannels () const;
+       
+       bool                                    HasChannelLayouts (AudioUnitScope               inScope, 
+                                                                                       AudioUnitElement                inEl) const;
+               
+       bool                                    GetChannelLayouts (AudioUnitScope               inScope,
+                                                                       AudioUnitElement                                inEl,
+                                                                       ChannelTagVector                                &outChannelVector) const;
+       
+       OSStatus                                GetChannelLayout (AudioUnitScope                inScope,
+                                                                                       AudioUnitElement                inEl,
+                                                                                       CAAudioChannelLayout    &outLayout) const;      
+
+       OSStatus                                SetChannelLayout (AudioUnitScope                inScope, 
+                                                                                       AudioUnitElement                inEl,
+                                                                                       CAAudioChannelLayout    &inLayout);
+
+       OSStatus                                SetChannelLayout (AudioUnitScope                inScope, 
+                                                                                       AudioUnitElement                inEl,
+                                                                                       AudioChannelLayout              &inLayout,
+                                                                                       UInt32                                  inSize);
+                                                                                       
+       OSStatus                                ClearChannelLayout (AudioUnitScope              inScope,
+                                                                                       AudioUnitElement                inEl);
+                                                                                               
+       OSStatus                                GetFormat (AudioUnitScope                                       inScope,
+                                                                                       AudioUnitElement                        inEl,
+                                                                                       AudioStreamBasicDescription     &outFormat) const;
+       // if an AudioChannelLayout is either required or set, this call can fail
+       // and the SetChannelLayout call should be used to set the format
+       OSStatus                                SetFormat (AudioUnitScope                                                       inScope,
+                                                                                       AudioUnitElement                                        inEl,
+                                                                                       const AudioStreamBasicDescription       &inFormat);
+
+       OSStatus                                GetSampleRate (AudioUnitScope           inScope,
+                                                                                       AudioUnitElement        inEl,
+                                                                                       Float64                         &outRate) const;
+       OSStatus                                SetSampleRate (AudioUnitScope           inScope,
+                                                                                       AudioUnitElement        inEl,
+                                                                                       Float64                         inRate);
+
+       // this sets the sample rate on all in/out buses of the AU
+       OSStatus                                SetSampleRate (Float64                          inSampleRate);
+       
+       OSStatus                                NumberChannels (AudioUnitScope          inScope,
+                                                                                       AudioUnitElement        inEl,
+                                                                                       UInt32                          &outChans) const;
+
+       OSStatus                                GetNumberChannels (AudioUnitScope       inScope,
+                                                                                       AudioUnitElement        inEl,
+                                                                                       UInt32                          &outChans) const 
+                                                       { 
+                                                               return NumberChannels (inScope, inEl, outChans); 
+                                                       }
+
+       OSStatus                                SetNumberChannels (AudioUnitScope       inScope,
+                                                                                       AudioUnitElement        inEl,
+                                                                                       UInt32                          inChans);
+
+       OSStatus                                IsElementCountWritable (AudioUnitScope inScope, bool &outWritable) const;
+
+       OSStatus                                GetElementCount (AudioUnitScope         inScope, UInt32 &outCount) const;
+
+       OSStatus                                SetElementCount (AudioUnitScope         inScope, UInt32 inCount);
+               
+               // value of -1 for outTotalNumChannels indicates no restriction on num channels
+               // for ex. the Matrix Mixer satisfies this (its in/out element count is writable, and can be set to 
+               // any number of channels.
+               // outTotalNumChannels is only valid if method returns true...
+       bool                                    HasDynamicInputs (SInt32 &outTotalNumChannels) const
+                                                       {
+                                                               return HasDynamicScope (kAudioUnitScope_Input, outTotalNumChannels);
+                                                       }
+                                                       
+       bool                                    HasDynamicOutputs (SInt32 &outTotalNumChannels) const
+                                                       {
+                                                               return HasDynamicScope (kAudioUnitScope_Output, outTotalNumChannels);
+                                                       }
+       
+               // here, if the in (or out) elements are dynamic, then you supply the number of elements
+               // you want on in (or out) scope, and the number of channels on each consecutive element
+       OSStatus                                ConfigureDynamicInput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate)
+                                                       {
+                                                               return ConfigureDynamicScope (kAudioUnitScope_Input, inNumElements, inChannelsPerElement, inSampleRate);
+                                                       }
+                                                       
+       OSStatus                                ConfigureDynamicOutput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate)
+                                                       {
+                                                               return ConfigureDynamicScope (kAudioUnitScope_Output, inNumElements, inChannelsPerElement, inSampleRate);
+                                                       }
+
+       bool                                    CanBypass               () const;
+
+       bool                                    GetBypass               () const;
+
+       OSStatus                                SetBypass               (bool                           inBypass) const;
+       
+       Float64                                 Latency () const;
+       
+               // these calls just deal with the global preset state
+               // you could rescope them to deal with presets on the part scope
+       OSStatus                                GetAUPreset (CFPropertyListRef &outData) const;
+
+       OSStatus                                SetAUPreset (CFPropertyListRef &inData);
+       
+       OSStatus                                GetPresentPreset (AUPreset &outData) const;
+       
+       OSStatus                                SetPresentPreset (AUPreset &inData);
+       
+       bool                                    HasCustomView () const;
+       
+#pragma mark __Print   
+       void                                    Print () const { Print (stdout); }
+       void                                    Print (FILE* file) const;
+       
+private:
+       CAComponent                             mComp;
+       
+       class AUState;
+       AUState*                mDataPtr;
+               
+               // this can throw - so wrap this up in a static that returns a result code...
+       CAAudioUnit (const CAComponent& inComp);
+
+       bool                            HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNumChannels) const;
+       OSStatus                        ConfigureDynamicScope (AudioUnitScope   inScope, 
+                                                                                       UInt32                          inNumElements, 
+                                                                                       UInt32                          *inChannelsPerElement, 
+                                                                                       Float64                         inSampleRate);
+       bool                            ValidateChannelPair (int                                inChannelsIn, 
+                                                                                       int                             inChannelsOut,
+                                                                                       const AUChannelInfo * info,
+                                                                                       UInt32                          numChanInfo) const;
+                                                                                       
+       bool                            ValidateDynamicScope (AudioUnitScope    inScope, 
+                                                                                       SInt32                          &outTotalNumChannels, 
+                                                                                       const AUChannelInfo * info, 
+                                                                                       UInt32 numInfo) const;
+       bool                            CheckOneSide (const CAAUChanHelper              &inHelper, 
+                                                                                       bool                            checkOutput, 
+                                                                                       const AUChannelInfo *info, 
+                                                                                       UInt32                          numInfo) const;
+       
+};
+
+class CAAUChanHelper {
+public:
+                               CAAUChanHelper() 
+                                       : mChans(mStaticChans), mNumEls(0), mDidAllocate(false) 
+                               {
+                                       memset (mChans, 0, sizeof(UInt32) * 8);
+                               }
+                               CAAUChanHelper(const CAAudioUnit &inAU, AudioUnitScope inScope);
+                               CAAUChanHelper (const CAAUChanHelper &c) :mChans(mStaticChans), mNumEls(0), mDidAllocate(false) { *this = c; }
+                               
+                               ~CAAUChanHelper();
+
+       CAAUChanHelper& operator= (const CAAUChanHelper &c);
+
+       UInt32          * mChans;
+       UInt32          mNumEls;
+       
+private:
+       UInt32 mStaticChans[8];
+       bool mDidAllocate;
+};
+
+#endif
diff --git a/libs/appleutility/CACFDictionary.cpp b/libs/appleutility/CACFDictionary.cpp
new file mode 100644 (file)
index 0000000..c209b5f
--- /dev/null
@@ -0,0 +1,478 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CACFDictionary.cpp
+       CAAudioEngine
+
+=============================================================================*/
+
+//=============================================================================
+//     Includes
+//=============================================================================
+
+//     Self Include
+#include "CACFDictionary.h"
+
+//     PublicUtility Includes
+#include "CACFString.h"
+#include "CACFNumber.h"
+
+//=============================================================================
+//     CACFDictionary
+//=============================================================================
+
+bool   CACFDictionary::HasKey(const CFStringRef inKey) const
+{
+       return CFDictionaryContainsKey(mCFDictionary, inKey) != 0;
+}
+
+UInt32 CACFDictionary::Size () const
+{
+       return CFDictionaryGetCount(mCFDictionary);
+}
+
+void   CACFDictionary::GetKeys (const void **keys) const
+{
+       CFDictionaryGetKeysAndValues(mCFDictionary, keys, NULL);
+}
+
+bool   CACFDictionary::GetBool(const CFStringRef inKey, bool& outValue) const
+{
+       bool theAnswer = false;
+       
+       CFTypeRef theValue = NULL;
+       if(GetCFType(inKey, theValue))
+       {
+               if((theValue != NULL) && (CFGetTypeID(theValue) == CFBooleanGetTypeID()))
+               {
+                       outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue));
+                       theAnswer = true;
+               }
+               else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+               {
+                       SInt32 theNumericValue = 0;
+                       CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue);
+                       outValue = theNumericValue != 0;
+                       theAnswer = true;
+               }
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::GetSInt32(const CFStringRef inKey, SInt32& outValue) const
+{
+       bool theAnswer = false;
+       
+       CFTypeRef theValue = NULL;
+       if(GetCFType(inKey, theValue))
+       {
+               if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+               {
+                       CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+                       theAnswer = true;
+               }
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::GetUInt32(const CFStringRef inKey, UInt32& outValue) const
+{
+       bool theAnswer = false;
+       
+       CFTypeRef theValue = NULL;
+       if(GetCFType(inKey, theValue))
+       {
+               if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+               {
+                       CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
+                       theAnswer = true;
+               }
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::GetSInt64(const CFStringRef inKey, SInt64& outValue) const
+{
+       bool theAnswer = false;
+       
+       CFTypeRef theValue = NULL;
+       if(GetCFType(inKey, theValue))
+       {
+               if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+               {
+                       CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+                       theAnswer = true;
+               }
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::GetUInt64(const CFStringRef inKey, UInt64& outValue) const
+{
+       bool theAnswer = false;
+       
+       CFTypeRef theValue = NULL;
+       if(GetCFType(inKey, theValue))
+       {
+               if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+               {
+                       CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
+                       theAnswer = true;
+               }
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::GetFloat32(const CFStringRef inKey, Float32& outValue) const
+{
+       bool theAnswer = false;
+       
+       CFTypeRef theValue = NULL;
+       if(GetCFType(inKey, theValue))
+       {
+               if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+               {
+                       CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat32Type, &outValue);
+                       theAnswer = true;
+               }
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::GetFloat64(const CFStringRef inKey, Float64& outValue) const
+{
+       bool theAnswer = false;
+       
+       CFTypeRef theValue = NULL;
+       if(GetCFType(inKey, theValue))
+       {
+               if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
+               {
+                       CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat64Type, &outValue);
+                       theAnswer = true;
+               }
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::GetString(const CFStringRef inKey, CFStringRef& outValue) const
+{
+       bool theAnswer = false;
+       
+       CFTypeRef theValue = NULL;
+       if(GetCFType(inKey, theValue))
+       {
+               if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
+               {
+                       outValue = static_cast<CFStringRef>(theValue);
+                       theAnswer = true;
+               }
+       }
+       
+       return theAnswer;
+}
+       
+bool   CACFDictionary::GetArray(const CFStringRef inKey, CFArrayRef& outValue) const
+{
+       bool theAnswer = false;
+       
+       CFTypeRef theValue = NULL;
+       if(GetCFType(inKey, theValue))
+       {
+               if((theValue != NULL) && (CFGetTypeID(theValue) == CFArrayGetTypeID()))
+               {
+                       outValue = static_cast<CFArrayRef>(theValue);
+                       theAnswer = true;
+               }
+       }
+       
+       return theAnswer;
+}
+       
+bool   CACFDictionary::GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const
+{
+       bool theAnswer = false;
+       
+       CFTypeRef theValue = NULL;
+       if(GetCFType(inKey, theValue))
+       {
+               if((theValue != NULL) && (CFGetTypeID(theValue) == CFDictionaryGetTypeID()))
+               {
+                       outValue = static_cast<CFDictionaryRef>(theValue);
+                       theAnswer = true;
+               }
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::GetData(const CFStringRef inKey, CFDataRef& outValue) const
+{
+       bool theAnswer = false;
+       
+       CFTypeRef theValue = NULL;
+       if(GetCFType(inKey, theValue))
+       {
+               if((theValue != NULL) && (CFGetTypeID(theValue) == CFDataGetTypeID()))
+               {
+                       outValue = static_cast<CFDataRef>(theValue);
+                       theAnswer = true;
+               }
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::GetCFType(const CFStringRef inKey, CFTypeRef& outValue) const
+{
+       bool theAnswer = false;
+       
+       if(mCFDictionary != NULL)
+       {
+               outValue = CFDictionaryGetValue(mCFDictionary, inKey);
+               theAnswer = (outValue != NULL);
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const
+{
+       bool theAnswer = false;
+       
+       if(mCFDictionary != NULL)
+       {
+               CACFString theKey(inKey);
+               if(theKey.IsValid())
+               {
+                       theAnswer = GetCFType(theKey.GetCFString(), outValue);
+               }
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddSInt32(const CFStringRef inKey, SInt32 inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               CACFNumber theValue(inValue);
+               theAnswer = AddCFType(inKey, theValue.GetCFNumber());
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddUInt32(const CFStringRef inKey, UInt32 inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               CACFNumber theValue(inValue);
+               theAnswer = AddCFType(inKey, theValue.GetCFNumber());
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddSInt64(const CFStringRef inKey, SInt64 inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               CACFNumber theValue(inValue);
+               theAnswer = AddCFType(inKey, theValue.GetCFNumber());
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddUInt64(const CFStringRef inKey, UInt64 inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               CACFNumber theValue(inValue);
+               theAnswer = AddCFType(inKey, theValue.GetCFNumber());
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddFloat32(const CFStringRef inKey, Float32 inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               CACFNumber theValue(inValue);
+               theAnswer = AddCFType(inKey, theValue.GetCFNumber());
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddFloat64(const CFStringRef inKey, Float64 inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               CACFNumber theValue(inValue);
+               theAnswer = AddCFType(inKey, theValue.GetCFNumber());
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddNumber(const CFStringRef inKey, const CFNumberRef inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               theAnswer = AddCFType(inKey, inValue);
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddString(const CFStringRef inKey, const CFStringRef inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               theAnswer = AddCFType(inKey, inValue);
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddArray(const CFStringRef inKey, const CFArrayRef inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               theAnswer = AddCFType(inKey, inValue);
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               theAnswer = AddCFType(inKey, inValue);
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddData(const CFStringRef inKey, const CFDataRef inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               theAnswer = AddCFType(inKey, inValue);
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddCFType(const CFStringRef inKey, const CFTypeRef inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               CFDictionarySetValue(mCFDictionary, inKey, inValue);
+               theAnswer = true;
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               CACFString theKey(inKey);
+               if(theKey.IsValid())
+               {
+                       theAnswer = AddCFType(theKey.GetCFString(), inValue);
+               }
+       }
+       
+       return theAnswer;
+}
+
+bool   CACFDictionary::AddCString(const CFStringRef inKey, const char* inValue)
+{
+       bool theAnswer = false;
+       
+       if(mMutable && (mCFDictionary != NULL))
+       {
+               CACFString theValue(inValue);
+               if(theValue.IsValid())
+               {
+                       theAnswer = AddCFType(inKey, theValue.GetCFString());
+               }
+       }
+       
+       return theAnswer;
+}
diff --git a/libs/appleutility/CACFDictionary.h b/libs/appleutility/CACFDictionary.h
new file mode 100644 (file)
index 0000000..362b1c8
--- /dev/null
@@ -0,0 +1,141 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CACFDictionary.h
+=============================================================================*/
+#if !defined(__CACFDictionary_h__)
+#define __CACFDictionary_h__
+
+//=============================================================================
+//     Includes
+//=============================================================================
+
+//     System Includes
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <CoreFoundation/CoreFoundation.h>
+#else
+       #include <CoreFoundation.h>
+#endif
+
+//=============================================================================
+//     CACFDictionary
+//=============================================================================
+
+class CACFDictionary 
+{
+
+//     Construction/Destruction
+public:
+                                                       CACFDictionary(bool inRelease) : mCFDictionary(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)), mRelease(inRelease), mMutable(true) {}
+                                                       CACFDictionary(const CFDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(const_cast<CFMutableDictionaryRef>(inCFDictionary)), mRelease(inRelease), mMutable(true) {}
+                                                       CACFDictionary(const CFMutableDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(inCFDictionary), mRelease(inRelease), mMutable(true) {}
+                                                       CACFDictionary(const CACFDictionary& inDictionary) : mCFDictionary(inDictionary.mCFDictionary), mRelease(inDictionary.mRelease), mMutable(inDictionary.mMutable) { if(mRelease && (mCFDictionary != NULL)) { CFRetain(mCFDictionary); } }
+       CACFDictionary&                 operator=(const CACFDictionary& inDictionary) { mCFDictionary = inDictionary.mCFDictionary; mRelease = inDictionary.mRelease; mMutable = inDictionary.mMutable; if(mRelease && (mCFDictionary != NULL)) { CFRetain(mCFDictionary); } return *this; } 
+                                                       ~CACFDictionary() { if(mRelease && (mCFDictionary != NULL)) { CFRelease(mCFDictionary); } }
+               
+//     Attributes
+public:
+       bool                                    IsValid() const { return mCFDictionary != NULL; }
+       bool                                    IsMutable() const { return mMutable;}
+       bool                                    CanModify() const { return mMutable && (mCFDictionary != NULL); }
+       
+       bool                                    WillRelease() const { return mRelease; }
+       void                                    ShouldRelease(bool inRelease) { mRelease = inRelease; }
+       
+       CFDictionaryRef                 GetDict() const { return mCFDictionary; }
+       CFDictionaryRef                 GetCFDictionary() const { return mCFDictionary; }
+       CFDictionaryRef                 CopyCFDictionary() const { if(mCFDictionary != NULL) { CFRetain(mCFDictionary); } return mCFDictionary; }
+
+       CFMutableDictionaryRef  GetMutableDict() { return mCFDictionary; }
+       CFMutableDictionaryRef  GetCFMutableDictionary() const { return mCFDictionary; }
+       CFMutableDictionaryRef  CopyCFMutableDictionary() const { if(mCFDictionary != NULL) { CFRetain(mCFDictionary); } return mCFDictionary; }
+       void                                    SetCFMutableDictionaryFromCopy(CFDictionaryRef inDictionary, bool inRelease = true) { if(mRelease && (mCFDictionary != NULL)) { CFRelease(mCFDictionary); } mCFDictionary = CFDictionaryCreateMutableCopy(NULL, 0, inDictionary); mMutable = true; mRelease = inRelease; }
+
+       CFPropertyListRef               AsPropertyList() const { return mCFDictionary; }
+       OSStatus                                GetDictIfMutable(CFMutableDictionaryRef& outDict) const { OSStatus theAnswer = -1; if(mMutable) { outDict = mCFDictionary; theAnswer = 0; } return theAnswer; }
+
+//     Item Operations
+public:
+       bool                                    HasKey(const CFStringRef inKey) const;
+       UInt32                                  Size() const;
+       void                                    GetKeys(const void** keys) const;
+       
+       bool                                    GetBool(const CFStringRef inKey, bool& outValue) const;
+       bool                                    GetSInt32(const CFStringRef inKey, SInt32& outValue) const;
+       bool                                    GetUInt32(const CFStringRef inKey, UInt32& outValue) const;
+       bool                                    GetSInt64(const CFStringRef inKey, SInt64& outValue) const;
+       bool                                    GetUInt64(const CFStringRef inKey, UInt64& outValue) const;
+       bool                                    GetFloat32(const CFStringRef inKey, Float32& outValue) const;
+       bool                                    GetFloat64(const CFStringRef inKey, Float64& outValue) const;
+       bool                                    GetString(const CFStringRef inKey, CFStringRef& outValue) const;        
+       bool                                    GetArray(const CFStringRef inKey, CFArrayRef& outValue) const;  
+       bool                                    GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const;        
+       bool                                    GetData(const CFStringRef inKey, CFDataRef& outValue) const;
+       bool                                    GetCFType(const CFStringRef inKey, CFTypeRef& outValue) const;
+       
+       bool                                    GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const;
+
+       bool                                    AddSInt32(const CFStringRef inKey, SInt32 inValue);
+       bool                                    AddUInt32(const CFStringRef inKey, UInt32 inValue);
+       bool                                    AddSInt64(const CFStringRef inKey, SInt64 inValue);
+       bool                                    AddUInt64(const CFStringRef inKey, UInt64 inValue);
+       bool                                    AddFloat32(const CFStringRef inKey, Float32 inValue);
+       bool                                    AddFloat64(const CFStringRef inKey, Float64 inValue);
+       bool                                    AddNumber(const CFStringRef inKey, const CFNumberRef inValue);
+       bool                                    AddString(const CFStringRef inKey, const CFStringRef inValue);
+       bool                                    AddArray(const CFStringRef inKey, const CFArrayRef inValue);
+       bool                                    AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue);
+       bool                                    AddData(const CFStringRef inKey, const CFDataRef inValue);
+       bool                                    AddCFType(const CFStringRef inKey, const CFTypeRef inValue);
+       
+       bool                                    AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue);
+       bool                                    AddCString(const CFStringRef inKey, const char* inValue);
+
+       void                                    Clear() { if(CanModify()) { CFDictionaryRemoveAllValues(mCFDictionary); } }
+       
+       void                                    Show() { CFShow(mCFDictionary); }
+       
+//     Implementation
+private:
+       CFMutableDictionaryRef  mCFDictionary;
+       bool                                    mRelease;
+       bool                                    mMutable;
+};
+
+#endif //__CACFDictionary_h__
diff --git a/libs/appleutility/CACFNumber.cpp b/libs/appleutility/CACFNumber.cpp
new file mode 100644 (file)
index 0000000..3b6160c
--- /dev/null
@@ -0,0 +1,65 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CACFNumber.cp
+
+=============================================================================*/
+
+//=============================================================================
+//     Includes
+//=============================================================================
+
+#include "CACFNumber.h"
+
+//=============================================================================
+//     CACFNumber
+//=============================================================================
+
+Float32        CACFNumber::GetFixed32() const
+{
+       SInt32 theFixedValue = GetSInt32();
+       
+       //      this is a 16.16 value so convert it to a float
+       Float32 theSign = theFixedValue < 0 ? -1.0 : 1.0;
+       theFixedValue *= (SInt32)theSign;
+       Float32 theWholePart = (theFixedValue & 0x7FFF0000) >> 16;
+       Float32 theFractPart = theFixedValue & 0x0000FFFF;
+       theFractPart /= 65536.0;
+       
+       return theSign * (theWholePart + theFractPart);
+}
diff --git a/libs/appleutility/CACFNumber.h b/libs/appleutility/CACFNumber.h
new file mode 100644 (file)
index 0000000..3991637
--- /dev/null
@@ -0,0 +1,102 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CACFNumber.h
+
+=============================================================================*/
+#if !defined(__CACFNumber_h__)
+#define __CACFNumber_h__
+
+//=============================================================================
+//     Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <CoreAudio/CoreAudioTypes.h>
+       #include <CoreFoundation/CFNumber.h>
+#else
+       #include <CoreAudioTypes.h>
+       #include <CFNumber.h>
+#endif
+
+//=============================================================================
+//     CACFNumber
+//=============================================================================
+
+class  CACFNumber
+{
+//     Construction/Destruction
+public:
+                               CACFNumber(CFNumberRef inCFNumber, bool inWillRelease = true) : mCFNumber(inCFNumber), mWillRelease(inWillRelease) {}
+                               CACFNumber(SInt32 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt32Type, &inValue)), mWillRelease(true) {}
+                               CACFNumber(UInt32 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt32Type, &inValue)), mWillRelease(true) {}
+                               CACFNumber(SInt64 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt64Type, &inValue)), mWillRelease(true) {}
+                               CACFNumber(UInt64 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberSInt64Type, &inValue)), mWillRelease(true) {}
+                               CACFNumber(Float32 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberFloat32Type, &inValue)), mWillRelease(true) {}
+                               CACFNumber(Float64 inValue) : mCFNumber(CFNumberCreate(NULL, kCFNumberFloat64Type, &inValue)), mWillRelease(true) {}
+                               ~CACFNumber() { Release(); }
+                               CACFNumber(const CACFNumber& inNumber) : mCFNumber(inNumber.mCFNumber), mWillRelease(inNumber.mWillRelease) { Retain(); }
+       CACFNumber&     operator=(const CACFNumber& inNumber) { Release(); mCFNumber = inNumber.mCFNumber; mWillRelease = inNumber.mWillRelease; Retain(); return *this; }
+       CACFNumber&     operator=(CFNumberRef inCFNumber) { Release(); mCFNumber = inCFNumber; mWillRelease = true; return *this; }
+
+private:
+       void            Retain() { if(mWillRelease && (mCFNumber != NULL)) { CFRetain(mCFNumber); } }
+       void            Release() { if(mWillRelease && (mCFNumber != NULL)) { CFRelease(mCFNumber); } }
+       
+       CFNumberRef     mCFNumber;
+       bool            mWillRelease;
+
+//     Operations
+public:
+       void            AllowRelease() { mWillRelease = true; }
+       void            DontAllowRelease() { mWillRelease = false; }
+       bool            IsValid() { return mCFNumber != NULL; }
+
+//     Value Access
+public:
+       CFNumberRef     GetCFNumber() const { return mCFNumber; }
+       CFNumberRef     CopyCFNumber() const { if(mCFNumber != NULL) { CFRetain(mCFNumber); } return mCFNumber; }
+
+       SInt8           GetSInt8() const { SInt8 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt8Type, &theAnswer); } return theAnswer; }
+       SInt32          GetSInt32() const { SInt32 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt32Type, &theAnswer); } return theAnswer; }
+       Float32         GetFloat32() const { Float32 theAnswer = 0.0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberFloat32Type, &theAnswer); } return theAnswer; }
+       Float32         GetFixed32() const;
+       SInt64          GetSInt64() const { SInt64 theAnswer = 0; if(mCFNumber != NULL) { CFNumberGetValue(mCFNumber, kCFNumberSInt64Type, &theAnswer); } return theAnswer; }
+};
+
+#endif
diff --git a/libs/appleutility/CACFString.cpp b/libs/appleutility/CACFString.cpp
new file mode 100644 (file)
index 0000000..ec3b18a
--- /dev/null
@@ -0,0 +1,106 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CACFString.cp
+
+=============================================================================*/
+
+//=============================================================================
+//     Includes
+//=============================================================================
+
+#include "CACFString.h"
+
+//=============================================================================
+//     CACFString
+//=============================================================================
+
+UInt32 CACFString::GetStringByteLength(CFStringRef inCFString, CFStringEncoding inEncoding)
+{
+       UInt32 theAnswer = 0;
+       
+       if(inCFString != NULL)
+       {
+               CFRange theRange = { 0, CFStringGetLength(inCFString) };
+               CFStringGetBytes(inCFString, theRange, inEncoding, 0, false, NULL, 0x7FFFFFFF, (CFIndex*)&theAnswer);
+       }
+       
+       return theAnswer;
+}
+
+void   CACFString::GetCString(CFStringRef inCFString, char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding)
+{
+       if(ioStringSize > 0)
+       {
+               if(inCFString != NULL)
+               {
+                       CFIndex theLength = 0;
+                       CFRange theRange = { 0, CFStringGetLength(inCFString) };
+                       CFStringGetBytes(inCFString, theRange, inEncoding, 0, false, (UInt8*)outString, ioStringSize - 1, &theLength);
+                       outString[theLength] = 0;
+                       ioStringSize = theLength + 1;
+               }
+               else
+               {
+                       outString[0] = 0;
+                       ioStringSize = 1;
+               }
+       }
+}
+
+void   CACFString::GetUnicodeString(CFStringRef inCFString, UInt16* outString, UInt32& ioStringSize)
+{
+       if(ioStringSize > 0)
+       {
+               if(inCFString != NULL)
+               {
+                       CFRange theStringRange = { 0, CFStringGetLength(inCFString) };
+                       if(static_cast<UInt32>(theStringRange.length) > ioStringSize)
+                       {
+                               theStringRange.length = ioStringSize;
+                       }
+                       CFStringGetCharacters(inCFString, theStringRange, outString);
+                       ioStringSize = theStringRange.length;
+               }
+               else
+               {
+                       outString[0] = 0;
+                       ioStringSize = 0;
+               }
+       }
+}
diff --git a/libs/appleutility/CACFString.h b/libs/appleutility/CACFString.h
new file mode 100644 (file)
index 0000000..51fa64e
--- /dev/null
@@ -0,0 +1,156 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CACFString.h
+
+=============================================================================*/
+#if !defined(__CACFString_h__)
+#define __CACFString_h__
+
+//=============================================================================
+//     Includes
+//=============================================================================
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <CoreAudio/CoreAudioTypes.h>
+       #include <CoreFoundation/CFString.h>
+#else
+       #include <CoreAudioTypes.h>
+       #include <CFString.h>
+#endif
+
+//=============================================================================
+//     CACFString
+//=============================================================================
+
+class  CACFString
+{
+//     Construction/Destruction
+public:
+                                       CACFString() : mCFString(NULL), mWillRelease(true) {}
+                                       CACFString(CFStringRef inCFString, bool inWillRelease = true) : mCFString(inCFString), mWillRelease(inWillRelease) {}
+                                       CACFString(const char* inCString, bool inWillRelease = true) : mCFString(CFStringCreateWithCString(NULL, inCString, kCFStringEncodingASCII)), mWillRelease(inWillRelease) {}
+                                       CACFString(const char* inCString, CFStringEncoding inCStringEncoding, bool inWillRelease = true) : mCFString(CFStringCreateWithCString(NULL, inCString, inCStringEncoding)), mWillRelease(inWillRelease) {}
+                                       ~CACFString() { Release(); }
+                                       CACFString(const CACFString& inString) : mCFString(inString.mCFString), mWillRelease(inString.mWillRelease) { Retain(); }
+       CACFString&             operator=(const CACFString& inString) { Release(); mCFString = inString.mCFString; mWillRelease = inString.mWillRelease; Retain(); return *this; }
+       CACFString&             operator=(CFStringRef inCFString) { Release(); mCFString = inCFString; mWillRelease = true; return *this; }
+
+private:
+       void                    Retain() { if(mWillRelease && (mCFString != NULL)) { CFRetain(mCFString); } }
+       void                    Release() { if(mWillRelease && (mCFString != NULL)) { CFRelease(mCFString); } }
+       
+       CFStringRef             mCFString;
+       bool                    mWillRelease;
+
+//     Operations
+public:
+       void                    AllowRelease() { mWillRelease = true; }
+       void                    DontAllowRelease() { mWillRelease = false; }
+       bool                    IsValid() const { return mCFString != NULL; }
+       bool                    StartsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFString != NULL) { theAnswer = CFStringHasPrefix(mCFString, inString); } return theAnswer; }
+       bool                    EndsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFString != NULL) { theAnswer = CFStringHasSuffix(mCFString, inString); } return theAnswer; }
+
+//     Value Access
+public:
+       CFStringRef             GetCFString() const { return mCFString; }
+       CFStringRef             CopyCFString() const { if(mCFString != NULL) { CFRetain(mCFString); } return mCFString; }
+       UInt32                  GetLength() const { UInt32 theAnswer = 0; if(mCFString != NULL) { theAnswer = CFStringGetLength(mCFString); } return theAnswer; }
+       UInt32                  GetByteLength(CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { UInt32 theAnswer = 0; if(mCFString != NULL) { theAnswer = GetStringByteLength(mCFString, inEncoding); } return theAnswer; }
+       void                    GetCString(char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { GetCString(mCFString, outString, ioStringSize, inEncoding); }
+       void                    GetUnicodeString(UInt16* outString, UInt32& ioStringSize) const { GetUnicodeString(mCFString, outString, ioStringSize); }
+
+       static UInt32   GetStringByteLength(CFStringRef inCFString, CFStringEncoding inEncoding = kCFStringEncodingUTF8);
+       static void             GetCString(CFStringRef inCFString, char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8);
+       static void             GetUnicodeString(CFStringRef inCFString, UInt16* outString, UInt32& ioStringSize);
+       
+};
+
+inline bool    operator<(const CACFString& x, const CACFString& y) { return CFStringCompare(x.GetCFString(), y.GetCFString(), 0) == kCFCompareLessThan; }
+inline bool    operator==(const CACFString& x, const CACFString& y) { return CFStringCompare(x.GetCFString(), y.GetCFString(), 0) == kCFCompareEqualTo; }
+inline bool    operator!=(const CACFString& x, const CACFString& y) { return !(x == y); }
+inline bool    operator<=(const CACFString& x, const CACFString& y) { return (x < y) || (x == y); }
+inline bool    operator>=(const CACFString& x, const CACFString& y) { return !(x < y); }
+inline bool    operator>(const CACFString& x, const CACFString& y) { return !((x < y) || (x == y)); }
+
+//=============================================================================
+//     CACFMutableString
+//=============================================================================
+
+class  CACFMutableString
+{
+//     Construction/Destruction
+public:
+                                               CACFMutableString() : mCFMutableString(NULL), mWillRelease(true) {}
+                                               CACFMutableString(CFMutableStringRef inCFMutableString, bool inWillRelease = true) : mCFMutableString(inCFMutableString), mWillRelease(inWillRelease) {}
+                                               CACFMutableString(CFStringRef inStringToCopy, bool /*inMakeCopy*/, bool inWillRelease = true) : mCFMutableString(CFStringCreateMutableCopy(NULL, 0, inStringToCopy)), mWillRelease(inWillRelease) {}
+                                               CACFMutableString(const char* inCString, bool inWillRelease = true) : mCFMutableString(NULL), mWillRelease(inWillRelease) { CACFString theString(inCString); mCFMutableString = CFStringCreateMutableCopy(NULL, 0, theString.GetCFString()); }
+                                               CACFMutableString(const char* inCString, CFStringEncoding inCStringEncoding, bool inWillRelease = true) : mCFMutableString(NULL), mWillRelease(inWillRelease) { CACFString theString(inCString, inCStringEncoding); mCFMutableString = CFStringCreateMutableCopy(NULL, 0, theString.GetCFString()); }
+                                               ~CACFMutableString() { Release(); }
+                                               CACFMutableString(const CACFMutableString& inString) : mCFMutableString(inString.mCFMutableString), mWillRelease(inString.mWillRelease) { Retain(); }
+       CACFMutableString       operator=(const CACFMutableString& inString) { Release(); mCFMutableString = inString.mCFMutableString; mWillRelease = inString.mWillRelease; Retain(); return *this; }
+       CACFMutableString       operator=(CFMutableStringRef inCFMutableString) { Release(); mCFMutableString = inCFMutableString; mWillRelease = true; return *this; }
+
+private:
+       void                            Retain() { if(mWillRelease && (mCFMutableString != NULL)) { CFRetain(mCFMutableString); } }
+       void                            Release() { if(mWillRelease && (mCFMutableString != NULL)) { CFRelease(mCFMutableString); } }
+       
+       CFMutableStringRef      mCFMutableString;
+       bool                            mWillRelease;
+
+//     Operations
+public:
+       void                            AllowRelease() { mWillRelease = true; }
+       void                            DontAllowRelease() { mWillRelease = false; }
+       bool                            IsValid() { return mCFMutableString != NULL; }
+       bool                            StartsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFMutableString != NULL) { theAnswer = CFStringHasPrefix(mCFMutableString, inString); } return theAnswer; }
+       bool                            EndsWith(CFStringRef inString) const { bool theAnswer = false; if(mCFMutableString != NULL) { theAnswer = CFStringHasSuffix(mCFMutableString, inString); } return theAnswer; }
+       void                            Append(CFStringRef inString) { if(mCFMutableString != NULL) { CFStringAppend(mCFMutableString, inString); } }
+
+//     Value Access
+public:
+       CFMutableStringRef      GetCFMutableString() const { return mCFMutableString; }
+       CFMutableStringRef      CopyCFMutableString() const { if(mCFMutableString != NULL) { CFRetain(mCFMutableString); } return mCFMutableString; }
+       UInt32                          GetLength() const { UInt32 theAnswer = 0; if(mCFMutableString != NULL) { theAnswer = CFStringGetLength(mCFMutableString); } return theAnswer; }
+       UInt32                          GetByteLength(CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { UInt32 theAnswer = 0; if(mCFMutableString != NULL) { theAnswer = CACFString::GetStringByteLength(mCFMutableString, inEncoding); } return theAnswer; }
+       void                            GetCString(char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8) const { CACFString::GetCString(mCFMutableString, outString, ioStringSize, inEncoding); }
+       void                            GetUnicodeString(UInt16* outString, UInt32& ioStringSize) const { CACFString::GetUnicodeString(mCFMutableString, outString, ioStringSize); }
+
+};
+
+#endif
diff --git a/libs/appleutility/CAComponent.cpp b/libs/appleutility/CAComponent.cpp
new file mode 100644 (file)
index 0000000..700d9e2
--- /dev/null
@@ -0,0 +1,257 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CAComponent.cpp
+=============================================================================*/
+
+#include "CAComponent.h"
+#include "CAComponentDescription.h"
+#include "CACFDictionary.h"
+#include <stdlib.h>
+
+CAComponent::CAComponent (const ComponentDescription& inDesc, CAComponent* next)
+       : mManuName(0), mAUName(0), mCompName(0), mCompInfo (0)
+{
+       mComp = FindNextComponent ((next ? next->Comp() : NULL), const_cast<ComponentDescription*>(&inDesc));
+       if (mComp)
+               GetComponentInfo (Comp(), &mDesc, NULL, NULL, NULL);
+       else
+               memcpy (&mDesc, &inDesc, sizeof(ComponentDescription));
+}
+
+CAComponent::CAComponent (const Component& comp) 
+       : mComp (comp),
+         mManuName(0), 
+         mAUName(0), 
+         mCompName(0), 
+         mCompInfo (0) 
+{
+       GetComponentInfo (Comp(), &mDesc, NULL, NULL, NULL);
+}
+
+CAComponent::CAComponent (const ComponentInstance& compInst) 
+       : mComp (Component(compInst)), 
+         mManuName(0), 
+         mAUName(0), 
+         mCompName(0), 
+         mCompInfo (0) 
+{ 
+       GetComponentInfo (Comp(), &mDesc, NULL, NULL, NULL);
+}
+
+CAComponent::CAComponent (OSType inType, OSType inSubtype, OSType inManu)
+       : mDesc (inType, inSubtype, inManu),
+         mManuName(0), mAUName(0), mCompName(0), mCompInfo (0)
+{
+       mComp = FindNextComponent (NULL, &mDesc);
+       GetComponentInfo (Comp(), &mDesc, NULL, NULL, NULL);
+}
+
+CAComponent::~CAComponent ()
+{
+       Clear();
+}
+
+OSStatus               CAComponent::GetResourceVersion (UInt32 &outVersion) const
+{
+       bool versionFound = false;
+       short componentResFileID = kResFileNotOpened;
+       OSStatus result;
+       short thngResourceCount;
+       
+       short curRes = CurResFile();
+       require_noerr (result = OpenAComponentResFile( mComp, &componentResFileID), home);
+       require_noerr (result = componentResFileID <= 0, home);
+       
+       UseResFile(componentResFileID);
+
+       thngResourceCount = Count1Resources(kComponentResourceType);
+       
+       require_noerr (result = ResError(), home);
+                       // only go on if we successfully found at least 1 thng resource
+       require_noerr (thngResourceCount <= 0 ? -1 : 0, home);
+
+       // loop through all of the Component thng resources trying to 
+       // find one that matches this Component description
+       for (short i = 0; i < thngResourceCount && (!versionFound); i++)
+       {
+               // try to get a handle to this code resource
+               Handle thngResourceHandle = Get1IndResource(kComponentResourceType, i+1);
+               if (thngResourceHandle != NULL && ((*thngResourceHandle) != NULL))
+               {
+                       if (UInt32(GetHandleSize(thngResourceHandle)) >= sizeof(ExtComponentResource))
+                       {
+                               ExtComponentResource * componentThng = (ExtComponentResource*) (*thngResourceHandle);
+
+                               // check to see if this is the thng resource for the particular Component that we are looking at
+                               // (there often is more than one Component described in the resource)
+                               if ((componentThng->cd.componentType == mDesc.Type()) 
+                                               && (componentThng->cd.componentSubType == mDesc.SubType()) 
+                                               && (componentThng->cd.componentManufacturer == mDesc.Manu()))
+                               {
+                                       outVersion = componentThng->componentVersion;
+                                       versionFound = true;
+                               }
+                       }
+                       ReleaseResource(thngResourceHandle);
+               }
+       }
+
+       if (!versionFound)
+               result = resNotFound;
+               
+       UseResFile(curRes);     // revert
+       
+       if ( componentResFileID != kResFileNotOpened )
+               CloseComponentResFile(componentResFileID);
+               
+home:
+       return result;
+}
+
+void                   CAComponent::Clear ()
+{
+       if (mManuName) { CFRelease (mManuName); mManuName = 0; }
+       if (mAUName) { CFRelease (mAUName);  mAUName = 0; }
+       if (mCompName) { CFRelease (mCompName); mCompName = 0; }
+       if (mCompInfo) { CFRelease (mCompInfo); mCompInfo = 0; }
+}
+
+CAComponent&   CAComponent::operator= (const CAComponent& y)
+{
+       Clear();
+
+       mComp = y.mComp;
+       mDesc = y.mDesc;
+
+       if (y.mManuName) { mManuName = y.mManuName; CFRetain (mManuName); }
+       if (y.mAUName) { mAUName = y.mAUName; CFRetain (mAUName); }
+       if (y.mCompName) { mCompName = y.mCompName; CFRetain (mCompName); } 
+       if (y.mCompInfo) { mCompInfo = y.mCompInfo; CFRetain (mCompInfo); }
+
+       return *this;
+}
+
+void           CAComponent::SetCompNames () const
+{
+       if (!mCompName) {
+               Handle h1 = NewHandle(4);
+               CAComponentDescription desc;
+               OSStatus err = GetComponentInfo (Comp(), &desc, h1, 0, 0);
+               
+               if (err) { DisposeHandle(h1); return; }
+               
+               HLock(h1);
+               char* ptr1 = *h1;
+               // Get the manufacturer's name... look for the ':' character convention
+               int len = *ptr1++;
+               char* displayStr = 0;
+
+               const_cast<CAComponent*>(this)->mCompName = CFStringCreateWithPascalString(NULL, (const unsigned char*)*h1, kCFStringEncodingMacRoman);
+                               
+               for (int i = 0; i < len; ++i) {
+                       if (ptr1[i] == ':') { // found the name
+                               ptr1[i] = 0;
+                               displayStr = ptr1;
+                               break;
+                       }
+               }
+               
+               if (displayStr)
+               {
+                       const_cast<CAComponent*>(this)->mManuName = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingMacRoman);
+                                                                               
+                       //move displayStr ptr past the manu, to the name
+                       // we move the characters down a index, because the handle doesn't have any room
+                       // at the end for the \0
+                       int i = strlen(displayStr), j = 0;
+                       while (displayStr[++i] == ' ' && i < len)
+                                       ;
+                       while (i < len)
+                               displayStr[j++] = displayStr[i++];
+                       displayStr[j] = 0;
+
+                       const_cast<CAComponent*>(this)->mAUName = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingMacRoman);
+               } 
+               
+               DisposeHandle (h1);
+       }
+}
+
+void   CAComponent::SetCompInfo () const
+{
+       if (!mCompInfo) {
+               Handle h1 = NewHandle(4);
+               CAComponentDescription desc;
+               OSStatus err = GetComponentInfo (Comp(), &desc, 0, h1, 0);
+               if (err) return;
+               HLock (h1);
+               const_cast<CAComponent*>(this)->mCompInfo = CFStringCreateWithPascalString(NULL, (const unsigned char*)*h1, kCFStringEncodingMacRoman);
+
+               DisposeHandle (h1);
+       }
+}
+
+void   _ShowCF (FILE* file, CFStringRef str)
+{
+       if (CFGetTypeID(str) != CFStringGetTypeID()) {
+               CFShow(str);
+               return;
+       }
+
+       UInt32 len = CFStringGetLength(str);
+       char* chars = (char*)malloc (len * 2); // give us plenty of room for unichar chars
+       if (CFStringGetCString (str, chars, len * 2, kCFStringEncodingUTF8))
+               fprintf (file, "%s", chars);
+       else
+               CFShow (str);
+
+       free (chars);
+}
+
+void   CAComponent::Print(FILE* file) const
+{
+       fprintf (file, "CAComponent: 0x%X", int(Comp()));
+       if (mManuName) {
+               fprintf (file, ", Manu:"); _ShowCF (file, mManuName);
+               if (mAUName) fprintf (file, ", Name:"); _ShowCF (file, mAUName);
+       }
+       fprintf (file, ", "); 
+       Desc ().Print(file);
+}
diff --git a/libs/appleutility/CAComponent.h b/libs/appleutility/CAComponent.h
new file mode 100644 (file)
index 0000000..2ace425
--- /dev/null
@@ -0,0 +1,120 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CAComponent.h
+=============================================================================*/
+
+#ifndef __CAComponent_h__
+#define __CAComponent_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <CoreServices/CoreServices.h>
+#else
+       #include <ConditionalMacros.h>
+       #include <CoreServices.h>
+#endif
+
+#include "CAComponentDescription.h"
+
+class CAComponent 
+{
+public:
+       CAComponent ()
+               : mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0), mCompInfo (0) {}
+               
+               // if next is specifed that is used to find the next component after that one
+       CAComponent (const ComponentDescription& inDesc, CAComponent* next = 0);
+       
+       CAComponent (const CAComponent& y) 
+               : mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0), mCompInfo (0) { *this = y; }
+
+       CAComponent (const Component& comp);
+       
+       CAComponent (const ComponentInstance& compInst);
+
+       CAComponent (OSType inType, OSType inSubtype = 0, OSType inManu = 0);
+       
+       ~CAComponent ();
+       
+       CAComponent&    operator= (const CAComponent& y);
+       
+               // returns true if this object references a valid component
+       bool                    IsValid () const { return Comp() != 0; }
+       
+       bool                    HasAUStrings() const {  SetCompNames (); return mManuName != 0; }
+
+               // CFStringRef should be retained by caller if needed beyond lifetime of this object
+               
+               // Can return NULL if component doesn't follow AU naming conventions
+       CFStringRef             GetAUManu () const { SetCompNames (); return mManuName; }
+       CFStringRef             GetAUName () const { SetCompNames (); return mAUName ? mAUName : mCompName; }
+               
+               // Return value of NULL indicates a problem getting that information from the component
+       CFStringRef             GetCompName () const { SetCompNames(); return mCompName; }
+       CFStringRef             GetCompInfo () const { SetCompInfo(); return mCompInfo; }
+       
+       const CAComponentDescription&   Desc () const { return mDesc; }
+                       
+       OSStatus                Open (ComponentInstance& outInst) const 
+       {
+               return OpenAComponent (Comp(), &outInst);
+       }
+
+       OSStatus                        GetResourceVersion (UInt32 &outVersion) const;
+       
+       const Component&                Comp() const { return mComp; }
+       
+       void                    Print(FILE* file = stdout) const;
+
+       OSStatus                        Save (CFPropertyListRef *outData) const;
+               
+       OSStatus                        Restore (CFPropertyListRef &inData);
+       
+private:
+       Component mComp;
+       CAComponentDescription mDesc;
+       
+       CFStringRef mManuName, mAUName, mCompName, mCompInfo;
+
+       void    SetCompNames () const;
+       void    SetCompInfo () const;
+       void    Clear ();
+};
+
+#endif
diff --git a/libs/appleutility/CAComponentDescription.cpp b/libs/appleutility/CAComponentDescription.cpp
new file mode 100644 (file)
index 0000000..261a2b8
--- /dev/null
@@ -0,0 +1,123 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CAComponentDescription.cpp
+=============================================================================*/
+
+#include "CAComponentDescription.h"
+#include <ctype.h>
+
+extern "C" void CAShowComponentDescription(const ComponentDescription *desc)
+{
+       CAComponentDescription::_CAShowComponentDescription (desc, stdout);
+}
+
+char *StringForOSType (OSType t, char *writeLocation)
+{
+       char *p = writeLocation;
+       unsigned char str[4], *q = str;
+       *(UInt32 *)str = EndianU32_NtoB(t);
+       for (int i = 0; i < 4; ++i) {
+               if (isprint(*q) && *q != '\\')
+                       *p++ = *q++;
+               else {
+                       sprintf(p, "\\x%02X", *q++);
+                       p += 4;
+               }
+       }
+       *p = '\0';
+       return writeLocation;
+}
+
+
+void   CAComponentDescription::_CAShowComponentDescription(const ComponentDescription *desc, FILE* file)
+{
+       if (desc)
+       {
+               char str[24];
+               fprintf (file, "ComponentDescription: %s - ", StringForOSType(desc->componentType, str));
+               fprintf (file, "%s - ", StringForOSType(desc->componentSubType, str));
+               fprintf (file, "%s", StringForOSType(desc->componentManufacturer, str));                
+               fprintf (file, ", 0x%lX, 0x%lX\n", desc->componentFlags, desc->componentFlagsMask);
+       }
+}
+
+CAComponentDescription::CAComponentDescription (OSType inType, OSType inSubtype, OSType inManu)
+{
+       componentType = inType;
+       componentSubType = inSubtype;
+       componentManufacturer = inManu;
+       componentFlags = 0;
+       componentFlagsMask = 0;
+}
+
+bool   CAComponentDescription::IsAU () const 
+{ 
+       bool flag = IsEffect() || IsMusicDevice() || IsOffline();
+       if (flag) return true;
+       
+       switch (componentType) {
+               case kAudioUnitType_Output:
+               case kAudioUnitType_FormatConverter:
+               case kAudioUnitType_Mixer:
+                       return true;
+       }
+       return false;
+}
+
+inline bool _MatchTest (const OSType &inTypeA, const OSType &inTypeB)
+{
+       return ((inTypeA == inTypeB) || (!inTypeA && !inTypeB) || (inTypeA && !inTypeB) || (!inTypeA && inTypeB)); 
+}
+
+bool   CAComponentDescription::Matches (const ComponentDescription &desc) const
+{
+       bool matches = false;
+               
+               // see if the type matches
+       matches = _MatchTest (componentType, desc.componentType);
+       
+       if (matches)
+               matches = _MatchTest (componentSubType, desc.componentSubType);
+       
+       if (matches)
+               matches = _MatchTest (componentManufacturer, desc.componentManufacturer);
+       
+       return matches;
+}
diff --git a/libs/appleutility/CAComponentDescription.h b/libs/appleutility/CAComponentDescription.h
new file mode 100644 (file)
index 0000000..a681902
--- /dev/null
@@ -0,0 +1,148 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CAComponentDescription.h
+       
+=============================================================================*/
+
+#ifndef __CAComponentDescription_h__
+#define __CAComponentDescription_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <CoreServices/CoreServices.h>
+       #include <AudioUnit/AudioUnit.h>
+#else
+       #include <ConditionalMacros.h>
+       #include <CoreServices.h>
+       #include <AudioUnit.h>
+#endif
+
+#include "CACFDictionary.h"
+#include <stdio.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void CAShowComponentDescription(const ComponentDescription *desc);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+// ____________________________________________________________________________
+//
+//     CAComponentDescription
+class CAComponentDescription : public ComponentDescription {
+public:
+       CAComponentDescription() { memset (this, 0, sizeof (ComponentDescription)); }
+       
+       CAComponentDescription (OSType inType, OSType inSubtype = 0, OSType inManu = 0);
+
+       CAComponentDescription(const ComponentDescription& desc) { memcpy (this, &desc, sizeof (ComponentDescription)); }
+               
+       // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+       //
+       // interrogation
+       
+       bool    IsAU () const;
+       
+       bool    IsAUFX() const { return componentType == kAudioUnitType_Effect; }
+       bool    IsAUFM() const { return componentType == kAudioUnitType_MusicEffect; }
+       
+       bool    IsEffect () const { return IsAUFX() || IsAUFM() || IsPanner(); }
+       
+       bool    IsOffline () const { return componentType == 'auol'; }
+       
+       bool    IsFConv () const { return componentType == kAudioUnitType_FormatConverter; }
+       
+       bool    IsPanner () const { return componentType == kAudioUnitType_Panner; }
+       
+       bool    IsMusicDevice () const { return componentType == kAudioUnitType_MusicDevice; }
+       
+#ifndef MAC_OS_X_VERSION_10_4
+       bool    IsGenerator () const { return componentType =='augn'; }
+#else
+       bool    IsGenerator () const { return componentType ==kAudioUnitType_Generator; }
+#endif
+       
+       bool    IsOutput () const { return componentType == kAudioUnitType_Output; }
+       
+       bool    IsSource () const { return IsMusicDevice() || IsGenerator(); }
+       
+       OSType  Type () const { return componentType; }
+       OSType  SubType () const { return componentSubType; }
+       OSType  Manu () const { return componentManufacturer; }
+
+       int             Count() const { return CountComponents(const_cast<CAComponentDescription*>(this)); }
+       
+               // does a semantic match where "wild card" values for type, subtype, manu will match
+       bool    Matches (const ComponentDescription &desc) const;
+       
+       // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+       //
+       //      other
+       
+       void    Print(FILE* file = stdout) const        { _CAShowComponentDescription (this, file); }
+
+       OSStatus                        Save (CFPropertyListRef *outData) const;
+       OSStatus                        Restore (CFPropertyListRef &inData);
+
+private:
+       static void _CAShowComponentDescription (const ComponentDescription *desc, FILE* file);
+       friend void CAShowComponentDescription (const ComponentDescription *desc);
+};
+
+inline bool    operator< (const ComponentDescription& x, const ComponentDescription& y)
+{
+       return memcmp (&x, &y, offsetof (ComponentDescription, componentFlags)) < 0;
+}
+
+inline bool    operator== (const ComponentDescription& x, const ComponentDescription& y)
+{
+       return !memcmp (&x, &y, offsetof (ComponentDescription, componentFlags));
+}
+
+inline bool    operator!= (const ComponentDescription& x, const ComponentDescription& y)
+{
+       return !(x == y);
+}
+
+#endif
diff --git a/libs/appleutility/CAConditionalMacros.h b/libs/appleutility/CAConditionalMacros.h
new file mode 100644 (file)
index 0000000..62f6427
--- /dev/null
@@ -0,0 +1,74 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CAConditionalMacros.h
+
+=============================================================================*/
+#if !defined(__CAConditionalMacros_h__)
+#define __CAConditionalMacros_h__
+
+//=============================================================================
+//     This file exists to make figuring out how to include system headers
+//     easier in a cross platform world. We throw in an include of the standard
+//     ConditionalMacros too.
+//=============================================================================
+
+// ########## THIS FILE SHOULD GO AWAY SOON, replaced by __COREAUDIO_USE_FLAT_INCLUDES__
+// but for now, use this as a way to define __COREAUDIO_USE_FLAT_INCLUDES__ programmatically
+
+//     TargetConditionals.h defines the bare minimum we need
+#include "TargetConditionals.h"
+
+//     Determine whether or not to use framework style includes for system headers
+#if !defined(CoreAudio_Use_Framework_Includes) && !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #if     TARGET_RT_MAC_MACHO
+               #define CoreAudio_Use_Framework_Includes        1
+       #else
+               #define CoreAudio_Use_Framework_Includes        0
+       #endif
+#endif
+
+//     Include the regular ConditionalMacros.h too, since it has useful stuff that
+//     TargetConditionals.h lacks for some reason.
+#if    CoreAudio_Use_Framework_Includes
+       #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/ConditionalMacros.h>
+#else
+       #include "ConditionalMacros.h"
+#endif
+
+#endif
diff --git a/libs/appleutility/CADebugMacros.cpp b/libs/appleutility/CADebugMacros.cpp
new file mode 100644 (file)
index 0000000..edee1f3
--- /dev/null
@@ -0,0 +1,84 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CADebugMacros.cp
+
+=============================================================================*/
+
+#include "CADebugMacros.h"
+#include <stdio.h>
+#include <stdarg.h>
+#if TARGET_API_MAC_OSX
+       #include <syslog.h>
+#endif
+
+#if DEBUG
+#include <stdio.h>
+
+void   DebugPrint(const char *fmt, ...)
+{
+       va_list args;
+       va_start(args, fmt);
+       vprintf(fmt, args);
+       va_end(args);
+}
+#endif // DEBUG
+
+#if TARGET_API_MAC_OSX
+void   LogError(const char *fmt, ...)
+{
+       va_list args;
+       va_start(args, fmt);
+#if DEBUG
+       vprintf(fmt, args);
+#endif
+       vsyslog(LOG_ERR, fmt, args);
+       va_end(args);
+}
+
+void   LogWarning(const char *fmt, ...)
+{
+       va_list args;
+       va_start(args, fmt);
+#if DEBUG
+       vprintf(fmt, args);
+#endif
+       vsyslog(LOG_WARNING, fmt, args);
+       va_end(args);
+}
+#endif
diff --git a/libs/appleutility/CADebugMacros.h b/libs/appleutility/CADebugMacros.h
new file mode 100644 (file)
index 0000000..1abae40
--- /dev/null
@@ -0,0 +1,414 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CADebugMacros.h
+
+=============================================================================*/
+#if !defined(__CADebugMacros_h__)
+#define __CADebugMacros_h__
+
+//=============================================================================
+//     CADebugMacros
+//=============================================================================
+
+//#define      CoreAudio_StopOnFailure                 1
+//#define      CoreAudio_TimeStampMessages             1
+//#define      CoreAudio_ThreadStampMessages   1
+//#define      CoreAudio_FlushDebugMessages    1
+
+#define        CA4CCToCString(the4CC)  { ((char*)&the4CC)[0], ((char*)&the4CC)[1], ((char*)&the4CC)[2], ((char*)&the4CC)[3], 0 }
+
+#pragma mark   Basic Definitions
+
+#if    DEBUG || CoreAudio_Debug
+       
+       // can be used to break into debugger immediately, also see CADebugger
+       #define BusError()              (*(long *)0 = 0)
+       
+       //      basic debugging print routines
+       #if     TARGET_OS_MAC && !TARGET_API_MAC_CARBON
+               extern pascal void DebugStr(const unsigned char* debuggerMsg);
+               #define DebugMessage(msg)       DebugStr("\p"msg)
+               #define DebugMessageN1(msg, N1)
+               #define DebugMessageN2(msg, N1, N2)
+               #define DebugMessageN3(msg, N1, N2, N3)
+       #else
+               #include "CADebugPrintf.h"
+               
+               #if     (CoreAudio_FlushDebugMessages && !CoreAudio_UseSysLog) || defined(CoreAudio_UseSideFile)
+                       #define FlushRtn        ;fflush(DebugPrintfFile)
+               #else
+                       #define FlushRtn
+               #endif
+               
+               #if             CoreAudio_ThreadStampMessages
+                       #include <pthread.h>
+                       #include "CAHostTimeBase.h"
+                       #define DebugMessage(msg)                                                                               DebugPrintfRtn(DebugPrintfFile, "%p %.4f: %s"DebugPrintfLineEnding, pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), msg) FlushRtn
+                       #define DebugMessageN1(msg, N1)                                                                 DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1) FlushRtn
+                       #define DebugMessageN2(msg, N1, N2)                                                             DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2) FlushRtn
+                       #define DebugMessageN3(msg, N1, N2, N3)                                                 DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3) FlushRtn
+                       #define DebugMessageN4(msg, N1, N2, N3, N4)                                             DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4) FlushRtn
+                       #define DebugMessageN5(msg, N1, N2, N3, N4, N5)                                 DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5) FlushRtn
+                       #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6)                             DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6) FlushRtn
+                       #define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7)                 DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7) FlushRtn
+                       #define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8)             DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8) FlushRtn
+                       #define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugPrintfRtn(DebugPrintfFile, "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8, N9) FlushRtn
+               #elif   CoreAudio_TimeStampMessages
+                       #include "CAHostTimeBase.h"
+                       #define DebugMessage(msg)                                                                               DebugPrintfRtn(DebugPrintfFile, "%.4f: %s"DebugPrintfLineEnding, pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), msg) FlushRtn
+                       #define DebugMessageN1(msg, N1)                                                                 DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1) FlushRtn
+                       #define DebugMessageN2(msg, N1, N2)                                                             DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2) FlushRtn
+                       #define DebugMessageN3(msg, N1, N2, N3)                                                 DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3) FlushRtn
+                       #define DebugMessageN4(msg, N1, N2, N3, N4)                                             DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4) FlushRtn
+                       #define DebugMessageN5(msg, N1, N2, N3, N4, N5)                                 DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5) FlushRtn
+                       #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6)                             DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6) FlushRtn
+                       #define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7)                 DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7) FlushRtn
+                       #define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8)             DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8) FlushRtn
+                       #define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugPrintfRtn(DebugPrintfFile, "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8, N9) FlushRtn
+               #else
+                       #define DebugMessage(msg)                                                                               DebugPrintfRtn(DebugPrintfFile, "%s"DebugPrintfLineEnding, msg) FlushRtn
+                       #define DebugMessageN1(msg, N1)                                                                 DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1) FlushRtn
+                       #define DebugMessageN2(msg, N1, N2)                                                             DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2) FlushRtn
+                       #define DebugMessageN3(msg, N1, N2, N3)                                                 DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3) FlushRtn
+                       #define DebugMessageN4(msg, N1, N2, N3, N4)                                             DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4) FlushRtn
+                       #define DebugMessageN5(msg, N1, N2, N3, N4, N5)                                 DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5) FlushRtn
+                       #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6)                             DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6) FlushRtn
+                       #define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7)                 DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7) FlushRtn
+                       #define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8)             DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7, N8) FlushRtn
+                       #define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugPrintfRtn(DebugPrintfFile, msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7, N8, N9) FlushRtn
+               #endif
+       #endif
+       void    DebugPrint(const char *fmt, ...);       // can be used like printf
+       #define DEBUGPRINT(msg) DebugPrint msg          // have to double-parenthesize arglist (see Debugging.h)
+       #if VERBOSE
+               #define vprint(msg) DEBUGPRINT(msg)
+       #else
+               #define vprint(msg)
+       #endif
+       
+       #if     CoreAudio_StopOnFailure
+               #include "CADebugger.h"
+               #define STOP    CADebuggerStop()
+       #else
+               #define STOP
+       #endif
+
+#else
+       #define DebugMessage(msg)
+       #define DebugMessageN1(msg, N1)
+       #define DebugMessageN2(msg, N1, N2)
+       #define DebugMessageN3(msg, N1, N2, N3)
+       #define DebugMessageN4(msg, N1, N2, N3, N4)
+       #define DebugMessageN5(msg, N1, N2, N3, N4, N5)
+       #define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6)
+       #define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7)
+       #define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8)
+       #define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9)
+       #define DEBUGPRINT(msg)
+       #define vprint(msg)
+       #define STOP
+#endif
+
+void   LogError(const char *fmt, ...);                 // writes to syslog (and stderr if debugging)
+void   LogWarning(const char *fmt, ...);               // writes to syslog (and stderr if debugging)
+
+#if    DEBUG || CoreAudio_Debug
+
+#pragma mark   Debug Macros
+
+#define        Assert(inCondition, inMessage)                                                                                                  \
+                       if(!(inCondition))                                                                                                                      \
+                       {                                                                                                                                                       \
+                               DebugMessage(inMessage);                                                                                                \
+                               STOP;                                                                                                                                   \
+                       }
+
+#define        AssertNoError(inError, inMessage)                                                                                               \
+                       {                                                                                                                                                       \
+                               SInt32 __Err = (inError);                                                                                               \
+                               if(__Err != 0)                                                                                                                  \
+                               {                                                                                                                                               \
+                                       char __4CC[5] = CA4CCToCString(__Err);                                                          \
+                                       DebugMessageN2(inMessage ", Error: %ld (%s)", __Err, __4CC);            \
+                                       STOP;                                                                                                                           \
+                               }                                                                                                                                               \
+                       }
+
+#define        AssertNoKernelError(inError, inMessage)                                                                                 \
+                       {                                                                                                                                                       \
+                               unsigned int __Err = (unsigned int)(inError);                                                   \
+                               if(__Err != 0)                                                                                                                  \
+                               {                                                                                                                                               \
+                                       DebugMessageN1(inMessage ", Error: 0x%X", __Err);                                       \
+                                       STOP;                                                                                                                           \
+                               }                                                                                                                                               \
+                       }
+
+#define        FailIf(inCondition, inHandler, inMessage)                                                                               \
+                       if(inCondition)                                                                                                                         \
+                       {                                                                                                                                                       \
+                               DebugMessage(inMessage);                                                                                                \
+                               STOP;                                                                                                                                   \
+                               goto inHandler;                                                                                                                 \
+                       }
+
+#define        FailWithAction(inCondition, inAction, inHandler, inMessage)                                             \
+                       if(inCondition)                                                                                                                         \
+                       {                                                                                                                                                       \
+                               DebugMessage(inMessage);                                                                                                \
+                               STOP;                                                                                                                                   \
+                               { inAction; }                                                                                                                   \
+                               goto inHandler;                                                                                                                 \
+                       }
+
+#define        FailIfNULL(inPointer, inAction, inHandler, inMessage)                                                   \
+                       if((inPointer) == NULL)                                                                                                         \
+                       {                                                                                                                                                       \
+                               DebugMessage(inMessage);                                                                                                \
+                               STOP;                                                                                                                                   \
+                               { inAction; }                                                                                                                   \
+                               goto inHandler;                                                                                                                 \
+                       }
+
+#define        FailIfKernelError(inKernelError, inException, inMessage)                                                \
+                       {                                                                                                                                                       \
+                               kern_return_t __Err = (inKernelError);                                                                  \
+                               if(__Err != 0)                                                                                                                  \
+                               {                                                                                                                                               \
+                                       DebugMessageN1(inMessage ", Error: 0x%X", __Err);                                       \
+                                       STOP;                                                                                                                           \
+                                       { inAction; }                                                                                                           \
+                                       goto inHandler;                                                                                                         \
+                               }                                                                                                                                               \
+                       }
+
+#define        FailIfError(inError, inException, inMessage)                                                                    \
+                       {                                                                                                                                                       \
+                               SInt32 __Err = (inError);                                                                                               \
+                               if(__Err != 0)                                                                                                                  \
+                               {                                                                                                                                               \
+                                       char __4CC[5] = CA4CCToCString(__Err);                                                          \
+                                       DebugMessageN2(inMessage ", Error: %ld (%s)", __Err, __4CC);            \
+                                       STOP;                                                                                                                           \
+                                       { inAction; }                                                                                                           \
+                                       goto inHandler;                                                                                                         \
+                               }                                                                                                                                               \
+                       }
+
+#if defined(__cplusplus)
+
+#define Throw(inException)  STOP; throw (inException)
+
+#define        ThrowIf(inCondition, inException, inMessage)                                                                    \
+                       if(inCondition)                                                                                                                         \
+                       {                                                                                                                                                       \
+                               DebugMessage(inMessage);                                                                                                \
+                               Throw(inException);                                                                                                             \
+                       }
+
+#define        ThrowIfNULL(inPointer, inException, inMessage)                                                                  \
+                       if((inPointer) == NULL)                                                                                                         \
+                       {                                                                                                                                                       \
+                               DebugMessage(inMessage);                                                                                                \
+                               Throw(inException);                                                                                                             \
+                       }
+
+#define        ThrowIfKernelError(inKernelError, inException, inMessage)                                               \
+                       {                                                                                                                                                       \
+                               kern_return_t __Err = (inKernelError);                                                                  \
+                               if(__Err != 0)                                                                                                                  \
+                               {                                                                                                                                               \
+                                       DebugMessageN1(inMessage ", Error: 0x%X", __Err);                                       \
+                                       Throw(inException);                                                                                                     \
+                               }                                                                                                                                               \
+                       }
+
+#define        ThrowIfError(inError, inException, inMessage)                                                                   \
+                       {                                                                                                                                                       \
+                               SInt32 __Err = (inError);                                                                                               \
+                               if(__Err != 0)                                                                                                                  \
+                               {                                                                                                                                               \
+                                       char __4CC[5] = CA4CCToCString(__Err);                                                          \
+                                       DebugMessageN2(inMessage ", Error: %ld (%s)", __Err, __4CC);            \
+                                       Throw(inException);                                                                                                     \
+                               }                                                                                                                                               \
+                       }
+
+#if TARGET_OS_WIN32
+#define        ThrowIfWinError(inError, inException, inMessage)                                                                \
+                       {                                                                                                                                                       \
+                               HRESULT __Err = (inError);                                                                                              \
+                               if(FAILED(__Err))                                                                                                               \
+                               {                                                                                                                                               \
+                                       DebugMessageN1(inMessage ", Error: 0x%X", __Err);                                       \
+                                       Throw(inException);                                                                                                     \
+                               }                                                                                                                                               \
+                       }
+#endif
+
+#define        SubclassResponsibility(inMethodName, inException)                                                               \
+                       {                                                                                                                                                       \
+                               DebugMessage(inMethodName": Subclasses must implement this method");    \
+                               Throw(inException);                                                                                                             \
+                       }
+
+#endif //      defined(__cplusplus)
+
+#else
+
+#pragma mark   Release Macros
+
+#define        Assert(inCondition, inMessage)                                                                                                  \
+                       if(!(inCondition))                                                                                                                      \
+                       {                                                                                                                                                       \
+                               STOP;                                                                                                                                   \
+                       }
+
+#define        AssertNoError(inError, inMessage)                                                                                               \
+                       {                                                                                                                                                       \
+                               SInt32 __Err = (inError);                                                                                               \
+                               if(__Err != 0)                                                                                                                  \
+                               {                                                                                                                                               \
+                                       STOP;                                                                                                                           \
+                               }                                                                                                                                               \
+                       }
+
+#define        AssertNoKernelError(inError, inMessage)                                                                                 \
+                       {                                                                                                                                                       \
+                               unsigned int __Err = (unsigned int)(inError);                                                   \
+                               if(__Err != 0)                                                                                                                  \
+                               {                                                                                                                                               \
+                                       STOP;                                                                                                                           \
+                               }                                                                                                                                               \
+                       }
+
+#define        FailIf(inCondition, inHandler, inMessage)                                                                               \
+                       if(inCondition)                                                                                                                         \
+                       {                                                                                                                                                       \
+                               STOP;                                                                                                                                   \
+                               goto inHandler;                                                                                                                 \
+                       }
+
+#define        FailWithAction(inCondition, inAction, inHandler, inMessage)                                             \
+                       if(inCondition)                                                                                                                         \
+                       {                                                                                                                                                       \
+                               STOP;                                                                                                                                   \
+                               { inAction; }                                                                                                                   \
+                               goto inHandler;                                                                                                                 \
+                       }
+
+#define        FailIfNULL(inPointer, inAction, inHandler, inMessage)                                                   \
+                       if((inPointer) == NULL)                                                                                                         \
+                       {                                                                                                                                                       \
+                               STOP;                                                                                                                                   \
+                               { inAction; }                                                                                                                   \
+                               goto inHandler;                                                                                                                 \
+                       }
+
+#define        FailIfKernelError(inKernelError, inException, inMessage)                                                \
+                       if((inKernelError) != 0)                                                                                                        \
+                       {                                                                                                                                                       \
+                               STOP;                                                                                                                                   \
+                               { inAction; }                                                                                                                   \
+                               goto inHandler;                                                                                                                 \
+                       }
+
+#define        FailIfError(inError, inException, inMessage)                                                                    \
+                       if((inError) != 0)                                                                                                                      \
+                       {                                                                                                                                                       \
+                               STOP;                                                                                                                                   \
+                               { inAction; }                                                                                                                   \
+                               goto inHandler;                                                                                                                 \
+                       }
+
+#if defined(__cplusplus)
+
+#define Throw(inException)  STOP; throw (inException)
+
+#define        ThrowIf(inCondition, inException, inMessage)                                                                    \
+                       if(inCondition)                                                                                                                         \
+                       {                                                                                                                                                       \
+                               Throw(inException);                                                                                                             \
+                       }
+
+#define        ThrowIfNULL(inPointer, inException, inMessage)                                                                  \
+                       if((inPointer) == NULL)                                                                                                         \
+                       {                                                                                                                                                       \
+                               Throw(inException);                                                                                                             \
+                       }
+
+#define        ThrowIfKernelError(inKernelError, inException, inMessage)                                               \
+                       {                                                                                                                                                       \
+                               kern_return_t __Err = (inKernelError);                                                                  \
+                               if(__Err != 0)                                                                                                                  \
+                               {                                                                                                                                               \
+                                       Throw(inException);                                                                                                     \
+                               }                                                                                                                                               \
+                       }
+
+#define        ThrowIfError(inError, inException, inMessage)                                                                   \
+                       {                                                                                                                                                       \
+                               SInt32 __Err = (inError);                                                                                               \
+                               if(__Err != 0)                                                                                                                  \
+                               {                                                                                                                                               \
+                                       Throw(inException);                                                                                                     \
+                               }                                                                                                                                               \
+                       }
+
+#if TARGET_OS_WIN32
+#define        ThrowIfWinError(inError, inException, inMessage)                                                                \
+                       {                                                                                                                                                       \
+                               HRESULT __Err = (inError);                                                                                              \
+                               if(FAILED(__Err))                                                                                                               \
+                               {                                                                                                                                               \
+                                       Throw(inException);                                                                                                     \
+                               }                                                                                                                                               \
+                       }
+#endif
+
+#define        SubclassResponsibility(inMethodName, inException)                                                               \
+                       {                                                                                                                                                       \
+                               Throw(inException);                                                                                                             \
+                       }
+
+#endif //      defined(__cplusplus)
+
+#endif  //  DEBUG || CoreAudio_Debug
+
+#endif
diff --git a/libs/appleutility/CAMath.h b/libs/appleutility/CAMath.h
new file mode 100644 (file)
index 0000000..32b4e7f
--- /dev/null
@@ -0,0 +1,64 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CAMath.h
+       
+=============================================================================*/
+
+#ifndef __CAMath_h__
+#define __CAMath_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <CoreAudio/CoreAudioTypes.h>
+#else
+       #include <CoreAudioTypes.h>
+#endif
+
+inline bool fiszero(Float64 f) { return (f == 0.); }
+inline bool fiszero(Float32 f) { return (f == 0.f); }
+
+inline bool fnonzero(Float64 f) { return !fiszero(f); }
+inline bool fnonzero(Float32 f) { return !fiszero(f); }
+
+inline bool fequal(const Float64 &a, const Float64 &b) { return a == b; }
+inline bool fequal(const Float32 &a, const Float32 &b) { return a == b; }
+
+inline bool fnotequal(const Float64 &a, const Float64 &b) { return !fequal(a, b); }
+inline bool fnotequal(const Float32 &a, const Float32 &b) { return !fequal(a, b); }
+
+#endif // __CAMath_h__
diff --git a/libs/appleutility/CAReferenceCounted.h b/libs/appleutility/CAReferenceCounted.h
new file mode 100644 (file)
index 0000000..d57f97c
--- /dev/null
@@ -0,0 +1,83 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CAReferenceCounted.h
+       
+=============================================================================*/
+
+#ifndef __CAReferenceCounted_h__
+#define __CAReferenceCounted_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <CoreServices/CoreServices.h>
+#else
+       #include <CoreServices.h>
+#endif
+
+#if TARGET_OS_WIN32
+       #include "CAWindows.h"
+#endif
+
+// base class for reference-counted objects
+class CAReferenceCounted {
+public:
+       CAReferenceCounted() : mRefCount(1) {}
+       
+       void    retain() { IncrementAtomic(&mRefCount); }
+       
+       void    release() 
+                       { 
+                                       // this returns the ORIGINAL value, not the new one.
+                               SInt32 rc = DecrementAtomic(&mRefCount);
+                               if (rc == 1) {
+                                       delete this;
+                               }
+                       }
+
+protected:
+    virtual    ~CAReferenceCounted() { }
+       
+private:
+       SInt32          mRefCount;
+
+       CAReferenceCounted(const CAReferenceCounted &a) : mRefCount(0) { }
+       CAReferenceCounted operator=(const CAReferenceCounted &a) { return *this; }
+};
+
+
+#endif // __CAReferenceCounted_h__
diff --git a/libs/appleutility/CAStreamBasicDescription.cpp b/libs/appleutility/CAStreamBasicDescription.cpp
new file mode 100644 (file)
index 0000000..f65bdd9
--- /dev/null
@@ -0,0 +1,520 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CAStreamBasicDescription.cpp
+=============================================================================*/
+
+#include "CAConditionalMacros.h"
+
+#include "CAStreamBasicDescription.h"
+#include "CAMath.h"
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <CoreFoundation/CFByteOrder.h>
+#else
+       #include <CFByteOrder.h>
+#endif
+
+#pragma mark   This file needs to compile on more earlier versions of the OS, so please keep that in mind when editing it
+
+const AudioStreamBasicDescription      CAStreamBasicDescription::sEmpty = { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+CAStreamBasicDescription::CAStreamBasicDescription(double inSampleRate,                UInt32 inFormatID,
+                                                                       UInt32 inBytesPerPacket,        UInt32 inFramesPerPacket,
+                                                                       UInt32 inBytesPerFrame,         UInt32 inChannelsPerFrame,
+                                                                       UInt32 inBitsPerChannel,        UInt32 inFormatFlags)
+{
+       mSampleRate = inSampleRate;
+       mFormatID = inFormatID;
+       mBytesPerPacket = inBytesPerPacket;
+       mFramesPerPacket = inFramesPerPacket;
+       mBytesPerFrame = inBytesPerFrame;
+       mChannelsPerFrame = inChannelsPerFrame;
+       mBitsPerChannel = inBitsPerChannel;
+       mFormatFlags = inFormatFlags;
+}
+
+void CAStreamBasicDescription::PrintFormat(FILE *f, const char *indent, const char *name) const
+{
+       fprintf(f, "%s%s ", indent, name);
+       char formatID[5];
+       *(UInt32 *)formatID = CFSwapInt32HostToBig(mFormatID);
+       formatID[4] = '\0';
+       fprintf(f, "%2ld ch, %6.0f Hz, '%-4.4s' (0x%08lX) ",            
+                               NumberChannels(), mSampleRate, formatID,
+                               mFormatFlags);
+       if (mFormatID == kAudioFormatLinearPCM) {
+               bool isInt = !(mFormatFlags & kLinearPCMFormatFlagIsFloat);
+               int wordSize = SampleWordSize();
+               const char *endian = (wordSize > 1) ? 
+                       ((mFormatFlags & kLinearPCMFormatFlagIsBigEndian) ? " big-endian" : " little-endian" ) : "";
+               const char *sign = isInt ? 
+                       ((mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) ? " signed" : " unsigned") : "";
+               const char *floatInt = isInt ? "integer" : "float";
+               char packed[32];
+               if (wordSize > 0 && PackednessIsSignificant()) {
+                       if (mFormatFlags & kLinearPCMFormatFlagIsPacked)
+                               sprintf(packed, "packed in %d bytes", wordSize);
+                       else
+                               sprintf(packed, "unpacked in %d bytes", wordSize);
+               } else
+                       packed[0] = '\0';
+               const char *align = (wordSize > 0 && AlignmentIsSignificant()) ?
+                       ((mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh) ? " high-aligned" : " low-aligned") : "";
+               const char *deinter = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) ? ", deinterleaved" : "";
+               const char *commaSpace = (packed[0]!='\0') || (align[0]!='\0') ? ", " : "";
+               
+               fprintf(f, "%ld-bit%s%s %s%s%s%s%s\n",
+                       mBitsPerChannel, endian, sign, floatInt, 
+                       commaSpace, packed, align, deinter);
+       } else if (mFormatID == 'alac') {       //      kAudioFormatAppleLossless
+               int sourceBits = 0;
+               switch (mFormatFlags)
+               {
+                       case 1: //      kAppleLosslessFormatFlag_16BitSourceData
+                               sourceBits = 16;
+                               break;
+               case 2: //      kAppleLosslessFormatFlag_20BitSourceData
+                       sourceBits = 20;
+                       break;
+               case 3: //      kAppleLosslessFormatFlag_24BitSourceData
+                       sourceBits = 24;
+                       break;
+               case 4: //      kAppleLosslessFormatFlag_32BitSourceData
+                       sourceBits = 32;
+                       break;
+               }
+               if (sourceBits)
+                       fprintf(f, "from %d-bit source, ", sourceBits);
+               else
+                       fprintf(f, "from UNKNOWN source bit depth, ");
+                       
+               fprintf(f, "%ld frames/packet\n", mFramesPerPacket);
+       }
+       else
+               fprintf(f, "%ld bits/channel, %ld bytes/packet, %ld frames/packet, %ld bytes/frame\n", 
+                       mBitsPerChannel, mBytesPerPacket, mFramesPerPacket, mBytesPerFrame);
+}
+
+void   CAStreamBasicDescription::NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription)
+{
+       //  the only thing that changes is to make mixable linear PCM into the canonical linear PCM format
+       if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
+       {
+               //  the canonical linear PCM format is 32 bit native endian floats
+               ioDescription.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
+               ioDescription.mBytesPerPacket = sizeof(Float32) * ioDescription.mChannelsPerFrame;
+               ioDescription.mFramesPerPacket = 1;
+               ioDescription.mBytesPerFrame = sizeof(Float32) * ioDescription.mChannelsPerFrame;
+               ioDescription.mBitsPerChannel = 8 * sizeof(Float32);
+       }
+}
+
+void   CAStreamBasicDescription::ResetFormat(AudioStreamBasicDescription& ioDescription)
+{
+       ioDescription.mSampleRate = 0;
+       ioDescription.mFormatID = 0;
+       ioDescription.mBytesPerPacket = 0;
+       ioDescription.mFramesPerPacket = 0;
+       ioDescription.mBytesPerFrame = 0;
+       ioDescription.mChannelsPerFrame = 0;
+       ioDescription.mBitsPerChannel = 0;
+       ioDescription.mFormatFlags = 0;
+}
+
+void   CAStreamBasicDescription::FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription)
+{
+       if(fiszero(ioDescription.mSampleRate))
+       {
+               ioDescription.mSampleRate = inTemplateDescription.mSampleRate;
+       }
+       if(ioDescription.mFormatID == 0)
+       {
+               ioDescription.mFormatID = inTemplateDescription.mFormatID;
+       }
+       if(ioDescription.mFormatFlags == 0)
+       {
+               ioDescription.mFormatFlags = inTemplateDescription.mFormatFlags;
+       }
+       if(ioDescription.mBytesPerPacket == 0)
+       {
+               ioDescription.mBytesPerPacket = inTemplateDescription.mBytesPerPacket;
+       }
+       if(ioDescription.mFramesPerPacket == 0)
+       {
+               ioDescription.mFramesPerPacket = inTemplateDescription.mFramesPerPacket;
+       }
+       if(ioDescription.mBytesPerFrame == 0)
+       {
+               ioDescription.mBytesPerFrame = inTemplateDescription.mBytesPerFrame;
+       }
+       if(ioDescription.mChannelsPerFrame == 0)
+       {
+               ioDescription.mChannelsPerFrame = inTemplateDescription.mChannelsPerFrame;
+       }
+       if(ioDescription.mBitsPerChannel == 0)
+       {
+               ioDescription.mBitsPerChannel = inTemplateDescription.mBitsPerChannel;
+       }
+}
+
+void   CAStreamBasicDescription::GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, bool inAbbreviate)
+{
+       switch(inDescription.mFormatID)
+       {
+               case kAudioFormatLinearPCM:
+                       {
+                               const char* theEndianString = NULL;
+                               if((inDescription.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0)
+                               {
+                                       #if     TARGET_RT_LITTLE_ENDIAN
+                                               theEndianString = "Big Endian";
+                                       #endif
+                               }
+                               else
+                               {
+                                       #if     TARGET_RT_BIG_ENDIAN
+                                               theEndianString = "Little Endian";
+                                       #endif
+                               }
+                               
+                               const char* theKindString = NULL;
+                               if((inDescription.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
+                               {
+                                       theKindString = (inAbbreviate ? "Float" : "Floating Point");
+                               }
+                               else if((inDescription.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
+                               {
+                                       theKindString = (inAbbreviate ? "SInt" : "Signed Integer");
+                               }
+                               else
+                               {
+                                       theKindString = (inAbbreviate ? "UInt" : "Unsigned Integer");
+                               }
+                               
+                               const char* thePackingString = NULL;
+                               if((inDescription.mFormatFlags & kAudioFormatFlagIsPacked) == 0)
+                               {
+                                       if((inDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0)
+                                       {
+                                               thePackingString = "High";
+                                       }
+                                       else
+                                       {
+                                               thePackingString = "Low";
+                                       }
+                               }
+                               
+                               const char* theMixabilityString = NULL;
+                               if((inDescription.mFormatFlags & kIsNonMixableFlag) == 0)
+                               {
+                                       theMixabilityString = "Mixable";
+                               }
+                               else
+                               {
+                                       theMixabilityString = "Unmixable";
+                               }
+                               
+                               if(inAbbreviate)
+                               {
+                                       if(theEndianString != NULL)
+                                       {
+                                               if(thePackingString != NULL)
+                                               {
+                                                       sprintf(outName, "%s %d Ch %s %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
+                                               }
+                                               else
+                                               {
+                                                       sprintf(outName, "%s %d Ch %s %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, theKindString, (int)inDescription.mBitsPerChannel);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if(thePackingString != NULL)
+                                               {
+                                                       sprintf(outName, "%s %d Ch %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)((inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8));
+                                               }
+                                               else
+                                               {
+                                                       sprintf(outName, "%s %d Ch %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theKindString, (int)inDescription.mBitsPerChannel);
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       if(theEndianString != NULL)
+                                       {
+                                               if(thePackingString != NULL)
+                                               {
+                                                       sprintf(outName, "%s %d Channel %d Bit %s %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
+                                               }
+                                               else
+                                               {
+                                                       sprintf(outName, "%s %d Channel %d Bit %s %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if(thePackingString != NULL)
+                                               {
+                                                       sprintf(outName, "%s %d Channel %d Bit %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
+                                               }
+                                               else
+                                               {
+                                                       sprintf(outName, "%s %d Channel %d Bit %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString);
+                                               }
+                                       }
+                               }
+                       }
+                       break;
+               
+               case kAudioFormatAC3:
+                       strcpy(outName, "AC-3");
+                       break;
+               
+               case kAudioFormat60958AC3:
+                       strcpy(outName, "AC-3 for SPDIF");
+                       break;
+               
+               default:
+                       {
+                               char* the4CCString = (char*)&inDescription.mFormatID;
+                               outName[0] = the4CCString[0];
+                               outName[1] = the4CCString[1];
+                               outName[2] = the4CCString[2];
+                               outName[3] = the4CCString[3];
+                               outName[4] = 0;
+                       }
+                       break;
+       };
+}
+
+#if CoreAudio_Debug
+#include "CALogMacros.h"
+
+void   CAStreamBasicDescription::PrintToLog(const AudioStreamBasicDescription& inDesc)
+{
+       PrintFloat              ("  Sample Rate:        ", inDesc.mSampleRate);
+       Print4CharCode  ("  Format ID:          ", inDesc.mFormatID);
+       PrintHex                ("  Format Flags:       ", inDesc.mFormatFlags);
+       PrintInt                ("  Bytes per Packet:   ", inDesc.mBytesPerPacket);
+       PrintInt                ("  Frames per Packet:  ", inDesc.mFramesPerPacket);
+       PrintInt                ("  Bytes per Frame:    ", inDesc.mBytesPerFrame);
+       PrintInt                ("  Channels per Frame: ", inDesc.mChannelsPerFrame);
+       PrintInt                ("  Bits per Channel:   ", inDesc.mBitsPerChannel);
+}
+#endif
+
+bool   operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
+{
+       bool theAnswer = false;
+       bool isDone = false;
+       
+       //      note that if either side is 0, that field is skipped
+       
+       //      format ID is the first order sort
+       if((!isDone) && ((x.mFormatID != 0) && (y.mFormatID != 0)))
+       {
+               if(x.mFormatID != y.mFormatID)
+               {
+                       //      formats are sorted numerically except that linear
+                       //      PCM is always first
+                       if(x.mFormatID == kAudioFormatLinearPCM)
+                       {
+                               theAnswer = true;
+                       }
+                       else if(y.mFormatID == kAudioFormatLinearPCM)
+                       {
+                               theAnswer = false;
+                       }
+                       else
+                       {
+                               theAnswer = x.mFormatID < y.mFormatID;
+                       }
+                       isDone = true;
+               }
+       }
+       
+       
+       //  mixable is always better than non-mixable for linear PCM and should be the second order sort item
+       if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
+       {
+               if(((x.mFormatFlags & kIsNonMixableFlag) == 0) && ((y.mFormatFlags & kIsNonMixableFlag) != 0))
+               {
+                       theAnswer = true;
+                       isDone = true;
+               }
+               else if(((x.mFormatFlags & kIsNonMixableFlag) != 0) && ((y.mFormatFlags & kIsNonMixableFlag) == 0))
+               {
+                       theAnswer = false;
+                       isDone = true;
+               }
+       }
+       
+       //      floating point vs integer for linear PCM only
+       if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
+       {
+               if((x.mFormatFlags & kAudioFormatFlagIsFloat) != (y.mFormatFlags & kAudioFormatFlagIsFloat))
+               {
+                       //      floating point is better than integer
+                       theAnswer = y.mFormatFlags & kAudioFormatFlagIsFloat;
+                       isDone = true;
+               }
+       }
+       
+       //      bit depth
+       if((!isDone) && ((x.mBitsPerChannel != 0) && (y.mBitsPerChannel != 0)))
+       {
+               if(x.mBitsPerChannel != y.mBitsPerChannel)
+               {
+                       //      deeper bit depths are higher quality
+                       theAnswer = x.mBitsPerChannel < y.mBitsPerChannel;
+                       isDone = true;
+               }
+       }
+       
+       //      sample rate
+       if((!isDone) && fnonzero(x.mSampleRate) && fnonzero(y.mSampleRate))
+       {
+               if(fnotequal(x.mSampleRate, y.mSampleRate))
+               {
+                       //      higher sample rates are higher quality
+                       theAnswer = x.mSampleRate < y.mSampleRate;
+                       isDone = true;
+               }
+       }
+       
+       //      number of channels
+       if((!isDone) && ((x.mChannelsPerFrame != 0) && (y.mChannelsPerFrame != 0)))
+       {
+               if(x.mChannelsPerFrame != y.mChannelsPerFrame)
+               {
+                       //      more channels is higher quality
+                       theAnswer = x.mChannelsPerFrame < y.mChannelsPerFrame;
+                       isDone = true;
+               }
+       }
+       
+       return theAnswer;
+}
+
+static bool MatchFormatFlags(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
+{
+       UInt32 xFlags = x.mFormatFlags;
+       UInt32 yFlags = y.mFormatFlags;
+       
+       // match wildcards
+       if (x.mFormatID == 0 || y.mFormatID == 0 || xFlags == 0 || yFlags == 0) 
+               return true;
+       
+       if (x.mFormatID == kAudioFormatLinearPCM)
+       {                               
+               // knock off the all clear flag
+               xFlags = xFlags & ~kAudioFormatFlagsAreAllClear;
+               yFlags = yFlags & ~kAudioFormatFlagsAreAllClear;
+       
+               // if both kAudioFormatFlagIsPacked bits are set, then we don't care about the kAudioFormatFlagIsAlignedHigh bit.
+               if (xFlags & yFlags & kAudioFormatFlagIsPacked) {
+                       xFlags = xFlags & ~kAudioFormatFlagIsAlignedHigh;
+                       yFlags = yFlags & ~kAudioFormatFlagIsAlignedHigh;
+               }
+               
+               // if both kAudioFormatFlagIsFloat bits are set, then we don't care about the kAudioFormatFlagIsSignedInteger bit.
+               if (xFlags & yFlags & kAudioFormatFlagIsFloat) {
+                       xFlags = xFlags & ~kAudioFormatFlagIsSignedInteger;
+                       yFlags = yFlags & ~kAudioFormatFlagIsSignedInteger;
+               }
+               
+               //      if the bit depth is 8 bits or less and the format is packed, we don't care about endianness
+               if((x.mBitsPerChannel <= 8) && ((xFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked))
+               {
+                       xFlags = xFlags & ~kAudioFormatFlagIsBigEndian;
+               }
+               if((y.mBitsPerChannel <= 8) && ((yFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked))
+               {
+                       yFlags = yFlags & ~kAudioFormatFlagIsBigEndian;
+               }
+               
+               //      if the number of channels is 0 or 1, we don't care about non-interleavedness
+               if (x.mChannelsPerFrame <= 1 && y.mChannelsPerFrame <= 1) {
+                       xFlags &= ~kLinearPCMFormatFlagIsNonInterleaved;
+                       yFlags &= ~kLinearPCMFormatFlagIsNonInterleaved;
+               }
+       }
+       return xFlags == yFlags;
+}
+
+bool   operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
+{
+       //      the semantics for equality are:
+       //              1) Values must match exactly
+       //              2) wildcard's are ignored in the comparison
+       
+#define MATCH(name) ((x.name) == 0 || (y.name) == 0 || (x.name) == (y.name))
+       
+       return 
+                       //      check the sample rate
+               (fiszero(x.mSampleRate) || fiszero(y.mSampleRate) || fequal(x.mSampleRate, y.mSampleRate))
+               
+                       //      check the format ids
+               && MATCH(mFormatID)
+               
+                       //      check the format flags
+               && MatchFormatFlags(x, y)  
+                       
+                       //      check the bytes per packet
+               && MATCH(mBytesPerPacket) 
+               
+                       //      check the frames per packet
+               && MATCH(mFramesPerPacket) 
+               
+                       //      check the bytes per frame
+               && MATCH(mBytesPerFrame) 
+               
+                       //      check the channels per frame
+               && MATCH(mChannelsPerFrame) 
+               
+                       //      check the channels per frame
+               && MATCH(mBitsPerChannel) ;
+}
+
+bool SanityCheck(const AudioStreamBasicDescription& x)
+{
+       return (x.mSampleRate >= 0.);
+}
diff --git a/libs/appleutility/CAStreamBasicDescription.h b/libs/appleutility/CAStreamBasicDescription.h
new file mode 100644 (file)
index 0000000..aa41c40
--- /dev/null
@@ -0,0 +1,224 @@
+/*     Copyright:      ï¿½ Copyright 2005 Apple Computer, Inc. All rights reserved.
+
+       Disclaimer:     IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+                       ("Apple") in consideration of your agreement to the following terms, and your
+                       use, installation, modification or redistribution of this Apple software
+                       constitutes acceptance of these terms.  If you do not agree with these terms,
+                       please do not use, install, modify or redistribute this Apple software.
+
+                       In consideration of your agreement to abide by the following terms, and subject
+                       to these terms, Apple grants you a personal, non-exclusive license, under Apple�s
+                       copyrights in this original Apple software (the "Apple Software"), to use,
+                       reproduce, modify and redistribute the Apple Software, with or without
+                       modifications, in source and/or binary forms; provided that if you redistribute
+                       the Apple Software in its entirety and without modifications, you must retain
+                       this notice and the following text and disclaimers in all such redistributions of
+                       the Apple Software.  Neither the name, trademarks, service marks or logos of
+                       Apple Computer, Inc. may be used to endorse or promote products derived from the
+                       Apple Software without specific prior written permission from Apple.  Except as
+                       expressly stated in this notice, no other rights or licenses, express or implied,
+                       are granted by Apple herein, including but not limited to any patent rights that
+                       may be infringed by your derivative works or by other works in which the Apple
+                       Software may be incorporated.
+
+                       The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+                       WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+                       WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+                       PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+                       COMBINATION WITH YOUR PRODUCTS.
+
+                       IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+                       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+                       GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+                       ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+                       OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+                       (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+                       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+       CAStreamBasicDescription.h
+       
+=============================================================================*/
+
+#ifndef __CAStreamBasicDescription_h__
+#define __CAStreamBasicDescription_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+       #include <CoreAudio/CoreAudioTypes.h>
+       #include <CoreFoundation/CoreFoundation.h>
+#else
+       #include "CoreAudioTypes.h"
+       #include "CoreFoundation.h"
+#endif
+
+#include "CADebugMacros.h"
+#include <string.h>    // for memset, memcpy
+#include <stdio.h>     // for FILE *
+
+#pragma mark   This file needs to compile on more earlier versions of the OS, so please keep that in mind when editing it
+
+//     define the IsMixable format flag for all versions of the system
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3)
+       enum { kIsNonMixableFlag = kAudioFormatFlagIsNonMixable };
+#else
+       enum { kIsNonMixableFlag = (1L << 6) };
+#endif
+
+//=============================================================================
+//     CAStreamBasicDescription
+//
+//     This is a wrapper class for the AudioStreamBasicDescription struct.
+//     It adds a number of convenience routines, but otherwise adds nothing
+//     to the footprint of the original struct.
+//=============================================================================
+class CAStreamBasicDescription : 
+       public AudioStreamBasicDescription
+{
+
+//     Constants
+public:
+       static const AudioStreamBasicDescription        sEmpty;
+
+//     Construction/Destruction
+public:
+       CAStreamBasicDescription() { memset (this, 0, sizeof(AudioStreamBasicDescription)); }
+       
+       CAStreamBasicDescription(const AudioStreamBasicDescription &desc)
+       {
+               SetFrom(desc);
+       }
+       
+       CAStreamBasicDescription(               double inSampleRate,            UInt32 inFormatID,
+                                                                       UInt32 inBytesPerPacket,        UInt32 inFramesPerPacket,
+                                                                       UInt32 inBytesPerFrame,         UInt32 inChannelsPerFrame,
+                                                                       UInt32 inBitsPerChannel,        UInt32 inFormatFlags);
+
+//     Assignment
+       CAStreamBasicDescription&       operator=(const AudioStreamBasicDescription& v) { SetFrom(v); return *this; }
+
+       void    SetFrom(const AudioStreamBasicDescription &desc)
+       {
+               memcpy(this, &desc, sizeof(AudioStreamBasicDescription));
+       }
+       
+       // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+       //
+       // interrogation
+       
+       bool    IsPCM() const { return mFormatID == kAudioFormatLinearPCM; }
+       
+       bool    PackednessIsSignificant() const
+       {
+               Assert(IsPCM(), "PackednessIsSignificant only applies for PCM");
+               return (SampleWordSize() << 3) != mBitsPerChannel;
+       }
+       
+       bool    AlignmentIsSignificant() const
+       {
+               return PackednessIsSignificant() || (mBitsPerChannel & 7) != 0;
+       }
+       
+       bool    IsInterleaved() const
+       {
+               return !IsPCM() || !(mFormatFlags & kAudioFormatFlagIsNonInterleaved);
+       }
+       
+       // for sanity with interleaved/deinterleaved possibilities, never access mChannelsPerFrame, use these:
+       UInt32  NumberInterleavedChannels() const       { return IsInterleaved() ? mChannelsPerFrame : 1; }     
+       UInt32  NumberChannelStreams() const            { return IsInterleaved() ? 1 : mChannelsPerFrame; }
+       UInt32  NumberChannels() const                          { return mChannelsPerFrame; }
+       UInt32  SampleWordSize() const                          { return (mBytesPerFrame > 0) ? mBytesPerFrame / NumberInterleavedChannels() :  0;}
+
+       UInt32  FramesToBytes(UInt32 nframes) const     { return nframes * mBytesPerFrame; }
+       UInt32  BytesToFrames(UInt32 nbytes) const      {
+               Assert(mBytesPerFrame > 0, "bytesPerFrame must be > 0 in BytesToFrames");
+               return nbytes / mBytesPerFrame;
+       }
+       
+       bool    SameChannelsAndInterleaving(const CAStreamBasicDescription &a) const
+       {
+               return this->NumberChannels() == a.NumberChannels() && this->IsInterleaved() == a.IsInterleaved();
+       }
+       
+       // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+       //
+       //      manipulation
+       
+       void    SetCanonical(UInt32 nChannels, bool interleaved)
+                               // note: leaves sample rate untouched
+       {
+               mFormatID = kAudioFormatLinearPCM;
+               mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
+               mBitsPerChannel = 32;
+               mChannelsPerFrame = nChannels;
+               mFramesPerPacket = 1;
+               if (interleaved)
+                       mBytesPerPacket = mBytesPerFrame = nChannels * sizeof(Float32);
+               else {
+                       mBytesPerPacket = mBytesPerFrame = sizeof(Float32);
+                       mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+               }
+       }
+       
+       void    ChangeNumberChannels(UInt32 nChannels, bool interleaved)
+                               // alter an existing format
+       {
+               Assert(IsPCM(), "ChangeNumberChannels only works for PCM formats");
+               UInt32 wordSize = SampleWordSize();     // get this before changing ANYTHING
+               if (wordSize == 0)
+                       wordSize = (mBitsPerChannel + 7) / 8;
+               mChannelsPerFrame = nChannels;
+               mFramesPerPacket = 1;
+               if (interleaved) {
+                       mBytesPerPacket = mBytesPerFrame = nChannels * wordSize;
+                       mFormatFlags &= ~kAudioFormatFlagIsNonInterleaved;
+               } else {
+                       mBytesPerPacket = mBytesPerFrame = wordSize;
+                       mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
+               }
+       }
+       
+       // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+       //
+       //      other
+       
+       void    Print() const
+       {
+               Print (stdout);
+       }
+
+       void    Print(FILE* file) const
+       {
+               PrintFormat (file, "", "AudioStreamBasicDescription:"); 
+       }
+
+       void PrintFormat(FILE *f, const char *indent, const char *name) const;
+
+       OSStatus                        Save(CFPropertyListRef *outData) const;
+               
+       OSStatus                        Restore(CFPropertyListRef &inData);
+
+//     Operations
+       static bool                     IsMixable(const AudioStreamBasicDescription& inDescription) { return (inDescription.mFormatID == kAudioFormatLinearPCM) && ((inDescription.mFormatFlags & kIsNonMixableFlag) == 0); }
+       static void                     NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription);
+       static void                     ResetFormat(AudioStreamBasicDescription& ioDescription);
+       static void                     FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription);
+       static void                     GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, bool inAbbreviate);
+#if CoreAudio_Debug
+       static void                     PrintToLog(const AudioStreamBasicDescription& inDesc);
+#endif
+};
+
+bool           operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
+bool           operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
+#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600))
+inline bool    operator!=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x == y); }
+inline bool    operator<=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return (x < y) || (x == y); }
+inline bool    operator>=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x < y); }
+inline bool    operator>(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !((x < y) || (x == y)); }
+#endif
+
+bool SanityCheck(const AudioStreamBasicDescription& x);
+
+
+#endif // __CAStreamBasicDescription_h__
diff --git a/libs/appleutility/SConscript b/libs/appleutility/SConscript
new file mode 100644 (file)
index 0000000..2f3280f
--- /dev/null
@@ -0,0 +1,23 @@
+# -*- python -*-
+
+import os
+import os.path
+import glob
+
+appleutility_files = glob.glob('*.cpp') 
+
+Import('env install_prefix')
+appleutility = env.Copy()
+
+appleutility.Append(LINKFLAGS='-framework AudioToolbox')
+appleutility.Append(LINKFLAGS='-framework AudioUnit')
+appleutility.Append(LINKFLAGS='-framework CoreFoundation')
+appleutility.Append(LINKFLAGS='-framework CoreServices')
+
+libappleutility = appleutility.SharedLibrary('appleutility', appleutility_files)
+
+Default(libappleutility)
+
+env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2'), libappleutility))
+
+env.Alias('tarball', env.Distribute (env['DISTTREE'], ['SConscript'] + appleutility_files + glob.glob('*.h') ))
index fc94a13888e773803839b83c364907f5f396f793..feb93ec293352de5194b992610e22b778d118f95 100644 (file)
@@ -83,6 +83,7 @@ send.cc
 session.cc
 session_butler.cc
 session_click.cc
+session_command.cc
 session_events.cc
 session_export.cc
 session_midi.cc
@@ -215,6 +216,9 @@ ardour.Merge ([
 if ardour['LIBLO']:
     ardour.Merge ([ libraries['lo'] ])
 
+if ardour['COREAUDIO']:
+    ardour.Merge ([ libraries['appleutility'] ])
+
 ardour.VersionBuild(['version.cc', 'ardour/version.h'], 'SConscript')
 
 def SharedAsmObjectEmitter(target, source, env):
index ba92416339b30626bb2ea77ffc8acc1529215280..c138cbf32f35e1805c9f87f304207eb72d3f6699 100644 (file)
@@ -45,7 +45,7 @@ namespace ARDOUR {
 
        static const jack_nframes_t max_frames = JACK_MAX_FRAMES;
 
-       int init (AudioEngine&, bool with_vst, bool try_optimization);
+       int init (AudioEngine& engine, bool with_vst, bool try_optimization);
        int cleanup ();
 
        
index ec437109a4885d5269cc02e60219b1d69cab6bfd..1c8d6cbc2dfa6d7d1617d2bca73dbbde10184819 100644 (file)
 #ifndef __ardour_audio_unit_h__
 #define __ardour_audio_unit_h__
 
+#include <stdint.h>
+
 #include <list>
+#include <set>
+#include <string>
+#include <vector>
 
 #include <ardour/plugin.h>
 
 #include <boost/shared_ptr.hpp>
 
-struct ComponentDescription;
+class CAComponent;
+class CAAudioUnit;
+class CAComponentDescription;
+struct AudioBufferList;
 
 namespace ARDOUR {
 
+class AudioEngine;
+class Session;
+
 class AUPlugin : public ARDOUR::Plugin
 {
   public:
-       AUPlugin (AudioEngine& engine, Session& session) : Plugin(engine, session) {};
-       virtual ~AUPlugin () {};
+       AUPlugin (AudioEngine& engine, Session& session, CAComponent* comp);
+       virtual ~AUPlugin ();
+       
+       uint32_t unique_id () const;
+       const char * label () const;
+       const char * name () const { return _info->name.c_str(); }
+       const char * maker () const;
+       uint32_t parameter_count () const;
+       float default_value (uint32_t port);
+       jack_nframes_t latency () const;
+       void set_parameter (uint32_t which, float val);
+       float get_parameter (uint32_t which) const;
+    
+       int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
+       uint32_t nth_parameter (uint32_t which, bool& ok) const;
+       void activate ();
+       void deactivate ();
+       void set_block_size (jack_nframes_t nframes);
+    
+       int connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, jack_nframes_t nframes, jack_nframes_t offset);
+       std::set<uint32_t> automatable() const;
+       void store_state (ARDOUR::PluginState&);
+       void restore_state (ARDOUR::PluginState&);
+       string describe_parameter (uint32_t);
+       string state_node_name () const { return "audiounit"; }
+       void print_parameter (uint32_t, char*, uint32_t len) const;
+    
+       bool parameter_is_audio (uint32_t) const;
+       bool parameter_is_control (uint32_t) const;
+       bool parameter_is_input (uint32_t) const;
+       bool parameter_is_output (uint32_t) const;
+    
+       XMLNode& get_state();
+       int set_state(const XMLNode& node);
+       
+       bool save_preset (string name);
+       bool load_preset (const string preset_label);
+       std::vector<std::string> get_presets ();
+    
+       bool has_editor () const;
+       
+  private:
+       CAComponent* comp;
+    CAAudioUnit* unit;
+
+       AudioBufferList* in_list;
+       AudioBufferList* out_list;
+
+       std::vector<std::pair<uint32_t, uint32_t> > parameter_map;
 };
 
 class AUPluginInfo : public PluginInfo {
-  public:
-       typedef boost::shared_ptr<ComponentDescription> CompDescPtr;
-       
+  public:      
        AUPluginInfo () { };
-       ~AUPluginInfo () { };
+       ~AUPluginInfo ();
 
-       CompDescPtr desc;
+       CAComponentDescription* desc;
 
        static PluginInfoList discover ();
+       PluginPtr load (Session& session);
 
   private:
-       friend class PluginManager;
+       static std::string get_name (CAComponentDescription&);
 };
 
 typedef boost::shared_ptr<AUPluginInfo> AUPluginInfoPtr;
@@ -58,4 +115,3 @@ typedef boost::shared_ptr<AUPluginInfo> AUPluginInfoPtr;
 } // namespace ARDOUR
 
 #endif // __ardour_audio_unit_h__
-
index 78daa531dd0e438992e84bb4b750b352bebb713a..5864de73c668201a761dc9209afa62b5d1ac4815 100644 (file)
@@ -51,7 +51,7 @@ struct ControlEvent {
 
 };
 
-class AutomationList : public StateManager
+class AutomationList : public StateManager, public Stateful
 {
   public:
        typedef std::list<ControlEvent*> AutomationEventList;
@@ -153,6 +153,11 @@ class AutomationList : public StateManager
        virtual void store_state (XMLNode& node) const;
        virtual void load_state (const XMLNode&);
 
+       XMLNode &get_state(void); 
+       int set_state (const XMLNode &s);
+
+        PBD::ID id() { return _id; }
+
        void set_max_xval (double);
        double get_max_xval() const { return max_xval; }
 
@@ -179,6 +184,7 @@ class AutomationList : public StateManager
        };
 
   protected:
+        PBD::ID _id;
        struct State : public ARDOUR::StateManager::State {
            AutomationEventList events;
 
index e4aba93ef67a5b89ce93e26730345e91a6d37ea4..99fc8848984d440823847feb35b3a3fadb54eaff 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2000-2006 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
@@ -137,6 +137,17 @@ class LadspaPlugin : public ARDOUR::Plugin
        void run (jack_nframes_t nsamples);
        void latency_compute_run ();
 };
-}
+
+class LadspaPluginInfo : public PluginInfo {
+  public:      
+       LadspaPluginInfo () { };
+       ~LadspaPluginInfo () { };
+
+       PluginPtr load (Session& session);
+};
+
+typedef boost::shared_ptr<LadspaPluginInfo> LadspaPluginInfoPtr;
+
+} // namespace ARDOUR
 
 #endif /* __ardour_ladspa_plugin_h__ */
index 30c02a80a1eaa0802f7937f9a9af1e0c89cf7083..ff953d1d7895ab8c138776acc1565480900bd0ce 100644 (file)
@@ -119,7 +119,10 @@ class Location : public Stateful, public sigc::trackable
        XMLNode& get_state (void);
        int set_state (const XMLNode&);
 
+        PBD::ID id() { return _id; }
+
   private:
+        PBD::ID _id;
        string        _name;
        jack_nframes_t     _start;
        jack_nframes_t     _end;
@@ -145,6 +148,7 @@ class Locations : public Stateful, public StateManager
 
        XMLNode& get_state (void);
        int set_state (const XMLNode&);
+        PBD::ID id() { return _id; }
 
        Location* auto_loop_location () const;
        Location* auto_punch_location () const;
@@ -197,6 +201,8 @@ class Locations : public Stateful, public StateManager
 
        Change   restore_state (StateManager::State&);
        StateManager::State* state_factory (std::string why) const;
+
+        PBD::ID _id;
 };
 
 } // namespace ARDOUR
index 9fb5b0eb2b5b2baf97a6bb054f51754027695aa9..b389258860bce55ccbd9ae251852d56e0fd1ded4 100644 (file)
@@ -76,6 +76,7 @@ class Playlist : public Stateful, public StateManager {
        EditMode get_edit_mode() const { return _edit_mode; }
        void set_edit_mode (EditMode);
 
+        PBD::ID id() { return _id; }
        /* Editing operations */
 
        void add_region (const Region&, jack_nframes_t position, float times = 1, bool with_save = true);
@@ -273,6 +274,8 @@ class Playlist : public Stateful, public StateManager {
        void unset_freeze_child (Playlist*);
 
        void timestamp_layer_op (Region&);
+
+        PBD::ID _id;
 };
 
 } /* namespace ARDOUR */
index 86666c19af53bcd9c1eea3e5fc22955a06539497..6b11a975ca358993e0f196cdb52dde559aab59ca 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2000-2006 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
@@ -18,8 +18,8 @@
     $Id$
 */
 
-#ifndef __ardour_ladspa_h__
-#define __ardour_ladspa_h__
+#ifndef __ardour_plugin_h__
+#define __ardour_plugin_h__
 
 #include <boost/shared_ptr.hpp>
 #include <sigc++/signal.h>
@@ -46,6 +46,9 @@ namespace ARDOUR {
 class AudioEngine;
 class Session;
 
+class Plugin;
+typedef boost::shared_ptr<Plugin> PluginPtr;
+
 class PluginInfo {
   public:
        enum Type {
@@ -54,11 +57,12 @@ class PluginInfo {
                VST
        };
 
-       PluginInfo () { };
+       PluginInfo () { }
        PluginInfo (const PluginInfo &o)
                : name(o.name), n_inputs(o.n_inputs), n_outputs(o.n_outputs),
                unique_id(o.unique_id), path (o.path), index(o.index) {}
-       ~PluginInfo () { };
+       virtual ~PluginInfo () { }
+       
        string name;
        string category;
        uint32_t n_inputs;
@@ -67,7 +71,9 @@ class PluginInfo {
 
        long unique_id;
 
-  private:
+       virtual PluginPtr load (Session& session) = 0;
+
+  protected:
        friend class PluginManager;
        string path;
        uint32_t index;
@@ -82,7 +88,7 @@ class Plugin : public Stateful, public sigc::trackable
   public:
        Plugin (ARDOUR::AudioEngine&, ARDOUR::Session&);
        Plugin (const Plugin&);
-       ~Plugin ();
+       virtual ~Plugin ();
        
        struct ParameterDescriptor {
 
@@ -143,8 +149,8 @@ class Plugin : public Stateful, public sigc::trackable
        
        PBD::Controllable *get_nth_control (uint32_t);
 
-       PluginInfo & get_info() { return _info; }
-       void set_info (const PluginInfo &inf) { _info = inf; }
+       PluginInfoPtr get_info() { return _info; }
+       void set_info (const PluginInfoPtr inf) { _info = inf; }
 
        ARDOUR::AudioEngine& engine() const { return _engine; }
        ARDOUR::Session& session() const { return _session; }
@@ -155,7 +161,7 @@ class Plugin : public Stateful, public sigc::trackable
   protected:
        ARDOUR::AudioEngine& _engine;
        ARDOUR::Session& _session;
-       PluginInfo _info;
+       PluginInfoPtr _info;
        uint32_t _cycles;
        map<string,string>       presets;
        bool save_preset(string name, string domain /* vst, ladspa etc. */);
@@ -181,9 +187,7 @@ class Plugin : public Stateful, public sigc::trackable
        vector<PortControllable*> controls;
 };
 
-/* this is actually defined in plugin_manager.cc */
-
-boost::shared_ptr<Plugin> find_plugin(ARDOUR::Session&, string name, long unique_id, PluginInfo::Type);
+PluginPtr find_plugin(ARDOUR::Session&, string name, long unique_id, PluginInfo::Type);
 
 } // namespace ARDOUR
  
index 8543ad528570dd1fb1384f5c5ff7b64680e4798d..8e6c0bd1c780ff3d4d1e5b8f822e2b580588d9ef 100644 (file)
@@ -5,42 +5,34 @@
 #include <map>
 #include <string>
 
-#include <boost/shared_ptr.hpp>
-
 #include <ardour/types.h>
 #include <ardour/plugin.h>
 #include <ardour/audio_unit.h>
 
 namespace ARDOUR {
 
-class PluginInfo;
 class Plugin;
 class Session;
 class AudioEngine;
 
 class PluginManager {
   public:
-       PluginManager (ARDOUR::AudioEngine&);
+       PluginManager ();
        ~PluginManager ();
 
        ARDOUR::PluginInfoList &vst_plugin_info () { return _vst_plugin_info; }
        ARDOUR::PluginInfoList &ladspa_plugin_info () { return _ladspa_plugin_info; }
-       ARDOUR::PluginInfoList &au_plugin_info () { return _au_plugin_info; }
 
        void refresh ();
 
        int add_ladspa_directory (std::string dirpath);
        int add_vst_directory (std::string dirpath);
 
-       boost::shared_ptr<Plugin> load (ARDOUR::Session& s, PluginInfoPtr info);
-
        static PluginManager* the_manager() { return _manager; }
 
   private:
-       ARDOUR::AudioEngine&   _engine;
        ARDOUR::PluginInfoList _vst_plugin_info;
        ARDOUR::PluginInfoList _ladspa_plugin_info;
-       ARDOUR::PluginInfoList _au_plugin_info;
        std::map<uint32_t, std::string> rdf_type;
 
        std::string ladspa_path;
@@ -60,8 +52,6 @@ class PluginManager {
        int ladspa_discover_from_path (std::string path);
        int ladspa_discover (std::string path);
 
-       int au_discover ();
-
        std::string get_ladspa_category (uint32_t id);
 
        static PluginManager* _manager; // singleton
index 8271c1cf6ab02b3abe20cd791bb235f73b786c91..d1db818e4004c1d29a755a7b6b1458e0436e235f 100644 (file)
@@ -97,7 +97,7 @@ class Route : public IO
        virtual int  silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
                                  jack_nframes_t offset, bool can_record, bool rec_monitors_input);
        virtual void toggle_monitor_input ();
-       virtual bool can_record() const { return false; }
+       virtual bool can_record() { return false; }
        virtual void set_record_enable (bool yn, void *src) {}
        virtual bool record_enabled() const { return false; }
        virtual void handle_transport_stopped (bool abort, bool did_locate, bool flush_redirects);
index d39807be3f8cfda1eff12b981bf3982cfddf6a6e..6eb025f076385f0201fb4852967795c4e3a894c8 100644 (file)
@@ -489,6 +489,7 @@ class Session : public sigc::trackable, public Stateful
        int save_state (string snapshot_name, bool pending = false);
        int restore_state (string snapshot_name);
        int save_template (string template_name);
+        int save_history ();
 
        static int rename_template (string old_name, string new_name);
 
@@ -501,7 +502,7 @@ class Session : public sigc::trackable, public Stateful
        static vector<string*>* possible_states(string path);
 
        XMLNode& get_state();
-       int      set_state(const XMLNode& node);
+       int      set_state(const XMLNode& node); // not idempotent
        XMLNode& get_template();
 
        void add_instant_xml (XMLNode&, const std::string& dir);
@@ -844,23 +845,65 @@ class Session : public sigc::trackable, public Stateful
        string next_undo() const { return history.next_undo(); }
        string next_redo() const { return history.next_redo(); }
 
-       void begin_reversible_command (string cmd_name, UndoAction *private_undo = 0);
-       void commit_reversible_command (UndoAction* private_redo = 0);
+       void begin_reversible_command (string cmd_name);
+       void commit_reversible_command (Command* cmd = 0);
 
-       void add_undo (const UndoAction& ua) {
-               current_cmd.add_undo (ua);
-       }
-       void add_redo (const UndoAction& ua) {
-               current_cmd.add_redo (ua);
-       }
-       void add_redo_no_execute (const UndoAction& ua) {
-               current_cmd.add_redo_no_execute (ua);
+       void add_command (Command *const cmd) {
+               current_trans.add_command (cmd);
        }
 
-       UndoAction global_solo_memento (void *src);
-       UndoAction global_mute_memento (void *src);
-       UndoAction global_record_enable_memento (void *src);
-       UndoAction global_metering_memento (void *src);
+        // these commands are implemented in libs/ardour/session_command.cc
+        class GlobalSoloStateCommand : public Command
+        {
+            GlobalRouteBooleanState before, after;
+            Session &sess;
+            void *src;
+        public:
+            GlobalSoloStateCommand(Session &, void *src);
+            void operator()();
+            void undo();
+            XMLNode &get_state();
+            void mark();
+        };
+
+        class GlobalMuteStateCommand : public Command
+        {
+            GlobalRouteBooleanState before, after;
+            Session &sess;
+            void *src;
+        public:
+            GlobalMuteStateCommand(Session &, void *src);
+            void operator()();
+            void undo();
+            XMLNode &get_state();
+            void mark();
+        };
+
+        class GlobalRecordEnableStateCommand : public Command
+        {
+            GlobalRouteBooleanState before, after;
+            Session &sess;
+            void *src;
+        public:
+            GlobalRecordEnableStateCommand(Session &, void *src);
+            void operator()();
+            void undo();
+            XMLNode &get_state();
+            void mark();
+        };
+
+        class GlobalMeteringStateCommand : public Command
+        {
+            GlobalRouteMeterState before, after;
+            Session &sess;
+            void *src;
+        public:
+            GlobalMeteringStateCommand(Session &, void *src);
+            void operator()();
+            void undo();
+            XMLNode &get_state();
+            void mark();
+        };
 
        /* edit mode */
 
@@ -1635,7 +1678,7 @@ class Session : public sigc::trackable, public Stateful
        void reverse_diskstream_buffers ();
 
        UndoHistory history;
-       UndoCommand current_cmd;
+       UndoTransaction current_trans;
 
        GlobalRouteBooleanState get_global_route_boolean (bool (Route::*method)(void) const);
        GlobalRouteMeterState get_global_route_metering ();
index 19ee2e624aa2f0edc6065110b5ad1b05a39cf9a8..99bfcfc3ceed22055d93be3a364791deab644db6 100644 (file)
@@ -35,6 +35,8 @@ class StateManager : public sigc::trackable
 
        state_id_t _current_state_id;
 
+       virtual bool should_save_state () const { return true; }
+
        static void prohibit_save ();
        static void allow_save (const char* why, bool dosave);
 
index db0689460728a34670d324122f2b421fc7e94906..bfd3e429c30d12069db4d2bac41b94440c9d5b5f 100644 (file)
@@ -238,6 +238,7 @@ class TempoMap : public Stateful, public StateManager {
 
        XMLNode& get_state (void);
        int set_state (const XMLNode&);
+        PBD::ID id() { return _id; }
 
        void dump (std::ostream&) const;
        void clear ();
@@ -315,6 +316,8 @@ class TempoMap : public Stateful, public StateManager {
 
        void save_state (std::string why);
 
+        PBD::ID _id;
+
 };
 
 }; /* namespace ARDOUR */
index f16e9d29d93ce4a7d0a18daa459d0bf8e831ba98..4e2af5c80eb9b1b035b357d03c51a701832f9933 100644 (file)
@@ -48,7 +48,7 @@ class Track : public Route
 
        void toggle_monitor_input ();
 
-       bool can_record() const { return true; }
+       virtual bool can_record();
 
        Diskstream& diskstream() const { return *_diskstream; }
 
index 3cb10d1779b55a98331ee88ed9afc57d5ce52c3b..5253da7b0a0ad6ca2113327d5f959af6cf70f073 100644 (file)
@@ -104,6 +104,15 @@ class VSTPlugin : public ARDOUR::Plugin
        bool        been_resumed;
 };
 
-}
+class VSTPluginInfo : public PluginInfo
+{
+  public:
+       VSTPluginInfo () {}
+       ~VSTPluginInfo () {}
+       
+       PluginPtr load (Session& session);
+};
+
+} // namespace ARDOUR
 
 #endif /* __ardour_vst_plugin_h__ */
index 7f0cb55821f591f2fa05f37e5e10b2058a1c9ccc..7d2a2103bb869aba8cd6f60297719a962ba210f0 100644 (file)
@@ -34,6 +34,7 @@
 #include <pbd/basename.h>
 #include <glibmm/thread.h>
 #include <pbd/xml++.h>
+#include <pbd/memento_command.h>
 
 #include <ardour/ardour.h>
 #include <ardour/audioengine.h>
@@ -1594,7 +1595,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
 
                // cerr << _name << ": there are " << capture_info.size() << " capture_info records\n";
                
-               _session.add_undo (_playlist->get_memento());
+                XMLNode &before = _playlist->get_state();
                _playlist->freeze ();
                
                for (buffer_position = channels[0].write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
@@ -1625,7 +1626,8 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
                }
 
                _playlist->thaw ();
-               _session.add_redo_no_execute (_playlist->get_memento());
+                XMLNode &after = _playlist->get_state();
+               _session.add_command (new MementoCommand<Playlist>(*_playlist, before, after));
        }
 
        mark_write_completed = true;
index 52cfc187afe20d7bfe941ef0bffa1587419e7e30..25c8aeb53bd2d89c99e603214478f36f4ddcfa96 100644 (file)
 
 */
 
+#include <pbd/transmitter.h>
+#include <pbd/xml++.h>
+
+#include <ardour/audioengine.h>
 #include <ardour/audio_unit.h>
+#include <ardour/session.h>
 #include <ardour/utils.h>
 
+#include <appleutility/CAAudioUnit.h>
+
 #include <CoreServices/CoreServices.h>
 #include <AudioUnit/AudioUnit.h>
 
+#include "i18n.h"
+
+using namespace std;
+using namespace PBD;
 using namespace ARDOUR;
 
-PluginInfoList
-AUPluginInfo::discover ()
+AUPlugin::AUPlugin (AudioEngine& engine, Session& session, CAComponent* _comp)
+       :
+       Plugin (engine, session),
+       comp (_comp),
+       unit (new CAAudioUnit)
+{                      
+       OSErr err = CAAudioUnit::Open (*comp, *unit);
+       if (err != noErr) {
+               error << _("AudioUnit: Could not convert CAComponent to CAAudioUnit") << endmsg;
+               delete unit;
+               delete comp;
+               throw failed_constructor ();
+       }
+       
+       unit->Initialize ();
+}
+
+AUPlugin::~AUPlugin ()
 {
-       PluginInfoList plugs;
+       if (unit) {
+               unit->Uninitialize ();
+               delete unit;
+       }
+       
+       if (comp) {
+               delete comp;
+       }
+       
+       if (in_list) {
+               delete in_list;
+       }
+       
+       if (out_list) {
+               delete out_list;
+       }
+}
+
+AUPluginInfo::~AUPluginInfo ()
+{
+       if (desc) {
+               delete desc;
+       }
+}
 
-       int numTypes = 2;    // this magic number was retrieved from the apple AUHost example.
+uint32_t
+AUPlugin::unique_id () const
+{
+       return 0;
+}
 
-       ComponentDescription desc;
-       desc.componentFlags = 0;
-       desc.componentFlagsMask = 0;
-       desc.componentSubType = 0;
-       desc.componentManufacturer = 0;
+const char *
+AUPlugin::label () const
+{
+       return "AUPlugin label";
+}
 
-       vector<ComponentDescription> vCompDescs;
+const char *
+AUPlugin::maker () const
+{
+       return "AUplugin maker";
+}
 
-       for (int i = 0; i < numTypes; ++i) {
-               if (i == 1) {
-                       desc.componentType = kAudioUnitType_MusicEffect;
-               } else {
-                       desc.componentType = kAudioUnitType_Effect;
-               }
+uint32_t
+AUPlugin::parameter_count () const
+{
+       return 0;
+}
+
+float
+AUPlugin::default_value (uint32_t port)
+{
+       // AudioUnits don't have default values.  Maybe presets though?
+       return 0;
+}
+
+jack_nframes_t
+AUPlugin::latency () const
+{
+       return unit->Latency ();
+}
+
+void
+AUPlugin::set_parameter (uint32_t which, float val)
+{
+       unit->SetParameter (parameter_map[which].first, parameter_map[which].second, 0, val);
+}
+
+float
+AUPlugin::get_parameter (uint32_t which) const
+{
+       float outValue = 0.0;
+       
+       unit->GetParameter(parameter_map[which].first, parameter_map[which].second, 0, outValue);
+       
+       return outValue;
+}
+
+int
+AUPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const
+{
+       return -1;
+}
+
+uint32_t
+AUPlugin::nth_parameter (uint32_t which, bool& ok) const
+{
+       return 0;
+}
+
+void
+AUPlugin::activate ()
+{
+       unit->GlobalReset ();
+}
+
+void
+AUPlugin::deactivate ()
+{
+       // not needed.  GlobalReset () takes care of it.
+}
 
-               Component comp = 0;
+void
+AUPlugin::set_block_size (jack_nframes_t nframes)
+{
+       
+}
+
+int
+AUPlugin::connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, jack_nframes_t nframes, jack_nframes_t offset)
+{
+       AudioUnitRenderActionFlags flags = 0;
+       AudioTimeStamp ts;
+       
+       AudioBufferList abl;
+       abl.mNumberBuffers = 1;
+       abl.mBuffers[0].mNumberChannels = 1;
+       abl.mBuffers[0].mDataByteSize = nframes * sizeof(Sample);
+       abl.mBuffers[0].mData = &bufs[0];
+       
+       
+       unit->Render (&flags, &ts, 0, 0, &abl);
+       
+       return 0;
+}
+
+set<uint32_t>
+AUPlugin::automatable() const
+{
+       set<uint32_t> automates;
+       
+       return automates;
+}
 
-               comp = FindNextComponent (NULL, &desc);
-               while (comp != NULL) {
-                       ComponentDescription temp;
-                       GetComponentInfo (comp, &temp, NULL, NULL, NULL);
-                       vCompDescs.push_back(temp);
-                       comp = FindNextComponent (comp, &desc);
+void
+AUPlugin::store_state (ARDOUR::PluginState&)
+{
+       
+}
+
+void
+AUPlugin::restore_state (ARDOUR::PluginState&)
+{
+       
+}
+
+string
+AUPlugin::describe_parameter (uint32_t)
+{
+       return "";
+}
+
+void
+AUPlugin::print_parameter (uint32_t, char*, uint32_t len) const
+{
+       
+}
+
+bool
+AUPlugin::parameter_is_audio (uint32_t) const
+{
+       return false;
+}
+
+bool
+AUPlugin::parameter_is_control (uint32_t) const
+{
+       return false;
+}
+
+bool
+AUPlugin::parameter_is_input (uint32_t) const
+{
+       return false;
+}
+
+bool
+AUPlugin::parameter_is_output (uint32_t) const
+{
+       return false;
+}
+
+XMLNode&
+AUPlugin::get_state()
+{
+       XMLNode* root = new XMLNode (state_node_name());
+       
+       return *root;
+}
+
+int
+AUPlugin::set_state(const XMLNode& node)
+{
+       return -1;
+}
+
+bool
+AUPlugin::save_preset (string name)
+{
+       return false;
+}
+
+bool
+AUPlugin::load_preset (const string preset_label)
+{
+       return false;
+}
+
+vector<string>
+AUPlugin::get_presets ()
+{
+       vector<string> presets;
+       
+       return presets;
+}
+
+bool
+AUPlugin::has_editor () const
+{
+       return false;
+}
+
+PluginPtr
+AUPluginInfo::load (Session& session)
+{
+       try {
+               PluginPtr plugin;
+
+               CAComponent* comp = new CAComponent(*desc);
+               
+               if (!comp->IsValid()) {
+                       error << ("AudioUnit: not a valid Component") << endmsg;
+               } else {
+                       plugin.reset (new AUPlugin (session.engine(), session, comp));
                }
+               
+               plugin->set_info(PluginInfoPtr(new AUPluginInfo(*this)));
+               return plugin;
        }
 
-       for (unsigned int i = 0; i < vCompDescs.size(); ++i) {
-
-               // the following large block is just for determining the name of the plugin.
-               CFStringRef itemName = NULL;
-               // Marc Poirier -style item name
-               Component auComponent = FindNextComponent (0, &(vCompDescs[i]));
-               if (auComponent != NULL) {
-                       ComponentDescription dummydesc;
-                       Handle nameHandle = NewHandle(sizeof(void*));
-                       if (nameHandle != NULL) {
-                               OSErr err = GetComponentInfo(auComponent, &dummydesc, nameHandle, NULL, NULL);
-                               if (err == noErr) {
-                                       ConstStr255Param nameString = (ConstStr255Param) (*nameHandle);
-                                       if (nameString != NULL) {
-                                               itemName = CFStringCreateWithPascalString(kCFAllocatorDefault, nameString, CFStringGetSystemEncoding());
-                                       }
-                               }
-                               DisposeHandle(nameHandle);
-                       }
-               }
+       catch (failed_constructor &err) {
+               return PluginPtr ((Plugin*) 0);
+       }
+}
 
-               // if Marc-style fails, do the original way
-               if (itemName == NULL) {
-                       CFStringRef compTypeString = UTCreateStringForOSType(vCompDescs[i].componentType);
-                       CFStringRef compSubTypeString = UTCreateStringForOSType(vCompDescs[i].componentSubType);
-                       CFStringRef compManufacturerString = UTCreateStringForOSType(vCompDescs[i].componentManufacturer);
-
-                       itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ - %@ - %@"), 
-                               compTypeString, compManufacturerString, compSubTypeString);
-
-                       if (compTypeString != NULL)
-                               CFRelease(compTypeString);
-                       if (compSubTypeString != NULL)
-                               CFRelease(compSubTypeString);
-                       if (compManufacturerString != NULL)
-                               CFRelease(compManufacturerString);
-               }
-               string realname = CFStringRefToStdString(itemName);
+PluginInfoList
+AUPluginInfo::discover ()
+{
+       PluginInfoList plugs;
+
+       CAComponentDescription desc;
+       desc.componentFlags = 0;
+       desc.componentFlagsMask = 0;
+       desc.componentSubType = 0;
+       desc.componentManufacturer = 0;
+       desc.componentType = kAudioUnitType_Effect;
+
+       Component comp = 0;
 
+       comp = FindNextComponent (NULL, &desc);
+       while (comp != NULL) {
+               CAComponentDescription temp;
+               GetComponentInfo (comp, &temp, NULL, NULL, NULL);
+               
                AUPluginInfoPtr plug(new AUPluginInfo);
-               plug->name = realname;
+               plug->name = AUPluginInfo::get_name (temp);
                plug->type = PluginInfo::AudioUnit;
                plug->n_inputs = 0;
                plug->n_outputs = 0;
                plug->category = "AudioUnit";
+               plug->desc = new CAComponentDescription(temp);
 
                plugs.push_back(plug);
+               
+               comp = FindNextComponent (comp, &desc);
        }
 
        return plugs;
 }
+
+string
+AUPluginInfo::get_name (CAComponentDescription& comp_desc)
+{
+       CFStringRef itemName = NULL;
+       // Marc Poirier -style item name
+       CAComponent auComponent (comp_desc);
+       if (auComponent.IsValid()) {
+               CAComponentDescription dummydesc;
+               Handle nameHandle = NewHandle(sizeof(void*));
+               if (nameHandle != NULL) {
+                       OSErr err = GetComponentInfo(auComponent.Comp(), &dummydesc, nameHandle, NULL, NULL);
+                       if (err == noErr) {
+                               ConstStr255Param nameString = (ConstStr255Param) (*nameHandle);
+                               if (nameString != NULL) {
+                                       itemName = CFStringCreateWithPascalString(kCFAllocatorDefault, nameString, CFStringGetSystemEncoding());
+                               }
+                       }
+                       DisposeHandle(nameHandle);
+               }
+       }
+    
+       // if Marc-style fails, do the original way
+       if (itemName == NULL) {
+               CFStringRef compTypeString = UTCreateStringForOSType(comp_desc.componentType);
+               CFStringRef compSubTypeString = UTCreateStringForOSType(comp_desc.componentSubType);
+               CFStringRef compManufacturerString = UTCreateStringForOSType(comp_desc.componentManufacturer);
+    
+               itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ - %@ - %@"), 
+                       compTypeString, compManufacturerString, compSubTypeString);
+    
+               if (compTypeString != NULL)
+                       CFRelease(compTypeString);
+               if (compSubTypeString != NULL)
+                       CFRelease(compSubTypeString);
+               if (compManufacturerString != NULL)
+                       CFRelease(compManufacturerString);
+       }
+       
+       return CFStringRefToStdString(itemName);
+}
index 63492b375b7f93b2d5586209183cfd17010446e5..dc1767d1e79abc2d881f52e11572b73f205dbab0 100644 (file)
@@ -1246,3 +1246,17 @@ AutomationList::load_state (const XMLNode& node)
                add (x, y);
        }
 }
+
+XMLNode &AutomationList::get_state ()
+{
+    XMLNode *node = new XMLNode("AutomationList");
+    store_state(*node);
+    return *node;
+}
+
+int AutomationList::set_state(const XMLNode &s)
+{
+    load_state(s);
+    return 0;
+}
+
index 4eafbbe9a17598464380fa4834a15c33ed716d76..6f3b772eced5cb228886ecf48f5f65b5ea84289b 100644 (file)
@@ -193,9 +193,9 @@ setup_midi (AudioEngine& engine     )
 }
 
 int
-ARDOUR::init (AudioEngine& engine, bool use_vst, bool try_optimization)
+ARDOUR::init (ARDOUR::AudioEngine& engine, bool use_vst, bool try_optimization)
 {
-        bool generic_mix_functions = true;
+       bool generic_mix_functions = true;
 
        (void) bindtextdomain(PACKAGE, LOCALEDIR);
 
@@ -303,7 +303,7 @@ ARDOUR::init (AudioEngine& engine, bool use_vst, bool try_optimization)
        }
 
        /* singleton - first object is "it" */
-       new PluginManager (engine);
+       new PluginManager ();
        
        /* singleton - first object is "it" */
        new ControlProtocolManager ();
index 11b1e25a743f01c744028310b71f375ae045bc8e..a057fef931708e23b733c7e73eaf5ca1e9805dbe 100644 (file)
@@ -186,25 +186,25 @@ PluginInsert::auto_state_changed (uint32_t which)
 uint32_t
 PluginInsert::output_streams() const
 {
-       return _plugins[0]->get_info().n_outputs * _plugins.size();
+       return _plugins[0]->get_info()->n_outputs * _plugins.size();
 }
 
 uint32_t
 PluginInsert::input_streams() const
 {
-       return _plugins[0]->get_info().n_inputs * _plugins.size();
+       return _plugins[0]->get_info()->n_inputs * _plugins.size();
 }
 
 uint32_t
 PluginInsert::natural_output_streams() const
 {
-       return _plugins[0]->get_info().n_outputs;
+       return _plugins[0]->get_info()->n_outputs;
 }
 
 uint32_t
 PluginInsert::natural_input_streams() const
 {
-       return _plugins[0]->get_info().n_inputs;
+       return _plugins[0]->get_info()->n_inputs;
 }
 
 bool
@@ -214,7 +214,7 @@ PluginInsert::is_generator() const
           a specific "instrument" flag, for example.
         */
 
-       return _plugins[0]->get_info().n_inputs == 0;
+       return _plugins[0]->get_info()->n_inputs == 0;
 }
 
 void
@@ -350,7 +350,7 @@ PluginInsert::silence (jack_nframes_t nframes, jack_nframes_t offset)
 
        if (active()) {
                for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
-                       n = (*i) -> get_info().n_inputs;
+                       n = (*i) -> get_info()->n_inputs;
                        (*i)->connect_and_run (_session.get_silent_buffers (n), n, in_index, out_index, nframes, offset);
                }
        }
@@ -367,8 +367,8 @@ PluginInsert::run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframe
                        connect_and_run (bufs, nbufs, nframes, offset, false);
                }
        } else {
-               uint32_t in = _plugins[0]->get_info().n_inputs;
-               uint32_t out = _plugins[0]->get_info().n_outputs;
+               uint32_t in = _plugins[0]->get_info()->n_inputs;
+               uint32_t out = _plugins[0]->get_info()->n_outputs;
 
                if (out > in) {
 
@@ -524,7 +524,7 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
 int32_t
 PluginInsert::compute_output_streams (int32_t cnt) const
 {
-       return _plugins[0]->get_info().n_outputs * cnt;
+       return _plugins[0]->get_info()->n_outputs * cnt;
 }
 
 int32_t
@@ -536,8 +536,8 @@ PluginInsert::configure_io (int32_t magic, int32_t in, int32_t out)
 int32_t 
 PluginInsert::can_support_input_configuration (int32_t in) const
 {
-       int32_t outputs = _plugins[0]->get_info().n_outputs;
-       int32_t inputs = _plugins[0]->get_info().n_inputs;
+       int32_t outputs = _plugins[0]->get_info()->n_outputs;
+       int32_t inputs = _plugins[0]->get_info()->n_inputs;
 
        if (inputs == 0) {
 
@@ -591,7 +591,7 @@ PluginInsert::state (bool full)
        node->add_property("id", string(buf));
        if (_plugins[0]->state_node_name() == "ladspa") {
                char buf[32];
-               snprintf (buf, sizeof (buf), "%ld", _plugins[0]->get_info().unique_id); 
+               snprintf (buf, sizeof (buf), "%ld", _plugins[0]->get_info()->unique_id); 
                node->add_property("unique-id", string(buf));
        }
        node->add_property("count", string_compose("%1", _plugins.size()));
@@ -761,7 +761,7 @@ PluginInsert::set_state(const XMLNode& node)
        }
        
        // The name of the PluginInsert comes from the plugin, nothing else
-       set_name(plugin->get_info().name,this);
+       set_name(plugin->get_info()->name,this);
        
        return 0;
 }
index 2dfd735a6b28150edc93703c09c577fa20a9123b..4d2d26f8014e6a3590311c9a6a5a740e5331602b 100644 (file)
@@ -170,7 +170,7 @@ IO::silence (jack_nframes_t nframes, jack_nframes_t offset)
 void
 IO::apply_declick (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, gain_t initial, gain_t target, bool invert_polarity)
 {
-       jack_nframes_t declick = min ((jack_nframes_t)4096, nframes);
+       jack_nframes_t declick = min ((jack_nframes_t)128, nframes);
        gain_t delta;
        Sample *buffer;
        double fractional_shift;
index fa19a682e77fcd279a5c064db0225691bf0efd5c..6b773b9e0bad915da4f18e36ac65c872ad181094 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000-2002 Paul Davis 
+    Copyright (C) 2000-2006 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
@@ -641,3 +641,26 @@ LadspaPlugin::latency_compute_run ()
        run (bufsize);
        deactivate ();
 }
+
+PluginPtr
+LadspaPluginInfo::load (Session& session)
+{
+       try {
+               PluginPtr plugin;
+               void *module;
+
+               if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) {
+                       error << string_compose(_("LADSPA: cannot load module from \"%1\""), path) << endmsg;
+                       error << dlerror() << endmsg;
+               } else {
+                       plugin.reset (new LadspaPlugin (module, session.engine(), session, index, session.frame_rate()));
+               }
+
+               plugin->set_info(PluginInfoPtr(new LadspaPluginInfo(*this)));
+               return plugin;
+       }
+
+       catch (failed_constructor &err) {
+               return PluginPtr ((Plugin*) 0);
+       }       
+}
index 6763e7f5084efa6819d1f962bfbca4fade1d5948..8ea95b89037db9333fdd1713fe32d667fc67ff1e 100644 (file)
@@ -39,6 +39,8 @@
 #include <ardour/session.h>
 #include <ardour/audioengine.h>
 #include <ardour/plugin.h>
+#include <ardour/ladspa_plugin.h>
+#include <ardour/plugin_manager.h>
 
 #include <pbd/stl_delete.h>
 
@@ -240,3 +242,43 @@ Plugin::save_preset (string name, string domain)
 
        return true;
 }
+
+PluginPtr
+ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginInfo::Type type)
+{
+       PluginManager *mgr = PluginManager::the_manager();
+       PluginInfoList plugs;
+
+       switch (type) {
+       case PluginInfo::LADSPA:
+               plugs = mgr->ladspa_plugin_info();
+               break;
+
+#ifdef VST_SUPPORT
+       case PluginInfo::VST:
+               plugs = mgr->vst_plugin_info();
+               unique_id = 0; // VST plugins don't have a unique id.
+               break;
+#endif
+
+#ifdef HAVE_COREAUDIO
+       case PluginInfo::AudioUnit:
+               plugs = AUPluginInfo::discover ();
+               unique_id = 0; // Neither do AU.
+               break;
+#endif
+
+       default:
+               return PluginPtr ((Plugin *) 0);
+       }
+
+       PluginInfoList::iterator i;
+       for (i = plugs.begin(); i != plugs.end(); ++i) {
+               if ((name == "" || (*i)->name == name) &&
+                       (unique_id == 0 || (*i)->unique_id == unique_id)) {
+                               return (*i)->load (session);
+               }
+       }
+       
+       return PluginPtr ((Plugin*) 0);
+}
index 06a944189a44cb2dbd74a8e76e7d18188d7f19ff..2a753617e88967b8ae87bb9c5f9857c1af2c1187 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000-2004 Paul Davis 
+    Copyright (C) 2000-2006 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
 #include <ardour/plugin_manager.h>
 #include <ardour/plugin.h>
 #include <ardour/ladspa_plugin.h>
+
+#ifdef VST_SUPPORT
 #include <ardour/vst_plugin.h>
-#include <ardour/audio_unit.h>
+#endif
 
 #include <pbd/error.h>
 #include <pbd/stl_delete.h>
@@ -49,8 +51,7 @@ using namespace PBD;
 
 PluginManager* PluginManager::_manager = 0;
 
-PluginManager::PluginManager (AudioEngine& e)
-       : _engine (e)
+PluginManager::PluginManager ()
 {
        char* s;
        string lrdf_path;
@@ -97,10 +98,6 @@ PluginManager::refresh ()
                vst_refresh ();
        }
 #endif // VST_SUPPORT
-
-#ifdef HAVE_COREAUDIO
-       _au_plugin_info = AUPluginInfo::discover ();
-#endif // HAVE_COREAUDIO
 }
 
 void
@@ -250,7 +247,7 @@ PluginManager::ladspa_discover (string path)
                        break;
                }
 
-               PluginInfoPtr info(new PluginInfo);
+               PluginInfoPtr info(new LadspaPluginInfo);
                info->name = descriptor->Name;
                info->category = get_ladspa_category(descriptor->UniqueID);
                info->path = path;
@@ -280,85 +277,6 @@ PluginManager::ladspa_discover (string path)
        return 0;
 }
 
-boost::shared_ptr<Plugin>
-PluginManager::load (Session& session, PluginInfoPtr info)
-{
-       void *module;
-
-       try {
-               boost::shared_ptr<Plugin> plugin;
-
-               if (info->type == PluginInfo::VST) {
-
-#ifdef VST_SUPPORT                     
-                       if (Config->get_use_vst()) {
-                               FSTHandle* handle;
-                               
-                               if ((handle = fst_load (info->path.c_str())) == 0) {
-                                       error << string_compose(_("VST: cannot load module from \"%1\""), info->path) << endmsg;
-                               } else {
-                                       plugin.reset (new VSTPlugin (_engine, session, handle));
-                               }
-                       } else {
-                               error << _("You asked ardour to not use any VST plugins") << endmsg;
-                       }
-#else // !VST_SUPPORT
-                       error << _("This version of ardour has no support for VST plugins") << endmsg;
-                       return boost::shared_ptr<Plugin> ((Plugin*) 0);
-#endif // !VST_SUPPORT
-                               
-               } else {
-
-                       if ((module = dlopen (info->path.c_str(), RTLD_NOW)) == 0) {
-                               error << string_compose(_("LADSPA: cannot load module from \"%1\""), info->path) << endmsg;
-                               error << dlerror() << endmsg;
-                       } else {
-                               plugin.reset (new LadspaPlugin (module, _engine, session, info->index, session.frame_rate()));
-                       }
-               }
-
-               plugin->set_info(*info);
-               return plugin;
-       }
-
-       catch (failed_constructor &err) {
-               return boost::shared_ptr<Plugin> ((Plugin*) 0);
-       }
-}
-
-boost::shared_ptr<Plugin>
-ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginInfo::Type type)
-{
-       PluginManager *mgr = PluginManager::the_manager();
-       PluginInfoList* plugs = 0;
-
-       switch (type) {
-       case PluginInfo::LADSPA:
-               plugs = &mgr->ladspa_plugin_info();
-               break;
-       case PluginInfo::VST:
-               plugs = &mgr->vst_plugin_info();
-               unique_id = 0; // VST plugins don't have a unique id.
-               break;
-       case PluginInfo::AudioUnit:
-               plugs = &mgr->au_plugin_info();
-               unique_id = 0;
-               break;
-       default:
-               return boost::shared_ptr<Plugin> ((Plugin *) 0);
-       }
-
-       PluginInfoList::iterator i;
-       for (i = plugs->begin(); i != plugs->end(); ++i) {
-               if ((name == "" || (*i)->name == name) &&
-                       (unique_id == 0 || (*i)->unique_id == unique_id)) {     
-                       return mgr->load (session, *i);
-               }
-       }
-       
-       return boost::shared_ptr<Plugin> ((Plugin*) 0);
-}
-
 string
 PluginManager::get_ladspa_category (uint32_t plugin_id)
 {
@@ -464,7 +382,7 @@ PluginManager::vst_discover (string path)
                        << endl;
        }
        
-       PluginInfoPtr info(new PluginInfo);
+       PluginInfoPtr info(new VSTPluginInfo);
 
        /* what a goddam joke freeware VST is */
 
index 902da43d91f317dbf47b9263a5986660c258445b..bfcb69572a8f80d97e7cf7c2859eecf92c91bd67 100644 (file)
@@ -1023,6 +1023,7 @@ Session::auto_punch_start_changed (Location* location)
        if (get_record_enabled() && get_punch_in()) {
                /* capture start has been changed, so save new pending state */
                save_state ("", true);
+                save_history();
        }
 }      
 
@@ -1344,6 +1345,7 @@ Session::maybe_enable_record ()
        */
 
        save_state ("", true);
+        save_history();
 
        if (_transport_speed) {
                if (!punch_in) {
@@ -2131,6 +2133,7 @@ Session::add_diskstream (Diskstream* dstream)
 
        set_dirty();
        save_state (_current_snapshot_name);
+        save_history();
 
        DiskstreamAdded (dstream); /* EMIT SIGNAL */
 }
@@ -2882,6 +2885,7 @@ Session::remove_source (Source* source)
                */
                
                save_state (_current_snapshot_name);
+                save_history();
        }
 
        SourceRemoved(source); /* EMIT SIGNAL */
diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc
new file mode 100644 (file)
index 0000000..9a43de5
--- /dev/null
@@ -0,0 +1,101 @@
+#include <ardour/session.h>
+#include <ardour/route.h>
+
+namespace ARDOUR {
+// solo
+Session::GlobalSoloStateCommand::GlobalSoloStateCommand(Session &sess, void *src)
+    : sess(sess), src(src)
+{
+    after = before = sess.get_global_route_boolean(&Route::soloed);
+}
+void Session::GlobalSoloStateCommand::mark()
+{
+    after = sess.get_global_route_boolean(&Route::soloed);
+}
+void Session::GlobalSoloStateCommand::operator()()
+{
+    sess.set_global_solo(after, src);
+}
+void Session::GlobalSoloStateCommand::undo()
+{
+    sess.set_global_solo(before, src);
+}
+XMLNode &Session::GlobalSoloStateCommand::get_state()
+{
+    XMLNode *node = new XMLNode("GlobalSoloStateCommand");
+    return *node;
+}
+
+// mute
+Session::GlobalMuteStateCommand::GlobalMuteStateCommand(Session &sess, void *src)
+    : sess(sess), src(src)
+{
+    after = before = sess.get_global_route_boolean(&Route::muted);
+}
+void Session::GlobalMuteStateCommand::mark()
+{
+    after = sess.get_global_route_boolean(&Route::muted);
+}
+void Session::GlobalMuteStateCommand::operator()()
+{
+    sess.set_global_mute(after, src);
+}
+void Session::GlobalMuteStateCommand::undo()
+{
+    sess.set_global_mute(before, src);
+}
+XMLNode &Session::GlobalMuteStateCommand::get_state()
+{
+    XMLNode *node = new XMLNode("GlobalMuteStateCommand");
+    return *node;
+}
+
+// record enable
+Session::GlobalRecordEnableStateCommand::GlobalRecordEnableStateCommand(Session &sess, void *src) 
+    : sess(sess), src(src)
+{
+    after = before = sess.get_global_route_boolean(&Route::record_enabled);
+}
+void Session::GlobalRecordEnableStateCommand::mark()
+{
+    after = sess.get_global_route_boolean(&Route::record_enabled);
+}
+void Session::GlobalRecordEnableStateCommand::operator()()
+{
+    sess.set_global_record_enable(after, src);
+}
+void Session::GlobalRecordEnableStateCommand::undo()
+{
+    sess.set_global_record_enable(before, src);
+}
+XMLNode &Session::GlobalRecordEnableStateCommand::get_state()
+{
+    XMLNode *node = new XMLNode("GlobalRecordEnableStateCommand");
+    return *node;
+}
+
+// metering
+Session::GlobalMeteringStateCommand::GlobalMeteringStateCommand(Session &sess, void *src) 
+    : sess(sess), src(src)
+{
+    after = before = sess.get_global_route_metering();
+}
+void Session::GlobalMeteringStateCommand::mark()
+{
+    after = sess.get_global_route_metering();
+}
+void Session::GlobalMeteringStateCommand::operator()()
+{
+    sess.set_global_route_metering(after, src);
+}
+void Session::GlobalMeteringStateCommand::undo()
+{
+    sess.set_global_route_metering(before, src);
+}
+XMLNode &Session::GlobalMeteringStateCommand::get_state()
+{
+    XMLNode *node = new XMLNode("GlobalMeteringStateCommand");
+    return *node;
+}
+
+} // namespace ARDOUR
index 8d11fd3b3ff86e61456530cf90af446b151db443..bb319511b7128ae0e3559cb5dde94f51ff5dd484 100644 (file)
@@ -611,6 +611,7 @@ Session::create (bool& new_session, string* mix_template, jack_nframes_t initial
                _state_of_the_state = Clean;
 
                if (save_state (_current_snapshot_name)) {
+                        save_history();
                        return -1;
                }
        }
@@ -1697,6 +1698,7 @@ Session::set_state (const XMLNode& node)
 
        if (state_was_pending) {
                save_state (_current_snapshot_name);
+                save_history();
                remove_pending_capture_state ();
                state_was_pending = false;
        }
@@ -2498,6 +2500,7 @@ void
 Session::auto_save()
 {
        save_state (_current_snapshot_name);
+        save_history();
 }
 
 RouteGroup *
@@ -2590,29 +2593,25 @@ Session::set_meter_falloff (float val)
 
 
 void
-Session::begin_reversible_command (string name, UndoAction* private_undo)
+Session::begin_reversible_command (string name)
 {
-       current_cmd.clear ();
-       current_cmd.set_name (name);
-
-       if (private_undo) {
-               current_cmd.add_undo (*private_undo);
-       }
+       current_trans.clear ();
+       current_trans.set_name (name);
 }
 
 void
-Session::commit_reversible_command (UndoAction* private_redo)
+Session::commit_reversible_command (Command *cmd)
 {
        struct timeval now;
 
-       if (private_redo) {
-               current_cmd.add_redo_no_execute (*private_redo);
+       if (cmd) {
+               current_trans.add_command (cmd);
        }
 
        gettimeofday (&now, 0);
-       current_cmd.set_timestamp (now);
+       current_trans.set_timestamp (now);
 
-       history.add (current_cmd);
+       history.add (current_trans);
 }
 
 Session::GlobalRouteBooleanState 
@@ -2691,6 +2690,7 @@ Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
        set_global_route_boolean (s, &Route::set_record_enable, src);
 }
 
+#if 0
 UndoAction
 Session::global_mute_memento (void* src)
 {
@@ -2714,6 +2714,7 @@ Session::global_record_enable_memento (void* src)
 {
        return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
 }
+#endif
 
 static bool
 template_filter (const string &str, void *arg)
@@ -3301,3 +3302,48 @@ Session::add_instant_xml (XMLNode& node, const std::string& dir)
        Stateful::add_instant_xml (node, dir);
        Config->add_instant_xml (node, get_user_ardour_path());
 }
+
+
+int 
+Session::save_history ()
+{
+    XMLTree tree;
+    string xml_path;
+    string bak_path;
+
+    tree.set_root (&history.get_state());
+
+    xml_path = _path + _current_snapshot_name + ".history"; 
+
+    bak_path = xml_path + ".bak";
+
+    if ((access (xml_path.c_str(), F_OK) == 0) &&
+        (rename (xml_path.c_str(), bak_path.c_str())))
+    {
+        error << _("could not backup old history file, current history not saved.") << endmsg;
+        return -1;
+    }
+
+    if (!tree.write (xml_path))
+    {
+        error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
+
+        /* don't leave a corrupt file lying around if it is
+         * possible to fix.
+         */
+
+        if (unlink (xml_path.c_str())) 
+        {
+            error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
+        } else {
+            if (rename (bak_path.c_str(), xml_path.c_str())) 
+            {
+                error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
+            }
+        }
+
+        return -1;
+    }
+
+    return 0;
+}
index bff8ae595524f840393992ac4b1eca6c881e13a9..592f9c86c65456caa5dbb70eb19996c72f03f724 100644 (file)
@@ -29,6 +29,7 @@
 #include <pbd/error.h>
 #include <glibmm/thread.h>
 #include <pbd/pthread_utils.h>
+#include <pbd/memento_command.h>
 
 #include <midi++/mmc.h>
 #include <midi++/port.h>
@@ -325,8 +326,10 @@ Session::non_realtime_stop (bool abort)
                }
                
                if (change_end) {
-                       add_undo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), loc->end())));
-                       add_redo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), _transport_frame)));
+                        XMLNode &before = loc->get_state();
+                        loc->set_end(_transport_frame);
+                        XMLNode &after = loc->get_state();
+                        add_command (new MementoCommand<Location>(*loc, before, after));
                }
 
                _end_location_is_free = false;
@@ -410,6 +413,7 @@ Session::non_realtime_stop (bool abort)
        if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
                /* capture start has been changed, so save pending state */
                save_state ("", true);
+                save_history();
        }
 
         /* always try to get rid of this */
index bcffe381c382be341f3ef1b90c7d89b82f4383f2..153773ed30c8cc54778b69793de93b03d144126f 100644 (file)
@@ -72,6 +72,9 @@ StateManager::use_state (state_id_t id)
 void
 StateManager::save_state (std::string why)
 {
+       if (!should_save_state())
+               return;
+
        if (!_allow_save) {
                SaveAllowed.connect (mem_fun (*this, &StateManager::save_state));
                return;
index 3b3b705a878d1e3b3a840cce6fc3b9fa1b38587d..f81ef9de4dea364dba22b01acb58b0c88eff8529 100644 (file)
@@ -31,6 +31,7 @@
 #include <ardour/audioplaylist.h>
 #include <ardour/panner.h>
 #include <ardour/utils.h>
+#include <ardour/connection.h>
 
 #include "i18n.h"
 
@@ -146,6 +147,18 @@ Track::record_enabled () const
 {
        return _diskstream->record_enabled ();
 }
+
+bool
+Track::can_record()
+{
+       bool will_record = true;
+       for (size_t i = 0; i < _inputs.size() && will_record; i++) {
+               if (!_inputs[i]->connected())
+                       will_record = false;
+       }
+
+       return will_record;
+}
        
 void
 Track::set_record_enable (bool yn, void *src)
@@ -159,8 +172,13 @@ Track::set_record_enable (bool yn, void *src)
                return;
        }
 
-       /* keep track of the meter point as it was before we rec-enabled */
+       // Do not set rec enabled if the track can't record.
+       if (yn && !can_record()) {
+               error << string_compose( _("Can not arm track '%1'. Check the input connections"), name() ) << endmsg;
+               return;
+       }
 
+       /* keep track of the meter point as it was before we rec-enabled */
        if (!_diskstream->record_enabled()) {
                _saved_meter_point = _meter_point;
        }
@@ -206,6 +224,7 @@ Track::set_name (string str, void *src)
 
        if ((ret = IO::set_name (str, src)) == 0) {
                _session.save_state ("");
+                _session.save_history();
        }
        return ret;
 }
index 352b887e133c1a42c80d69178939bf6e5398d6c6..4c09ba34401ed848a7e84e5bd19bf642e39480b0 100644 (file)
@@ -479,3 +479,33 @@ VSTPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const
 
        memmove (buf, first_nonws, strlen (buf) - (first_nonws - buf) + 1);
 }
+
+PluginPtr
+VSTPluginInfo::load (Session& session)
+{
+       try {
+               PluginPtr plugin;
+
+               if (Config->get_use_vst()) {
+                       FSTHandle* handle;
+                       
+                       handle = fst_load(path.c_str());
+       
+                       if ( (int)handle == -1) {
+                               error << string_compose(_("VST: cannot load module from \"%1\""), path) << endmsg;
+                       } else {
+                               plugin.reset (new VSTPlugin (session.engine(), session, handle));
+                       }
+               } else {
+                       error << _("You asked ardour to not use any VST plugins") << endmsg;
+                       return PluginPtr ((Plugin*) 0);
+               }
+
+               plugin->set_info(PluginInfoPtr(new VSTPluginInfo(*this)));
+               return plugin;
+       }       
+
+       catch (failed_constructor &err) {
+               return PluginPtr ((Plugin*) 0);
+       }
+}
index 1f0872f0bd77254c44467b9d9b31dbb7520a81f7..b74a4e3253df98374b2a6937f2e462a2b577a582 100644 (file)
@@ -128,38 +128,38 @@ static const int legal_sample_rates [] =
 {      8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000
 } ;
 
-static inline void
+static void
 s2flac8_array (const short *src, FLAC__int32 *dest, int count)
 {      while (--count >= 0)
                dest [count] = src [count] >> 8 ;
 } /* s2flac8_array */
 
-static inline void
+static void
 s2flac16_array (const short *src, FLAC__int32 *dest, int count)
 {      while (--count >= 0)
                dest [count] = src [count] ;
 } /* s2flac16_array */
 
-static inline void
+static void
 s2flac24_array (const short *src, FLAC__int32 *dest, int count)
 {      while (--count >= 0)
                dest [count] = src [count] << 8 ;
 } /* s2flac24_array */
 
-static inline void
+static void
 i2flac8_array (const int *src, FLAC__int32 *dest, int count)
 {      while (--count >= 0)
                dest [count] = src [count] >> 24 ;
 } /* i2flac8_array */
 
-static inline void
+static void
 i2flac16_array (const int *src, FLAC__int32 *dest, int count)
 {
   while (--count >= 0)
     dest [count] = src [count] >> 16 ;
 } /* i2flac16_array */
 
-static inline void
+static void
 i2flac24_array (const int *src, FLAC__int32 *dest, int count)
 {      while (--count >= 0)
                dest [count] = src [count] >> 8 ;
index 36fb02885ff16a352865cc16fca3d32e514cf726..4b15dd70d12889be24eb8046220a3352918f3373 100644 (file)
@@ -21,6 +21,7 @@ pbd_files = Split("""
 basename.cc
 base_ui.cc
 convert.cc
+command.cc
 controllable.cc
 dmalloc.cc
 error.cc
diff --git a/libs/pbd/command.cc b/libs/pbd/command.cc
new file mode 100644 (file)
index 0000000..5b41691
--- /dev/null
@@ -0,0 +1,10 @@
+#include <pbd/command.h>
+#include <pbd/xml++.h>
+
+
+XMLNode &Command::get_state()
+{
+    XMLNode *node = new XMLNode ("Command");
+    node->add_content("WARNING: Somebody forgot to subclass Command.");
+    return *node;
+}
index f9afa72c985a359f667e985c5666544759c5c64e..0de0d052c3d7a5e2d6e5c84697f8d553adba61df 100644 (file)
@@ -8,6 +8,7 @@
 #include <inttypes.h>
 
 #include <pbd/id.h>
+#include <string>
 
 using namespace std;
 using namespace PBD;
@@ -45,6 +46,13 @@ ID::print (char* buf) const
        snprintf (buf, 16, "%" PRIu64, id);
 }
 
+string ID::to_s() const
+{
+    char buf[16]; // see print()
+    print(buf);
+    return string(buf);
+}
+
 ID&
 ID::operator= (string str)
 {
diff --git a/libs/pbd/pbd/command.h b/libs/pbd/pbd/command.h
new file mode 100644 (file)
index 0000000..cd9bf0e
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+   Copyright (C) 2006 Hans Fugal & 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.
+
+    $Id: /local/undo/libs/pbd3/pbd/undo.h 80 2006-06-22T22:37:01.079855Z fugalh  $
+*/
+
+#ifndef __lib_pbd_command_h__
+#define __lib_pbd_command_h__
+
+#include <pbd/stateful.h>
+
+class Command : public Stateful
+{
+    public:
+       virtual ~Command() {}
+       virtual void operator() () = 0;
+        virtual void undo() = 0;
+        virtual void redo() { (*this)(); }
+        virtual XMLNode &get_state();
+        virtual int set_state(const XMLNode&) { /* noop */ return 0; }
+};
+
+#endif // __lib_pbd_command_h_
index 9a3f10478ddcc57bf328ed66e2fab095b8806edb..1ce448d58bd1397b15d7379f4a8a426f9c6d1a98 100644 (file)
@@ -28,6 +28,7 @@ class ID {
        }
 
        void print (char* buf) const;
+        std::string to_s() const;
        
        static uint64_t counter() { return _counter; }
        static void init_counter (uint64_t val) { _counter = val; }
diff --git a/libs/pbd/pbd/memento_command.h b/libs/pbd/pbd/memento_command.h
new file mode 100644 (file)
index 0000000..46c724e
--- /dev/null
@@ -0,0 +1,99 @@
+/* 
+   Copyright (C) 2006 Hans Fugal & 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.
+
+    $Id: /local/undo/libs/pbd3/pbd/undo.h 132 2006-06-29T18:45:16.609763Z fugalh  $
+*/
+
+#ifndef __lib_pbd_memento_command_h__
+#define __lib_pbd_memento_command_h__
+
+#include <pbd/command.h>
+#include <pbd/xml++.h>
+#include <sigc++/slot.h>
+
+/** This command class is initialized with before and after mementos 
+ * (from Stateful::get_state()), so undo becomes restoring the before
+ * memento, and redo is restoring the after memento.
+ */
+template <class obj_T>
+class MementoCommand : public Command
+{
+    public:
+        MementoCommand(obj_T &obj, 
+                       XMLNode &before,
+                       XMLNode &after
+                       ) 
+            : obj(obj), before(before), after(after) {}
+        void operator() () { obj.set_state(after); }
+        void undo() { obj.set_state(before); }
+        virtual XMLNode &get_state() 
+        {
+            XMLNode *node = new XMLNode("MementoCommand");
+            node->add_property("obj_id", obj.id().to_s());
+            node->add_child_nocopy(before);
+            node->add_child_nocopy(after);
+            return *node;
+        }
+        // TODO does this need a copy constructor?
+    protected:
+        obj_T &obj;
+        XMLNode &before, &after;
+};
+
+template <class obj_T>
+class MementoUndoCommand : public Command
+{
+public:
+    MementoUndoCommand(obj_T &obj, 
+                       XMLNode &before)
+        : obj(obj), before(before) {}
+    void operator() () { /* noop */ }
+    void undo() { obj.set_state(before); }
+    virtual XMLNode &get_state() 
+    {
+        XMLNode *node = new XMLNode("MementoUndoCommand");
+        node->add_property("obj_id", obj.id().to_s());
+        node->add_child_nocopy(before);
+        return *node;
+    }
+protected:
+    obj_T &obj;
+    XMLNode &before;
+};
+
+template <class obj_T>
+class MementoRedoCommand : public Command
+{
+public:
+    MementoRedoCommand(obj_T &obj, 
+                       XMLNode &after)
+        : obj(obj), after(after) {}
+    void operator() () { obj.set_state(after); }
+    void undo() { /* noop */ }
+    virtual XMLNode &get_state()
+    {
+        XMLNode *node = new XMLNode("MementoRedoCommand");
+        node->add_property("obj_id", obj.id().to_s());
+        node->add_child_nocopy(after);
+        return *node;
+    }
+protected:
+    obj_T &obj;
+    XMLNode &after;
+};
+
+#endif // __lib_pbd_memento_h__
index f067635ed3a2adf3ba9c58f393e779c0e05c4288..724e86aaa05ccfa58a898babf351a313be08b45e 100644 (file)
 
 #include <string>
 #include <list>
+#include <map>
 #include <sigc++/slot.h>
+#include <sigc++/bind.h>
 #include <sys/time.h>
+#include <pbd/command.h>
 
 using std::string;
 using std::list;
 
 typedef sigc::slot<void> UndoAction;
 
-class UndoCommand 
+class UndoTransaction : public Command
 {
   public:
-       UndoCommand ();
-       UndoCommand (const UndoCommand&);
-       UndoCommand& operator= (const UndoCommand&);
+       UndoTransaction ();
+       UndoTransaction (const UndoTransaction&);
+       UndoTransaction& operator= (const UndoTransaction&);
 
        void clear ();
 
-       void add_undo (const UndoAction&);
-       void add_redo (const UndoAction&);
-       void add_redo_no_execute (const UndoAction&);
+       void add_command (Command *const);
 
+        void operator() ();
        void undo();
        void redo();
+
+       XMLNode &get_state();
        
        void set_name (const string& str) {
                _name = str;
@@ -61,8 +65,7 @@ class UndoCommand
        }
 
   private:
-       list<UndoAction> redo_actions;
-       list<UndoAction> undo_actions;
+       list<Command*>   actions;
        struct timeval   _timestamp;
        string           _name;
 };
@@ -73,7 +76,7 @@ class UndoHistory
        UndoHistory() {}
        ~UndoHistory() {}
        
-       void add (UndoCommand uc);
+       void add (UndoTransaction ut);
        void undo (unsigned int n);
        void redo (unsigned int n);
        
@@ -87,9 +90,11 @@ class UndoHistory
        void clear_undo ();
        void clear_redo ();
 
+        XMLNode &get_state();
+        void save_state();
   private:
-       list<UndoCommand> UndoList;
-       list<UndoCommand> RedoList;
+       list<UndoTransaction> UndoList;
+       list<UndoTransaction> RedoList;
 };
 
 
index f2f11b1c5cc3fc4b9546f50ebafc89ca76a92540..8d1b416c16bcf66d1c611eaf45902288b9113cba 100644 (file)
 #include <iostream>
 
 #include <pbd/undo.h>
+#include <pbd/xml++.h>
+#include <string>
 
 using namespace std;
 using namespace sigc;
 
-UndoCommand::UndoCommand ()
+UndoTransaction::UndoTransaction ()
 {
 }
 
-UndoCommand::UndoCommand (const UndoCommand& rhs)
+UndoTransaction::UndoTransaction (const UndoTransaction& rhs)
 {
        _name = rhs._name;
        clear ();
-       undo_actions.insert(undo_actions.end(),rhs.undo_actions.begin(),rhs.undo_actions.end());
-       redo_actions.insert(redo_actions.end(),rhs.redo_actions.begin(),rhs.redo_actions.end());
+       actions.insert(actions.end(),rhs.actions.begin(),rhs.actions.end());
 }
 
-UndoCommand
-UndoCommand::operator= (const UndoCommand& rhs)
+UndoTransaction
+UndoTransaction::operator= (const UndoTransaction& rhs)
 {
        if (this == &rhs) return *this;
        _name = rhs._name;
        clear ();
-       undo_actions.insert(undo_actions.end(),rhs.undo_actions.begin(),rhs.undo_actions.end());
-       redo_actions.insert(redo_actions.end(),rhs.redo_actions.begin(),rhs.redo_actions.end());
+       actions.insert(actions.end(),rhs.actions.begin(),rhs.actions.end());
        return *this;
 }
 
 void
-UndoCommand::add_undo (const UndoAction& action)
+UndoTransaction::add_command (Command *const action)
 {
-       undo_actions.push_back (action);
+       actions.push_back (action);
 }
 
 void
-UndoCommand::add_redo (const UndoAction& action)
+UndoTransaction::clear ()
 {
-       redo_actions.push_back (action);
-       redo_actions.back()(); // operator()
+       actions.clear ();
 }
 
 void
-UndoCommand::add_redo_no_execute (const UndoAction& action)
+UndoTransaction::operator() ()
 {
-       redo_actions.push_back (action);
-}
-
-void
-UndoCommand::clear ()
-{
-       undo_actions.clear ();
-       redo_actions.clear ();
+       for (list<Command*>::iterator i = actions.begin(); i != actions.end(); ++i) {
+               (*(*i))();
+       }
 }
 
 void
-UndoCommand::undo ()
+UndoTransaction::undo ()
 {
        cerr << "Undo " << _name << endl;
-       for (list<UndoAction>::reverse_iterator i = undo_actions.rbegin(); i != undo_actions.rend(); ++i) {
-               (*i)();
+       for (list<Command*>::reverse_iterator i = actions.rbegin(); i != actions.rend(); ++i) {
+               (*i)->undo();
        }
 }
 
 void
-UndoCommand::redo ()
+UndoTransaction::redo ()
 {
        cerr << "Redo " << _name << endl;
-       for (list<UndoAction>::iterator i = redo_actions.begin(); i != redo_actions.end(); ++i) {
-               (*i)();
-       }
+        (*this)();
+}
+
+XMLNode &UndoTransaction::get_state()
+{
+    XMLNode *node = new XMLNode ("UndoTransaction");
+
+    list<Command*>::iterator it;
+    for (it=actions.begin(); it!=actions.end(); it++)
+        node->add_child_nocopy((*it)->get_state());
+
+    return *node;
 }
 
 void
-UndoHistory::add (UndoCommand uc)
+UndoHistory::add (UndoTransaction ut)
 {
-       UndoList.push_back (uc);
+       UndoList.push_back (ut);
 }
 
 void
@@ -105,10 +108,10 @@ UndoHistory::undo (unsigned int n)
                if (UndoList.size() == 0) {
                        return;
                }
-               UndoCommand uc = UndoList.back ();
+               UndoTransaction ut = UndoList.back ();
                UndoList.pop_back ();
-               uc.undo ();
-               RedoList.push_back (uc);
+               ut.undo ();
+               RedoList.push_back (ut);
        }
 }
 
@@ -119,10 +122,10 @@ UndoHistory::redo (unsigned int n)
                if (RedoList.size() == 0) {
                        return;
                }
-               UndoCommand cmd = RedoList.back ();
+               UndoTransaction ut = RedoList.back ();
                RedoList.pop_back ();
-               cmd.redo ();
-               UndoList.push_back (cmd);
+               ut.redo ();
+               UndoList.push_back (ut);
        }
 }
 
@@ -144,3 +147,14 @@ UndoHistory::clear ()
        RedoList.clear ();
        UndoList.clear ();
 }
+
+XMLNode & UndoHistory::get_state()
+{
+    XMLNode *node = new XMLNode ("UndoHistory");
+
+    list<UndoTransaction>::iterator it;
+    for (it=UndoList.begin(); it != UndoList.end(); it++)
+        node->add_child_nocopy(it->get_state());
+
+    return *node;
+}
index 3dc93cc64ad980070886d6215a613b25a5288260..47401c8cfe896dd9974cc7405a004e8312d155c4 100644 (file)
@@ -145,6 +145,7 @@ void
 BasicUI::save_state ()
 {
        session->save_state ("");
+        session->save_history();
 }
 
 void