r269@gandalf: fugalh | 2006-08-03 20:18:05 -0600
authorHans Fugal <hans@fugal.net>
Fri, 4 Aug 2006 02:18:45 +0000 (02:18 +0000)
committerHans Fugal <hans@fugal.net>
Fri, 4 Aug 2006 02:18:45 +0000 (02:18 +0000)
 Trunk merge conflicts resolved

git-svn-id: svn://localhost/ardour2/branches/undo@756 d708f5d6-7413-0410-9779-e7cbd77b26cf

444 files changed:
SConstruct
ardour.dox
gtk2_ardour/SConscript
gtk2_ardour/actions.cc
gtk2_ardour/analysis_window.cc
gtk2_ardour/ardev_common.sh
gtk2_ardour/ardour.menus
gtk2_ardour/ardour2_ui.rc
gtk2_ardour/ardour_dialog.h
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui2.cc
gtk2_ardour/ardour_ui_dialogs.cc
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/audio_clock.h
gtk2_ardour/audio_region_editor.cc [new file with mode: 0644]
gtk2_ardour/audio_region_editor.h [new file with mode: 0644]
gtk2_ardour/audio_region_view.cc [new file with mode: 0644]
gtk2_ardour/audio_region_view.h [new file with mode: 0644]
gtk2_ardour/audio_regionview.cc [new file with mode: 0644]
gtk2_ardour/audio_streamview.cc [new file with mode: 0644]
gtk2_ardour/audio_streamview.h [new file with mode: 0644]
gtk2_ardour/audio_time_axis.cc
gtk2_ardour/audio_time_axis.h
gtk2_ardour/automation_time_axis.cc
gtk2_ardour/automation_time_axis.h
gtk2_ardour/canvas-waveview.h
gtk2_ardour/crossfade_edit.cc
gtk2_ardour/crossfade_view.cc
gtk2_ardour/crossfade_view.h
gtk2_ardour/editing_syms.h
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_actions.cc
gtk2_ardour/editor_audio_import.cc
gtk2_ardour/editor_audiotrack.cc
gtk2_ardour/editor_canvas.cc
gtk2_ardour/editor_canvas_events.cc
gtk2_ardour/editor_export_audio.cc
gtk2_ardour/editor_items.h
gtk2_ardour/editor_keyboard.cc
gtk2_ardour/editor_keys.cc
gtk2_ardour/editor_markers.cc
gtk2_ardour/editor_mixer.cc
gtk2_ardour/editor_mouse.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_route_list.cc
gtk2_ardour/editor_timefx.cc
gtk2_ardour/export_dialog.cc
gtk2_ardour/export_region_dialog.cc
gtk2_ardour/export_region_dialog.h
gtk2_ardour/fft_graph.cc
gtk2_ardour/fft_graph.h
gtk2_ardour/fft_result.cc
gtk2_ardour/gain_automation_time_axis.cc
gtk2_ardour/gain_automation_time_axis.h
gtk2_ardour/gain_meter.cc
gtk2_ardour/gain_meter.h
gtk2_ardour/io_selector.cc
gtk2_ardour/io_selector.h
gtk2_ardour/keyboard.h
gtk2_ardour/main.cc
gtk2_ardour/mixer_strip.cc
gtk2_ardour/mixer_strip.h
gtk2_ardour/mixer_ui.cc
gtk2_ardour/mixer_ui.h
gtk2_ardour/option_editor.cc
gtk2_ardour/option_editor.h
gtk2_ardour/pan_automation_time_axis.cc
gtk2_ardour/pan_automation_time_axis.h
gtk2_ardour/panner_ui.cc
gtk2_ardour/panner_ui.h
gtk2_ardour/pixmaps/tool_audition.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/tool_gain.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/tool_object.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/tool_range.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/tool_stretch.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/tool_zoom.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/zoom_full.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/zoom_in.xpm [new file with mode: 0644]
gtk2_ardour/pixmaps/zoom_out.xpm [new file with mode: 0644]
gtk2_ardour/playlist_selector.cc
gtk2_ardour/playlist_selector.h
gtk2_ardour/plugin_selector.cc
gtk2_ardour/plugin_selector.h
gtk2_ardour/plugin_ui.cc
gtk2_ardour/plugin_ui.h
gtk2_ardour/po/SConscript
gtk2_ardour/public_editor.h
gtk2_ardour/redirect_automation_line.cc
gtk2_ardour/redirect_automation_time_axis.cc
gtk2_ardour/redirect_automation_time_axis.h
gtk2_ardour/redirect_box.cc
gtk2_ardour/redirect_box.h
gtk2_ardour/redirect_selection.h
gtk2_ardour/region_editor.cc [deleted file]
gtk2_ardour/region_editor.h
gtk2_ardour/region_gain_line.cc
gtk2_ardour/region_selection.cc
gtk2_ardour/region_selection.h
gtk2_ardour/region_view.cc [new file with mode: 0644]
gtk2_ardour/region_view.h [new file with mode: 0644]
gtk2_ardour/regionview.cc [deleted file]
gtk2_ardour/regionview.h [deleted file]
gtk2_ardour/route_params_ui.cc
gtk2_ardour/route_params_ui.h
gtk2_ardour/route_redirect_selection.cc
gtk2_ardour/route_redirect_selection.h
gtk2_ardour/route_selection.h
gtk2_ardour/route_time_axis.cc [new file with mode: 0644]
gtk2_ardour/route_time_axis.h [new file with mode: 0644]
gtk2_ardour/route_ui.cc
gtk2_ardour/route_ui.h
gtk2_ardour/selectable.h
gtk2_ardour/selection.cc
gtk2_ardour/selection.h
gtk2_ardour/selection_templates.h
gtk2_ardour/send_ui.cc
gtk2_ardour/send_ui.h
gtk2_ardour/sfdb_ui.cc
gtk2_ardour/sfdb_ui.h
gtk2_ardour/streamview.cc
gtk2_ardour/streamview.h
gtk2_ardour/tape_region_view.cc [new file with mode: 0644]
gtk2_ardour/tape_region_view.h [new file with mode: 0644]
gtk2_ardour/taperegionview.cc [deleted file]
gtk2_ardour/taperegionview.h [deleted file]
gtk2_ardour/time_axis_view.cc
gtk2_ardour/time_axis_view.h
gtk2_ardour/time_axis_view_item.cc
gtk2_ardour/time_axis_view_item.h
gtk2_ardour/utils.cc
gtk2_ardour/visual_time_axis.cc
gtk2_ardour/visual_time_axis.h
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_diskstream.h
libs/ardour/ardour/audio_library.h
libs/ardour/ardour/audio_track.h
libs/ardour/ardour/audio_unit.h [new file with mode: 0644]
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/audiofilesource.h
libs/ardour/ardour/audioplaylist.h
libs/ardour/ardour/audioregion.h
libs/ardour/ardour/audiosource.h
libs/ardour/ardour/buffer.h [new file with mode: 0644]
libs/ardour/ardour/configuration.h
libs/ardour/ardour/connection.h
libs/ardour/ardour/control_protocol_manager.h
libs/ardour/ardour/curve.h
libs/ardour/ardour/data_type.h [new file with mode: 0644]
libs/ardour/ardour/destructive_filesource.h
libs/ardour/ardour/diskstream.h [new file with mode: 0644]
libs/ardour/ardour/export.h
libs/ardour/ardour/insert.h
libs/ardour/ardour/io.h
libs/ardour/ardour/ladspa_plugin.h
libs/ardour/ardour/location.h
libs/ardour/ardour/logcurve.h
libs/ardour/ardour/named_selection.h
libs/ardour/ardour/panner.h
libs/ardour/ardour/playlist.h
libs/ardour/ardour/plugin.h
libs/ardour/ardour/plugin_manager.h
libs/ardour/ardour/port.h
libs/ardour/ardour/redirect.h
libs/ardour/ardour/region.h
libs/ardour/ardour/route.h
libs/ardour/ardour/route_group.h
libs/ardour/ardour/route_group_specialized.h
libs/ardour/ardour/send.h
libs/ardour/ardour/session.h
libs/ardour/ardour/session_diskstream.h [deleted file]
libs/ardour/ardour/session_region.h
libs/ardour/ardour/session_route.h
libs/ardour/ardour/sndfilesource.h
libs/ardour/ardour/source.h
libs/ardour/ardour/stateful.h [deleted file]
libs/ardour/ardour/tempo.h
libs/ardour/ardour/track.h [new file with mode: 0644]
libs/ardour/ardour/types.h
libs/ardour/ardour/utils.h
libs/ardour/ardour/vst_plugin.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_library.cc
libs/ardour/audio_playlist.cc
libs/ardour/audio_track.cc
libs/ardour/audio_unit.cc [new file with mode: 0644]
libs/ardour/audioengine.cc
libs/ardour/audiofilesource.cc
libs/ardour/audioregion.cc
libs/ardour/audiosource.cc
libs/ardour/auditioner.cc
libs/ardour/automation_event.cc
libs/ardour/configuration.cc
libs/ardour/control_protocol_manager.cc
libs/ardour/coreaudiosource.cc
libs/ardour/crossfade.cc
libs/ardour/destructive_filesource.cc
libs/ardour/diskstream.cc [new file with mode: 0644]
libs/ardour/globals.cc
libs/ardour/insert.cc
libs/ardour/io.cc
libs/ardour/ladspa_plugin.cc
libs/ardour/location.cc
libs/ardour/mix.cc
libs/ardour/panner.cc
libs/ardour/playlist.cc
libs/ardour/plugin.cc
libs/ardour/plugin_manager.cc
libs/ardour/po/el_GR.po
libs/ardour/po/it_IT.po
libs/ardour/po/ru_RU.po
libs/ardour/port.cc
libs/ardour/redirect.cc
libs/ardour/region.cc
libs/ardour/route.cc
libs/ardour/session.cc
libs/ardour/session_butler.cc
libs/ardour/session_export.cc
libs/ardour/session_midi.cc
libs/ardour/session_process.cc
libs/ardour/session_state.cc
libs/ardour/session_time.cc
libs/ardour/session_transport.cc
libs/ardour/sndfilesource.cc
libs/ardour/source.cc
libs/ardour/stateful.cc [deleted file]
libs/ardour/track.cc [new file with mode: 0644]
libs/ardour/utils.cc
libs/ardour/vst_plugin.cc
libs/gtkmm2ext/SConscript
libs/gtkmm2ext/barcontroller.cc
libs/gtkmm2ext/binding_proxy.cc [new file with mode: 0644]
libs/gtkmm2ext/controller.cc [deleted file]
libs/gtkmm2ext/gtkmm2ext/barcontroller.h
libs/gtkmm2ext/gtkmm2ext/bindable_button.h
libs/gtkmm2ext/gtkmm2ext/binding_proxy.h [new file with mode: 0644]
libs/gtkmm2ext/gtkmm2ext/controller.h [deleted file]
libs/gtkmm2ext/gtkmm2ext/pathlist.h [new file with mode: 0644]
libs/gtkmm2ext/gtkmm2ext/slider_controller.h
libs/gtkmm2ext/pathlist.cc [new file with mode: 0644]
libs/gtkmm2ext/popup.cc
libs/gtkmm2ext/slider_controller.cc
libs/libgnomecanvasmm/SConscript
libs/libsndfile/src/sndfile.c
libs/midi++2/SConscript
libs/midi++2/midi++/channel.h
libs/midi++2/midi++/controllable.h [deleted file]
libs/midi++2/midi++/coremidi_midiport.h
libs/midi++2/midi++/factory.h
libs/midi++2/midi++/fd_midiport.h
libs/midi++2/midi++/fifomidi.h
libs/midi++2/midi++/manager.h
libs/midi++2/midi++/mmc.h
libs/midi++2/midi++/nullmidi.h
libs/midi++2/midi++/parser.h
libs/midi++2/midi++/port.h
libs/midi++2/midi++/port_request.h
libs/midi++2/midi++/types.h
libs/midi++2/midicontrollable.cc [deleted file]
libs/midi++2/midiparser.cc
libs/pbd/.cvsignore [new file with mode: 0644]
libs/pbd/AUTHORS [new file with mode: 0644]
libs/pbd/COPYING [new file with mode: 0644]
libs/pbd/ChangeLog [new file with mode: 0644]
libs/pbd/NEWS [new file with mode: 0644]
libs/pbd/README [new file with mode: 0644]
libs/pbd/SConscript [new file with mode: 0644]
libs/pbd/base_ui.cc [new file with mode: 0644]
libs/pbd/basename.cc [new file with mode: 0644]
libs/pbd/command.cc [new file with mode: 0644]
libs/pbd/controllable.cc [new file with mode: 0644]
libs/pbd/convert.cc [new file with mode: 0644]
libs/pbd/dmalloc.cc [new file with mode: 0644]
libs/pbd/error.cc [new file with mode: 0644]
libs/pbd/gettext.h [new file with mode: 0644]
libs/pbd/i18n.h [new file with mode: 0644]
libs/pbd/id.cc [new file with mode: 0644]
libs/pbd/libpbd.pc.in [new file with mode: 0644]
libs/pbd/libpbd.spec.in [new file with mode: 0644]
libs/pbd/mountpoint.cc [new file with mode: 0644]
libs/pbd/path.cc [new file with mode: 0644]
libs/pbd/pathscanner.cc [new file with mode: 0644]
libs/pbd/pbd/.DS_Store [new file with mode: 0644]
libs/pbd/pbd/.cvsignore [new file with mode: 0644]
libs/pbd/pbd/abstract_ui.cc [new file with mode: 0644]
libs/pbd/pbd/abstract_ui.h [new file with mode: 0644]
libs/pbd/pbd/base_ui.h [new file with mode: 0644]
libs/pbd/pbd/basename.h [new file with mode: 0644]
libs/pbd/pbd/command.h [new file with mode: 0644]
libs/pbd/pbd/compose.h [new file with mode: 0644]
libs/pbd/pbd/controllable.h [new file with mode: 0644]
libs/pbd/pbd/convert.h [new file with mode: 0644]
libs/pbd/pbd/error.h [new file with mode: 0644]
libs/pbd/pbd/failed_constructor.h [new file with mode: 0644]
libs/pbd/pbd/fastlog.h [new file with mode: 0644]
libs/pbd/pbd/forkexec.h [new file with mode: 0644]
libs/pbd/pbd/id.h [new file with mode: 0644]
libs/pbd/pbd/mathfix.h [new file with mode: 0644]
libs/pbd/pbd/memento_command.h [new file with mode: 0644]
libs/pbd/pbd/mountpoint.h [new file with mode: 0644]
libs/pbd/pbd/path.h [new file with mode: 0644]
libs/pbd/pbd/pathscanner.h [new file with mode: 0644]
libs/pbd/pbd/pool.h [new file with mode: 0644]
libs/pbd/pbd/pthread_utils.h [new file with mode: 0644]
libs/pbd/pbd/rcu.h [new file with mode: 0644]
libs/pbd/pbd/receiver.h [new file with mode: 0644]
libs/pbd/pbd/restartable_rw.h [new file with mode: 0644]
libs/pbd/pbd/ringbuffer.h [new file with mode: 0644]
libs/pbd/pbd/ringbufferNPT.h [new file with mode: 0644]
libs/pbd/pbd/selectable.h [new file with mode: 0644]
libs/pbd/pbd/serializable.h [new file with mode: 0644]
libs/pbd/pbd/stacktrace.h [new file with mode: 0644]
libs/pbd/pbd/stateful.h [new file with mode: 0644]
libs/pbd/pbd/stl_delete.h [new file with mode: 0644]
libs/pbd/pbd/stl_functors.h [new file with mode: 0644]
libs/pbd/pbd/strsplit.h [new file with mode: 0644]
libs/pbd/pbd/textreceiver.h [new file with mode: 0644]
libs/pbd/pbd/thrown_error.h [new file with mode: 0644]
libs/pbd/pbd/tokenizer.h [new file with mode: 0644]
libs/pbd/pbd/touchable.h [new file with mode: 0644]
libs/pbd/pbd/transmitter.h [new file with mode: 0644]
libs/pbd/pbd/undo.h [new file with mode: 0644]
libs/pbd/pbd/whitespace.h [new file with mode: 0644]
libs/pbd/pbd/xml++.h [new file with mode: 0644]
libs/pbd/pool.cc [new file with mode: 0644]
libs/pbd/pthread_utils.cc [new file with mode: 0644]
libs/pbd/receiver.cc [new file with mode: 0644]
libs/pbd/stacktrace.cc [new file with mode: 0644]
libs/pbd/stateful.cc [new file with mode: 0644]
libs/pbd/strsplit.cc [new file with mode: 0644]
libs/pbd/textreceiver.cc [new file with mode: 0644]
libs/pbd/transmitter.cc [new file with mode: 0644]
libs/pbd/undo.cc [new file with mode: 0644]
libs/pbd/whitespace.cc [new file with mode: 0644]
libs/pbd/xml++.cc [new file with mode: 0644]
libs/pbd3/.cvsignore [deleted file]
libs/pbd3/AUTHORS [deleted file]
libs/pbd3/COPYING [deleted file]
libs/pbd3/ChangeLog [deleted file]
libs/pbd3/NEWS [deleted file]
libs/pbd3/README [deleted file]
libs/pbd3/SConscript [deleted file]
libs/pbd3/base_ui.cc [deleted file]
libs/pbd3/basename.cc [deleted file]
libs/pbd3/command.cc [deleted file]
libs/pbd3/convert.cc [deleted file]
libs/pbd3/dmalloc.cc [deleted file]
libs/pbd3/error.cc [deleted file]
libs/pbd3/gettext.h [deleted file]
libs/pbd3/i18n.h [deleted file]
libs/pbd3/libpbd.pc.in [deleted file]
libs/pbd3/libpbd.spec.in [deleted file]
libs/pbd3/mountpoint.cc [deleted file]
libs/pbd3/pathscanner.cc [deleted file]
libs/pbd3/pbd/.DS_Store [deleted file]
libs/pbd3/pbd/.cvsignore [deleted file]
libs/pbd3/pbd/abstract_ui.cc [deleted file]
libs/pbd3/pbd/abstract_ui.h [deleted file]
libs/pbd3/pbd/base_ui.h [deleted file]
libs/pbd3/pbd/basename.h [deleted file]
libs/pbd3/pbd/command.h [deleted file]
libs/pbd3/pbd/compose.h [deleted file]
libs/pbd3/pbd/convert.h [deleted file]
libs/pbd3/pbd/error.h [deleted file]
libs/pbd3/pbd/failed_constructor.h [deleted file]
libs/pbd3/pbd/fastlog.h [deleted file]
libs/pbd3/pbd/forkexec.h [deleted file]
libs/pbd3/pbd/mathfix.h [deleted file]
libs/pbd3/pbd/memento_command.h [deleted file]
libs/pbd3/pbd/mountpoint.h [deleted file]
libs/pbd3/pbd/pathscanner.h [deleted file]
libs/pbd3/pbd/pool.h [deleted file]
libs/pbd3/pbd/pthread_utils.h [deleted file]
libs/pbd3/pbd/receiver.h [deleted file]
libs/pbd3/pbd/restartable_rw.h [deleted file]
libs/pbd3/pbd/ringbuffer.h [deleted file]
libs/pbd3/pbd/ringbufferNPT.h [deleted file]
libs/pbd3/pbd/selectable.h [deleted file]
libs/pbd3/pbd/serializable.h [deleted file]
libs/pbd3/pbd/stacktrace.h [deleted file]
libs/pbd3/pbd/stl_delete.h [deleted file]
libs/pbd3/pbd/stl_functors.h [deleted file]
libs/pbd3/pbd/strsplit.h [deleted file]
libs/pbd3/pbd/textreceiver.h [deleted file]
libs/pbd3/pbd/thrown_error.h [deleted file]
libs/pbd3/pbd/touchable.h [deleted file]
libs/pbd3/pbd/transmitter.h [deleted file]
libs/pbd3/pbd/undo.h [deleted file]
libs/pbd3/pbd/whitespace.h [deleted file]
libs/pbd3/pbd/xml++.h [deleted file]
libs/pbd3/pool.cc [deleted file]
libs/pbd3/pthread_utils.cc [deleted file]
libs/pbd3/receiver.cc [deleted file]
libs/pbd3/stacktrace.cc [deleted file]
libs/pbd3/strsplit.cc [deleted file]
libs/pbd3/textreceiver.cc [deleted file]
libs/pbd3/transmitter.cc [deleted file]
libs/pbd3/undo.cc [deleted file]
libs/pbd3/whitespace.cc [deleted file]
libs/pbd3/xml++.cc [deleted file]
libs/soundtouch/STTypes.h
libs/surfaces/control_protocol/SConscript
libs/surfaces/control_protocol/control_protocol.cc
libs/surfaces/control_protocol/control_protocol/control_protocol.h
libs/surfaces/generic_midi/SConscript
libs/surfaces/generic_midi/generic_midi_control_protocol.cc
libs/surfaces/generic_midi/generic_midi_control_protocol.h
libs/surfaces/generic_midi/interface.cc
libs/surfaces/generic_midi/midicontrollable.cc [new file with mode: 0644]
libs/surfaces/generic_midi/midicontrollable.h [new file with mode: 0644]
libs/surfaces/tranzport/SConscript
libs/surfaces/tranzport/tranzport_control_protocol.cc
libs/surfaces/tranzport/tranzport_control_protocol.h
tools/.cvsignore [deleted file]
tools/config.guess
tools/osx_packaging/ardour2_mac_ui.rc [new file with mode: 0644]
vst/SConscript

index 1dd250edfb5454bfd74a4f1c8da661bd0d4fc3da..e93aad96a85bfa18e938bb440f5522a614cb8a69 100644 (file)
@@ -31,6 +31,7 @@ opts.AddOptions(
     PathOption('DESTDIR', 'Set the intermediate install "prefix"', '/'),
     EnumOption('DIST_TARGET', 'Build target for cross compiling packagers', 'auto', allowed_values=('auto', 'i386', 'i686', 'x86_64', 'powerpc', 'tiger', 'panther', 'none' ), ignorecase=2),
     BoolOption('DMALLOC', 'Compile and link using the dmalloc library', 0),
+    BoolOption('EXTRA_WARN', 'Compile with -Wextra, -ansi, and -pedantic.  Might break compilation.  For pedants', 0),
     BoolOption('FFT_ANALYSIS', 'Include FFT analysis window', 0),
     BoolOption('FPU_OPTIMIZATION', 'Build runtime checked assembler code', 1),
     BoolOption('LIBLO', 'Compile with support for liblo library', 1),
@@ -50,18 +51,25 @@ opts.AddOptions(
 class LibraryInfo(Environment):
     def __init__(self,*args,**kw):
         Environment.__init__ (self,*args,**kw)
-        
+    
     def Merge (self,others):
         for other in others:
             self.Append (LIBS = other.get ('LIBS',[]))
-            self.Append (LIBPATH = other.get ('LIBPATH', []))  
+            self.Append (LIBPATH = other.get ('LIBPATH', []))
             self.Append (CPPPATH = other.get('CPPPATH', []))
             self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
        self.Replace(LIBPATH = list(Set(self.get('LIBPATH', []))))
        self.Replace(CPPPATH = list(Set(self.get('CPPPATH',[]))))
         #doing LINKFLAGS breaks -framework
         #doing LIBS break link order dependency
-
+    
+    def ENV_update(self, src_ENV):
+        for k in src_ENV.keys():
+            if k in self['ENV'].keys() and k in [ 'PATH', 'LD_LIBRARY_PATH',
+                                                  'LIB', 'INCLUDE' ]:
+                self['ENV'][k]=SCons.Util.AppendPath(self['ENV'][k], src_ENV[k])
+            else:
+                self['ENV'][k]=src_ENV[k]
 
 env = LibraryInfo (options = opts,
                    CPPPATH = [ '.' ],
@@ -72,68 +80,69 @@ env = LibraryInfo (options = opts,
                    DISTCHECKDIR = '#ardour-' + version + '/check'
                    )
 
+env.ENV_update(os.environ)
 
 #----------------------------------------------------------------------
 # Builders
 #----------------------------------------------------------------------
 
 # Handy subst-in-file builder
-# 
+#
 
 def do_subst_in_file(targetfile, sourcefile, dict):
-        """Replace all instances of the keys of dict with their values.
-        For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
-        then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
-        """
-        try:
-            f = open(sourcefile, 'rb')
-            contents = f.read()
-            f.close()
-        except:
-            raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
-        for (k,v) in dict.items():
-            contents = re.sub(k, v, contents)
-        try:
-            f = open(targetfile, 'wb')
-            f.write(contents)
-            f.close()
-        except:
-            raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
-        return 0 # success
+    """Replace all instances of the keys of dict with their values.
+    For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
+    then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
+    """
+    try:
+        f = open(sourcefile, 'rb')
+        contents = f.read()
+        f.close()
+    except:
+        raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
+    for (k,v) in dict.items():
+        contents = re.sub(k, v, contents)
+    try:
+        f = open(targetfile, 'wb')
+        f.write(contents)
+        f.close()
+    except:
+        raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
+    return 0 # success
+
 def subst_in_file(target, source, env):
-        if not env.has_key('SUBST_DICT'):
-            raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
-        d = dict(env['SUBST_DICT']) # copy it
-        for (k,v) in d.items():
-            if callable(v):
-                d[k] = env.subst(v())
-            elif SCons.Util.is_String(v):
-                d[k]=env.subst(v)
-            else:
-                raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
-        for (t,s) in zip(target, source):
-            return do_subst_in_file(str(t), str(s), d)
+    if not env.has_key('SUBST_DICT'):
+        raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
+    d = dict(env['SUBST_DICT']) # copy it
+    for (k,v) in d.items():
+        if callable(v):
+            d[k] = env.subst(v())
+        elif SCons.Util.is_String(v):
+            d[k]=env.subst(v)
+        else:
+            raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
+    for (t,s) in zip(target, source):
+        return do_subst_in_file(str(t), str(s), d)
+
 def subst_in_file_string(target, source, env):
-        """This is what gets printed on the console."""
-        return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
-                          for (t,s) in zip(target, source)])
+    """This is what gets printed on the console."""
+    return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
+                      for (t,s) in zip(target, source)])
+
 def subst_emitter(target, source, env):
-        """Add dependency from substituted SUBST_DICT to target.
-        Returns original target, source tuple unchanged.
-        """
-        d = env['SUBST_DICT'].copy() # copy it
-        for (k,v) in d.items():
-            if callable(v):
-                d[k] = env.subst(v())
-            elif SCons.Util.is_String(v):
-                d[k]=env.subst(v)
-        Depends(target, SCons.Node.Python.Value(d))
-        # Depends(target, source) # this doesn't help the install-sapphire-linux.sh problem
-        return target, source
+    """Add dependency from substituted SUBST_DICT to target.
+    Returns original target, source tuple unchanged.
+    """
+    d = env['SUBST_DICT'].copy() # copy it
+    for (k,v) in d.items():
+        if callable(v):
+            d[k] = env.subst(v())
+        elif SCons.Util.is_String(v):
+            d[k]=env.subst(v)
+    Depends(target, SCons.Node.Python.Value(d))
+    # Depends(target, source) # this doesn't help the install-sapphire-linux.sh problem
+    return target, source
+
 subst_action = Action (subst_in_file, subst_in_file_string)
 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
 
@@ -141,31 +150,31 @@ env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emit
 # internationalization
 #
 
-# po_helper
+# po_builder: builder function to copy po files to the parent directory while updating them
 #
-# this is not a builder. we can't list the .po files as a target,
-# because then scons -c will remove them (even Precious doesn't alter
-# this). this function is called whenever a .mo file is being
-# built, and will conditionally update the .po file if necessary.
+# first source:  .po file
+# second source: .pot file
 #
 
-def po_helper(po,pot):
+def po_builder(target,source,env):
+    os.spawnvp (os.P_WAIT, 'cp', ['cp', str(source[0]), str(target[0])])
     args = [ 'msgmerge',
              '--update',
-             po,
-             pot,
+             str(target[0]),
+             str(source[1])
              ]
-    print 'Updating ' + po
+    print 'Updating ' + str(target[0])
     return os.spawnvp (os.P_WAIT, 'msgmerge', args)
 
+po_bld = Builder (action = po_builder)
+env.Append(BUILDERS = {'PoBuild' : po_bld})
+
 # mo_builder: builder function for (binary) message catalogs (.mo)
 #
 # first source:  .po file
-# second source: .pot file
 #
 
 def mo_builder(target,source,env):
-    po_helper (source[0].get_path(), source[1].get_path())
     args = [ 'msgfmt',
              '-c',
              '-o',
@@ -183,15 +192,15 @@ env.Append(BUILDERS = {'MoBuild' : mo_bld})
 #
 
 def pot_builder(target,source,env):
-    args = [ 'xgettext', 
+    args = [ 'xgettext',
              '--keyword=_',
              '--keyword=N_',
              '--from-code=UTF-8',
-             '-o', target[0].get_path(), 
+             '-o', target[0].get_path(),
              "--default-domain=" + env['PACKAGE'],
              '--copyright-holder="Paul Davis"' ]
     args += [ src.get_path() for src in source ]
-
+    
     return os.spawnvp (os.P_WAIT, 'xgettext', args)
 
 pot_bld = Builder (action = pot_builder)
@@ -204,33 +213,33 @@ env.Append(BUILDERS = {'PotBuild' : pot_bld})
 def i18n (buildenv, sources, installenv):
     domain = buildenv['PACKAGE']
     potfile = buildenv['POTFILE']
-
+    
     installenv.Alias ('potupdate', buildenv.PotBuild (potfile, sources))
-
+    
     p_oze = [ os.path.basename (po) for po in glob.glob ('po/*.po') ]
     languages = [ po.replace ('.po', '') for po in p_oze ]
-    m_oze = [ po.replace (".po", ".mo") for po in p_oze ]
     
-    for mo in m_oze[:]:
-        po = 'po/' + mo.replace (".mo", ".po")
-        installenv.Alias ('install', buildenv.MoBuild (mo, [ po, potfile ]))
-        
-    for lang in languages[:]:
+    for po_file in p_oze:
+        buildenv.PoBuild(po_file, ['po/'+po_file, potfile])
+        mo_file = po_file.replace (".po", ".mo")
+        installenv.Alias ('install', buildenv.MoBuild (mo_file, po_file))
+    
+    for lang in languages:
         modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/'))
         moname = domain + '.mo'
         installenv.Alias('install', installenv.InstallAs (os.path.join (modir, moname), lang + '.mo'))
 
 #
 # A generic builder for version.cc files
-# 
+#
 # note: requires that DOMAIN, MAJOR, MINOR, MICRO are set in the construction environment
 # note: assumes one source files, the header that declares the version variables
-# 
+#
 def version_builder (target, source, env):
    text  = "int " + env['DOMAIN'] + "_major_version = " + str (env['MAJOR']) + ";\n"
    text += "int " + env['DOMAIN'] + "_minor_version = " + str (env['MINOR']) + ";\n"
    text += "int " + env['DOMAIN'] + "_micro_version = " + str (env['MICRO']) + ";\n"
-
+   
    try:
       o = file (target[0].get_path(), 'w')
       o.write (text)
@@ -238,14 +247,14 @@ def version_builder (target, source, env):
    except IOError:
       print "Could not open", target[0].get_path(), " for writing\n"
       sys.exit (-1)
-
+   
    text  = "#ifndef __" + env['DOMAIN'] + "_version_h__\n"
    text += "#define __" + env['DOMAIN'] + "_version_h__\n"
    text += "extern int " + env['DOMAIN'] + "_major_version;\n"
    text += "extern int " + env['DOMAIN'] + "_minor_version;\n"
    text += "extern int " + env['DOMAIN'] + "_micro_version;\n"
    text += "#endif /* __" + env['DOMAIN'] + "_version_h__ */\n"
-
+   
    try:
       o = file (target[1].get_path(), 'w')
       o.write (text)
@@ -253,7 +262,7 @@ def version_builder (target, source, env):
    except IOError:
       print "Could not open", target[1].get_path(), " for writing\n"
       sys.exit (-1)
-  
+   
    return None
 
 version_bld = Builder (action = version_builder)
@@ -276,8 +285,8 @@ def versioned_builder(target,source,env):
     except IOError:
         print "Could not CVS/Entries for reading"
         return -1
-
-    last_date = ""        
+    
+    last_date = ""
     lines = o.readlines()
     for line in lines:
         if line[0:12] == '/SConscript/':
@@ -285,20 +294,20 @@ def versioned_builder(target,source,env):
             last_date = parts[3]
             break
     o.close ()
-
+    
     if last_date == "":
         print "No SConscript CVS update info found - versioned executable cannot be built"
         return -1
-
+    
     tag = time.strftime ('%Y%M%d%H%m', time.strptime (last_date))
     print "The current build ID is " + tag
-
+    
     tagged_executable = source[0].get_path() + '-' + tag
-
+    
     if os.path.exists (tagged_executable):
         print "Replacing existing executable with the same build tag."
         os.unlink (tagged_executable)
-
+    
     return os.link (source[0].get_path(), tagged_executable)
 
 verbuild = Builder (action = versioned_builder)
@@ -310,13 +319,13 @@ env.Append (BUILDERS = {'VersionedExecutable' : verbuild})
 
 def distcopy (target, source, env):
     treedir = str (target[0])
-
+    
     try:
         os.mkdir (treedir)
     except OSError, (errnum, strerror):
         if errnum != errno.EEXIST:
             print 'mkdir ', treedir, ':', strerror
-
+    
     cmd = 'tar cf - '
     #
     # we don't know what characters might be in the file names
@@ -328,7 +337,7 @@ def distcopy (target, source, env):
     p = os.popen (cmd)
     return p.close ()
 
-def tarballer (target, source, env):            
+def tarballer (target, source, env):
     cmd = 'tar -jcf ' + str (target[0]) +  ' ' + str(source[0]) + "  --exclude '*~'"
     print 'running ', cmd, ' ... '
     p = os.popen (cmd)
@@ -359,7 +368,7 @@ if env['VST']:
         env['VST'] = 0;
     else:
         print "OK, VST support will be enabled"
-        
+
 
 # ----------------------------------------------------------------------
 # Construction environment setup
@@ -381,7 +390,7 @@ libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
 libraries['samplerate'] = LibraryInfo()
 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
 
-if env['FFT_ANALYSIS']: 
+if env['FFT_ANALYSIS']:
        libraries['fftw3f'] = LibraryInfo()
        libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
 
@@ -420,9 +429,8 @@ libraries['ardour_cp'] = LibraryInfo (LIBS='ardour_cp', LIBPATH='#libs/surfaces/
 
 libraries['ardour'] = LibraryInfo (LIBS='ardour', LIBPATH='#libs/ardour', CPPPATH='#libs/ardour')
 libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
-libraries['pbd3']    = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd3', CPPPATH='#libs/pbd3')
+libraries['pbd']    = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd', CPPPATH='#libs/pbd')
 libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
-#libraries['cassowary'] = LibraryInfo(LIBS='cassowary', LIBPATH='#libs/cassowary', CPPPATH='#libs/cassowary')
 
 #
 # Check for libusb
@@ -434,7 +442,7 @@ if conf.CheckLib ('usb', 'usb_interrupt_write'):
     have_libusb = True
 else:
     have_libusb = False
-    
+
 libraries['usb'] = conf.Finish ()
 
 #
@@ -443,7 +451,7 @@ libraries['usb'] = conf.Finish ()
 libraries['flac'] = LibraryInfo ()
 
 conf = Configure (libraries['flac'])
-conf.CheckLib ('FLAC', 'FLAC__stream_decoder_new')
+conf.CheckLib ('FLAC', 'FLAC__stream_decoder_new', language='CXX')
 libraries['flac'] = conf.Finish ()
 
 #
@@ -451,7 +459,7 @@ libraries['flac'] = conf.Finish ()
 
 if env['LIBLO']:
     libraries['lo'] = LibraryInfo ()
-
+    
     conf = Configure (libraries['lo'])
     if conf.CheckLib ('lo', 'lo_server_new') == False:
         print "liblo does not appear to be installed."
@@ -473,14 +481,14 @@ if conf.CheckLib ('dmallocth', 'dmalloc_shutdown'):
     have_libdmalloc = True
 else:
     have_libdmalloc = False
-    
+
 libraries['dmalloc'] = conf.Finish ()
 
 #
 
 #
 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
-# 
+#
 
 conf = Configure(env)
 
@@ -498,11 +506,11 @@ elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/Co
 else:
     print "It appears you don't have the required MIDI libraries installed."
     sys.exit (1)
-        
+
 env = conf.Finish()
 
 if env['SYSLIBS']:
-
+    
     libraries['sigc2'] = LibraryInfo()
     libraries['sigc2'].ParseConfig('pkg-config --cflags --libs sigc++-2.0')
     libraries['glibmm2'] = LibraryInfo()
@@ -521,7 +529,7 @@ if env['SYSLIBS']:
 #
 # cannot use system one for the time being
 #
-
+    
     libraries['sndfile'] = LibraryInfo(LIBS='libsndfile',
                                     LIBPATH='#libs/libsndfile',
                                     CPPPATH=['#libs/libsndfile', '#libs/libsndfile/src'])
@@ -531,22 +539,29 @@ if env['SYSLIBS']:
 
 #    libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
     libraries['soundtouch'] = LibraryInfo()
-    libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
+    libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
 
+    libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
+                                            LIBPATH='#libs/appleutility',
+                                            CPPPATH='#libs/appleutility')
+    
     coredirs = [
         'templates'
     ]
-
+    
     subdirs = [
         'libs/libsndfile',
-        'libs/pbd3',
+        'libs/pbd',
         'libs/midi++2',
         'libs/ardour'
         ]
-
+    
     if env['VST']:
         subdirs = ['libs/fst'] + subdirs + ['vst']
 
+    if env['COREAUDIO']:
+        subdirs = subdirs + ['libs/appleutility']
+    
     gtk_subdirs = [
 #        'libs/flowcanvas',
         'libs/gtkmm2ext',
@@ -575,7 +590,7 @@ else:
     libraries['libgnomecanvasmm'] = LibraryInfo(LIBS='libgnomecanvasmm',
                                                 LIBPATH='#libs/libgnomecanvasmm',
                                                 CPPPATH='#libs/libgnomecanvasmm')
-
+    
     libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
                                           LIBPATH='#libs/soundtouch',
                                           CPPPATH=['#libs', '#libs/soundtouch'])
@@ -585,24 +600,29 @@ 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'
     ]
-
+    
     subdirs = [
-#          'libs/cassowary',
         'libs/sigc++2',
         'libs/libsndfile',
-        'libs/pbd3',
+        'libs/pbd',
         'libs/midi++2',
         'libs/ardour'
         ]
-
+    
     if env['VST']:
         subdirs = ['libs/fst'] + subdirs + ['vst']
 
+    if env['COREAUDIO']:
+        subdirs = subdirs + ['libs/appleutility']
+    
     gtk_subdirs = [
        'libs/glibmm2',
        'libs/gtkmm2/pango',
@@ -627,7 +647,7 @@ if env['SURFACES']:
         surface_subdirs += [ 'libs/surfaces/tranzport' ]
     if os.access ('libs/surfaces/sony9pin', os.F_OK):
         surface_subdirs += [ 'libs/surfaces/sony9pin' ]
-    
+
 opts.Save('scache.conf', env)
 Help(opts.GenerateHelpText(env))
 
@@ -646,7 +666,7 @@ if os.environ.has_key('CXX'):
 if os.environ.has_key('DISTCC_HOSTS'):
     env['ENV']['DISTCC_HOSTS'] = os.environ['DISTCC_HOSTS']
     env['ENV']['HOME'] = os.environ['HOME']
-    
+
 final_prefix = '$PREFIX'
 install_prefix = '$DESTDIR/$PREFIX'
 
@@ -670,7 +690,7 @@ if have_cxx[0] != 1:
     exit (1)
 else:
     print "Congratulations, you have a functioning C++ compiler."
-    
+
 env = conf.Finish()
 
 #
@@ -724,37 +744,37 @@ if config[config_cpu] == 'powerpc' and env['DIST_TARGET'] != 'none':
         if config[config_arch] == 'apple':
             opt_flags.extend ([ "-mcpu=7450", "-faltivec"])
         else:
-            opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"]) 
+            opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"])
     else:
         opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
     opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
 
 elif ((re.search ("i[0-9]86", config[config_cpu]) != None) or (re.search ("x86_64", config[config_cpu]) != None)) and env['DIST_TARGET'] != 'none':
-
+    
     build_host_supports_sse = 0
     
     debug_flags.append ("-DARCH_X86")
     opt_flags.append ("-DARCH_X86")
-
+    
     if config[config_kernel] == 'linux' :
-
-        if env['DIST_TARGET'] != 'i386': 
-
+        
+        if env['DIST_TARGET'] != 'i386':
+            
             flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
             x86_flags = flag_line.split (": ")[1:][0].split (' ')
-
+            
             if "mmx" in x86_flags:
                 opt_flags.append ("-mmmx")
             if "sse" in x86_flags:
                 build_host_supports_sse = 1
             if "3dnow" in x86_flags:
                 opt_flags.append ("-m3dnow")
-
+            
             if config[config_cpu] == "i586":
                 opt_flags.append ("-march=i586")
             elif config[config_cpu] == "i686":
                 opt_flags.append ("-march=i686")
-
+    
     if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) and build_host_supports_sse:
         opt_flags.extend (["-msse", "-mfpmath=sse"])
         debug_flags.extend (["-msse", "-mfpmath=sse"])
@@ -783,7 +803,7 @@ env.Append(CONFIG_ARCH=config[config_arch])
 
 
 #
-# ARCH="..." overrides all 
+# ARCH="..." overrides all
 #
 
 if env['ARCH'] != '':
@@ -812,6 +832,10 @@ else:
 env.Append(CCFLAGS="-Wall")
 env.Append(CXXFLAGS="-Woverloaded-virtual")
 
+if env['EXTRA_WARN']:
+    env.Append(CCFLAGS="-Wextra -pedantic")
+    env.Append(CXXFLAGS="-ansi")
+
 if env['LIBLO']:
     env.Append(CCFLAGS="-DHAVE_LIBLO")
 
@@ -822,34 +846,47 @@ if env['LIBLO']:
 env.Merge ([ libraries['core'] ])
 
 #
-# i18n support 
+# fix scons nitpickiness on APPLE
 #
 
-conf = Configure (env)
+if env['DIST_TARGET'] == 'panther' or env['DIST_TARGET'] == 'tiger':
+    env.Append(CCFLAGS="-I/opt/local/include", LINKFLAGS="-L/opt/local/lib")
 
+#
+# i18n support
+#
+
+conf = Configure (env)
 if env['NLS']:
+    nls_error = 'This system is not configured for internationalized applications.  An english-only version will be built:'
     print 'Checking for internationalization support ...'
     have_gettext = conf.TryAction(Action('xgettext --version'))
     if have_gettext[0] != 1:
-        print 'This system is not configured for internationalized applications (no xgettext command). An english-only version will be built\n'
+        nls_error += ' No xgettext command.'
         env['NLS'] = 0
-        
-    if conf.CheckCHeader('libintl.h') == None:
-        print 'This system is not configured for internationalized applications (no libintl.h). An english-only version will be built\n'
-        env['NLS'] = 0
-
-    have_intltool = conf.TryAction(Action('intltool-update --version'))
-    if have_intltool[0] != 1:
-        print 'This system is not configured for internationalized applications (no intltool-update command). An english-only version will be built\n'
+    else:
+        print "Found xgettext"
+    
+    have_msgmerge = conf.TryAction(Action('msgmerge --version'))
+    if have_msgmerge[0] != 1:
+        nls_error += ' No msgmerge command.'
         env['NLS'] = 0
+    else:
+        print "Found msgmerge"
     
-
+    if not conf.CheckCHeader('libintl.h'):
+        nls_error += ' No libintl.h.'
+        env['NLS'] = 0
+        
+    if env['NLS'] == 0:
+        print nls_error
+    else:
+        print "International version will be built."
 env = conf.Finish()
 
 if env['NLS'] == 1:
     env.Append(CCFLAGS="-DENABLE_NLS")
 
-
 Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n version subst_dict')
 
 #
@@ -903,18 +940,18 @@ env.Distribute (env['DISTTREE'],
                 glob.glob ('DOCUMENTATION/FAQ*') +
                 glob.glob ('DOCUMENTATION/README*')
                 )
-                
+
 srcdist = env.Tarball(env['TARBALL'], env['DISTTREE'])
 env.Alias ('srctar', srcdist)
 #
-# don't leave the distree around 
+# don't leave the distree around
 #
 env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
 env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
 
 #
 # the subdirs
-# 
+#
 
 for subdir in coredirs:
     SConscript (subdir + '/SConscript')
@@ -922,7 +959,7 @@ for subdir in coredirs:
 for sublistdir in [ subdirs, gtk_subdirs, surface_subdirs ]:
     for subdir in sublistdir:
         SConscript (subdir + '/SConscript')
-            
+
 # cleanup
 env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
 
index 8bd87d6fa300e253d3e02491ba5560c10629299f..a72ecbc5889c4cf0a9245c19a91230b6cf0a108d 100644 (file)
@@ -459,7 +459,7 @@ WARN_LOGFILE           =
 # directories like "/usr/src/myproject". Separate the files or directories 
 # with spaces.
 
-INPUT                  = libs/pbd3 libs/midi++2 libs/ardour libs/gtkmm2ext gtk2_ardour
+INPUT                  = libs/pbd libs/midi++2 libs/ardour libs/gtkmm2ext gtk2_ardour
 
 # If the value of the INPUT tag contains directories, you can use the 
 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
index 65f8dfca732bb618ee8297bd6b539ec1d06d8902..d004c9c4c65ef64a763d807e25f6f5eebd20eb9c 100644 (file)
@@ -27,7 +27,7 @@ gtkardour.Merge ([
     libraries['ardour_cp'],
     libraries['gtkmm2ext'],
     libraries['midi++2'],
-    libraries['pbd3'],
+    libraries['pbd'],
     libraries['gtkmm2'],
     libraries['glib2'],
     libraries['libgnomecanvas2'],
@@ -57,6 +57,10 @@ if gtkardour['FFT_ANALYSIS']:
        gtkardour.Merge ([libraries['fftw3f']])
        gtkardour.Append(CCFLAGS='-DFFT_ANALYSIS')
 
+if gtkardour['COREAUDIO']:
+       gtkardour.Append(CCFLAGS='-DHAVE_COREAUDIO')
+       gtkardour.Merge([libraries['appleutility']])
+
 skipped_files=Split("""
 connection_editor.cc
 """)
@@ -75,6 +79,7 @@ ardour_ui_ed.cc
 ardour_ui_mixer.cc
 ardour_ui_options.cc
 audio_clock.cc
+route_time_axis.cc
 audio_time_axis.cc
 automation_gain_line.cc
 automation_line.cc
@@ -141,8 +146,6 @@ marker.cc
 marker_time_axis.cc
 marker_time_axis_view.cc
 marker_view.cc
-meter_bridge.cc
-meter_bridge_strip.cc
 mixer_strip.cc
 mixer_ui.cc
 new_session_dialog.cc
@@ -159,10 +162,11 @@ public_editor.cc
 redirect_automation_line.cc
 redirect_automation_time_axis.cc
 redirect_box.cc
-region_editor.cc
+audio_region_editor.cc
 region_gain_line.cc
 region_selection.cc
-regionview.cc
+region_view.cc
+audio_region_view.cc
 route_params_ui.cc
 route_redirect_selection.cc
 route_ui.cc
@@ -170,7 +174,8 @@ selection.cc
 sfdb_ui.cc
 send_ui.cc
 streamview.cc
-taperegionview.cc
+audio_streamview.cc
+tape_region_view.cc
 tempo_dialog.cc
 time_axis_view.cc
 time_axis_view_item.cc
@@ -255,8 +260,7 @@ else:
        env.Alias('install', env.InstallAs(os.path.join(install_prefix, 'bin')+'/ardour2', ardoursh))
 
 if env['NLS']:
-        Export('gtkardour', 'intl_files')
-       SConscript ('po/SConscript')
+       i18n (gtkardour, gtkardour_files+skipped_files+fft_analysis_files, env)
     
 # configuration files
 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour2_ui.rc'))
index ee688c366006d72e710e15e5769d053523761311..2197d4dc005174b19d41d78727c2ca0699bfacd5 100644 (file)
@@ -19,7 +19,7 @@
 */
 
 #include <vector>
-#include <string.h>
+#include <string>
 
 #include <gtk/gtkaccelmap.h>
 #include <gtk/gtkuimanager.h>
index b8318f45feae0b3967bc444a67e2aa4c207ad2c3..f742afd7274a9a66ee901236919c3962e75d198c 100644 (file)
@@ -26,7 +26,7 @@
 #include <gtkmm/treeiter.h>
 
 #include <ardour/audioregion.h>
-#include <ardour/playlist.h>
+#include <ardour/audioplaylist.h>
 #include <ardour/types.h>
 
 #include "analysis_window.h"
@@ -35,7 +35,7 @@
 #include "time_axis_view.h"
 #include "public_editor.h"
 #include "selection.h"
-#include "regionview.h"
+#include "audio_region_view.h"
 
 #include "i18n.h"
 
@@ -45,16 +45,15 @@ using namespace PBD;
 AnalysisWindow::AnalysisWindow()
        : ArdourDialog(_("analysis window")),
        
-         fft_graph (2048),
-       
          source_selection_label       (_("Signal source")),
          source_selection_ranges_rb   (_("Selected ranges")),
          source_selection_regions_rb  (_("Selected regions")),
-         
+       
          display_model_label                   (_("Display model")),
          display_model_composite_separate_rb   (_("Composite graphs for each track")),
-         display_model_composite_all_tracks_rb (_("Composite graph of all tracks"))
+         display_model_composite_all_tracks_rb (_("Composite graph of all tracks")),
 
+         fft_graph (2048)
 {
        track_list_ready = false;
        
@@ -226,18 +225,23 @@ AnalysisWindow::analyze_data (Gtk::Button *button)
        
                Selection s = PublicEditor::instance().get_selection();
                TimeSelection ts = s.time;
-               AudioRegionSelection ars = s.audio_regions;
+               RegionSelection ars = s.regions;
        
        
                for (TrackSelection::iterator i = s.tracks.begin(); i != s.tracks.end(); ++i) {
-                       ARDOUR::Playlist *pl = (*i)->playlist();
+                       ARDOUR::AudioPlaylist *pl
+                               = dynamic_cast<ARDOUR::AudioPlaylist*>((*i)->playlist());
+
+                       if (!pl)
+                               continue;
+
                        RouteUI *rui = dynamic_cast<RouteUI *>(*i);
                        
                        // Busses don't have playlists, so we need to check that we actually are working with a playlist
                        if (!pl || !rui)
                                continue;
 
-                       FFTResult *res = fft_graph.prepareResult(*&rui->color(), *&rui->route().name());
+                       FFTResult *res = fft_graph.prepareResult(rui->color(), rui->route()->name());
                
                        // if timeSelection
                        if (source_selection_ranges_rb.get_active()) {
@@ -275,24 +279,29 @@ AnalysisWindow::analyze_data (Gtk::Button *button)
                                
                                TimeAxisView *current_axis = (*i);
                                
-                               for (std::set<AudioRegionView *>::iterator j = ars.begin(); j != ars.end(); ++j) {
+                               for (std::set<RegionView *>::iterator j = ars.begin(); j != ars.end(); ++j) {
+                                       // Check that the region is actually audio (so we can analyze it)
+                                       AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*j);
+                                       if (!arv)
+                                               continue;
+                                       
                                        // Check that the region really is selected on _this_ track/solo
-                                       if ( &(*j)->get_time_axis_view() != current_axis)
+                                       if ( &arv->get_time_axis_view() != current_axis)
                                                continue;
 
-//                                     cerr << " - " << (*j)->region.name() << ": " << (*j)->region.length() << " samples starting at " << (*j)->region.position() << endl;
+//                                     cerr << " - " << (*j)->region().name() << ": " << (*j)->region().length() << " samples starting at " << (*j)->region().position() << endl;
                                        jack_nframes_t i = 0;
                                        int n;
 
-                                       while ( i < (*j)->region.length() ) {
+                                       while ( i < arv->region().length() ) {
                                                // TODO: What about stereo+ channels? composite all to one, I guess
 
                                                n = fft_graph.windowSize();
-                                               if (i + n >= (*j)->region.length() ) {
-                                                       n = (*j)->region.length() - i;
+                                               if (i + n >= arv->region().length() ) {
+                                                       n = arv->region().length() - i;
                                                }
-                               
-                                               n = (*j)->region.read_at(buf, mixbuf, gain, work, (*j)->region.position() + i, n);
+
+                                               n = arv->audio_region().read_at(buf, mixbuf, gain, work, arv->region().position() + i, n);
        
                                                if ( n < fft_graph.windowSize()) {
                                                        for (int j = n; j < fft_graph.windowSize(); j++) {
@@ -313,9 +322,9 @@ AnalysisWindow::analyze_data (Gtk::Button *button)
 
                                
                        Gtk::TreeModel::Row newrow = *(tlmodel)->append();
-                       newrow[tlcols.trackname]   = rui->route().name();
+                       newrow[tlcols.trackname]   = rui->route()->name();
                        newrow[tlcols.visible]     = true;
-                       newrow[tlcols.color]       = *&rui->color();
+                       newrow[tlcols.color]       = rui->color();
                        newrow[tlcols.graph]       = res;
                }       
 
index 5c68933a963f1443de292f4009b1be4c85693867..bf644f3e845d91ab2fd95cb679a700d496c0e355 100755 (executable)
@@ -2,7 +2,10 @@
 
 export ARDOUR_PATH=./glade:./pixmaps:.
 
-export LD_LIBRARY_PATH=../libs/surfaces/control_protocol:../libs/ardour:../libs/midi++2:../libs/pbd3:../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
+
+# LADSPA_PATH for OSX
+export LADSPA_PATH=$LADSPA_PATH:/Library/Audio/Plug-Ins/LADSPA
index 9293883067040bd2beb789c22ec272f2e6b3f734..b1064b8e8718241f558f762e7a812b64d67019c3 100644 (file)
            <separator/>
            <menu action='addExistingAudioFiles'>
               <menuitem action='addExternalAudioAsRegion'/>           
-              <menuitem action='addExternalAudioAsTrack'/>            
               <menuitem action='addExternalAudioToTrack'/>            
+               <separator/>
+              <menuitem action='addExternalAudioAsTrack'/>            
+              <menuitem action='addExternalAudioAsTapeTrack'/>        
            </menu>
            <separator/>
            <menu name='Export' action='Export'>
index ac4f055df6ffb812da0291c6c5de4fc4db1e32f6..5422a63b8bc37dc1e5ee5c0b9b68509fe18f5da0 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"
@@ -936,6 +944,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 a23dcda9e0000d718e3903ed716fe0028623eb00..069768c1436b245e66cc69f6cf15f9bfadd77d61 100644 (file)
@@ -26,7 +26,7 @@
 
 namespace ARDOUR {
        class Session;
-};
+}
 
 /*
  * This virtual parent class is so that each dialog box uses the
@@ -55,3 +55,4 @@ class ArdourDialog : public Gtk::Dialog
 };
 
 #endif // __ardour_dialog_h__
+
index f452ec9c7ea3a96e133637dfdd70f63ac2f26acf..e5367d6280f633b88ec6d707e0c66cf142005c27 100644 (file)
@@ -46,6 +46,7 @@
 #include <midi++/mmc.h>
 
 #include <ardour/ardour.h>
+#include <ardour/session_route.h>
 #include <ardour/port.h>
 #include <ardour/audioengine.h>
 #include <ardour/playlist.h>
@@ -53,7 +54,6 @@
 #include <ardour/audio_diskstream.h>
 #include <ardour/audiofilesource.h>
 #include <ardour/recent_sessions.h>
-#include <ardour/session_diskstream.h>
 #include <ardour/port.h>
 #include <ardour/audio_track.h>
 
@@ -116,16 +116,15 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
 
          shuttle_units_button (_("% ")),
 
-         punch_in_button (_("punch\nin")),
-         punch_out_button (_("punch\nout")),
-         auto_return_button (_("auto\nreturn")),
-         auto_play_button (_("auto\nplay")),
-         auto_input_button (_("auto\ninput")),
-         click_button (_("click")),
-         auditioning_alert_button (_("AUDITIONING")),
+         punch_in_button (_("Punch In")),
+         punch_out_button (_("Punch Out")),
+         auto_return_button (_("Auto Return")),
+         auto_play_button (_("Autuo Play")),
+         auto_input_button (_("Auto Input")),
+         click_button (_("Click")),
+         auditioning_alert_button (_("AUDITION")),
          solo_alert_button (_("SOLO")),
          shown_flag (false)
-
 {
        using namespace Gtk::Menu_Helpers;
 
@@ -186,8 +185,8 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
        gettimeofday (&last_shuttle_request, 0);
 
        ARDOUR::AudioDiskstream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
-       ARDOUR::AudioDiskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
-       ARDOUR::AudioDiskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
+       ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
+       ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
 
        /* handle pending state with a dialog */
 
@@ -339,15 +338,15 @@ ARDOUR_UI::save_ardour_state ()
        Config->add_extra_xml (*node);
        Config->save_state();
 
-       XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
-       XMLNode& mnode (mixer->get_state());
+       XMLNode enode(static_cast<Stateful*>(editor)->get_state());
+       XMLNode mnode(mixer->get_state());
 
        if (session) {
-               session->add_instant_xml(enode, session->path());
-               session->add_instant_xml(mnode, session->path());
+               session->add_instant_xml (enode, session->path());
+               session->add_instant_xml (mnode, session->path());
        } else {
-               Config->add_instant_xml(enode, get_user_ardour_path());
-               Config->add_instant_xml(mnode, get_user_ardour_path());
+               Config->add_instant_xml (enode, get_user_ardour_path());
+               Config->add_instant_xml (mnode, get_user_ardour_path());
        }
 
        /* keybindings */
@@ -507,11 +506,11 @@ ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
                jack_nframes_t rate = engine->frame_rate();
                
                if (fmod (rate, 1000.0) != 0.0) {
-                       snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"), 
+                       snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f msecs"), 
                                  (float) rate/1000.0f,
                                  (engine->frames_per_cycle() / (float) rate) * 1000.0f);
                } else {
-                       snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"), 
+                       snprintf (buf, sizeof (buf), _("%u kHz / %4.1f msecs"), 
                                  rate/1000,
                                  (engine->frames_per_cycle() / (float) rate) * 1000.0f);
                }
@@ -524,7 +523,7 @@ void
 ARDOUR_UI::update_cpu_load ()
 {
        char buf[32];
-       snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
+       snprintf (buf, sizeof (buf), _("DSP: %.1f%%"), engine->get_cpu_load());
        cpu_load_label.set_text (buf);
 }
 
@@ -543,9 +542,10 @@ ARDOUR_UI::update_buffer_load ()
 }
 
 void
-ARDOUR_UI::count_recenabled_diskstreams (AudioDiskstream& ds)
+ARDOUR_UI::count_recenabled_diskstreams (Route& route)
 {
-       if (ds.record_enabled()) {
+       Track* track = dynamic_cast<Track*>(&route);
+       if (track && track->diskstream().record_enabled()) {
                rec_enabled_diskstreams++;
        }
 }
@@ -561,7 +561,7 @@ ARDOUR_UI::update_disk_space()
        char buf[64];
 
        if (frames == max_frames) {
-               strcpy (buf, _("space: 24hrs+"));
+               strcpy (buf, _("Disk: 24hrs+"));
        } else {
                int hrs;
                int mins;
@@ -571,7 +571,7 @@ ARDOUR_UI::update_disk_space()
                if (session->actively_recording()){
                        
                        rec_enabled_diskstreams = 0;
-                       session->foreach_audio_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
+                       session->foreach_route (this, &ARDOUR_UI::count_recenabled_diskstreams);
                        
                        if (rec_enabled_diskstreams) {
                                frames /= rec_enabled_diskstreams;
@@ -591,7 +591,7 @@ ARDOUR_UI::update_disk_space()
                frames -= mins * fr * 60;
                secs = frames / fr;
                
-               snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
+               snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
        }
 
        disk_space_label.set_text (buf);
@@ -876,7 +876,7 @@ ARDOUR_UI::session_add_midi_track ()
 void
 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode)
 {
-       Route* route;
+       boost::shared_ptr<Route> route;
 
        if (session == 0) {
                warning << _("You cannot add a track without a session already loaded.") << endmsg;
@@ -918,7 +918,7 @@ restart JACK with more ports."));
 }
 
 void
-ARDOUR_UI::diskstream_added (AudioDiskstream* ds)
+ARDOUR_UI::diskstream_added (Diskstream* ds)
 {
 }
 
@@ -1159,32 +1159,25 @@ ARDOUR_UI::transport_forward (int option)
 }
 
 void
-ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
+ARDOUR_UI::toggle_record_enable (uint32_t dstream)
 {
        if (session == 0) {
                return;
        }
 
-       AudioDiskstream *ds;
+       boost::shared_ptr<Route> r;
+       
+       if ((r = session->route_by_remote_id (dstream)) != 0) {
 
-       if ((ds = session->diskstream_by_id (dstream)) != 0) {
-               Port *port = ds->io()->input (0);
-               port->request_monitor_input (!port->monitoring_input());
-       }
-}
+               Track* t;
 
-void
-ARDOUR_UI::toggle_record_enable (guint32 dstream)
-{
+               if ((t = dynamic_cast<Track*>(r.get())) != 0) {
+                       t->diskstream().set_record_enabled (!t->diskstream().record_enabled());
+               }
+       }
        if (session == 0) {
                return;
        }
-
-       AudioDiskstream *ds;
-
-       if ((ds = session->diskstream_by_id (dstream)) != 0) {
-               ds->set_record_enabled (!ds->record_enabled(), this);
-       }
 }
 
 void
@@ -1385,63 +1378,6 @@ ARDOUR_UI::stop_blinking ()
        }
 }
 
-
-void
-ARDOUR_UI::add_diskstream_to_menu (AudioDiskstream& dstream)
-{
-       using namespace Gtk;
-       using namespace Menu_Helpers;
-
-       if (dstream.hidden()) {
-               return;
-       }
-
-       MenuList& items = diskstream_menu->items();
-       items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
-}
-       
-void
-ARDOUR_UI::diskstream_selected (gint32 id)
-{
-       selected_dstream = id;
-       Main::quit ();
-}
-
-gint32
-ARDOUR_UI::select_diskstream (GdkEventButton *ev)
-{
-       using namespace Gtk;
-       using namespace Menu_Helpers;
-
-       if (session == 0) {
-               return -1;
-       }
-
-       diskstream_menu = new Menu();
-       diskstream_menu->set_name ("ArdourContextMenu");
-       using namespace Gtk;
-       using namespace Menu_Helpers;
-
-       MenuList& items = diskstream_menu->items();
-       items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
-
-       session->foreach_audio_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
-
-       if (ev) {
-               diskstream_menu->popup (ev->button, ev->time);
-       } else {
-               diskstream_menu->popup (0, 0);
-       }
-
-       selected_dstream = -1;
-
-       Main::run ();
-
-       delete diskstream_menu;
-
-       return selected_dstream;
-}
-
 void
 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
                          string& buf,
@@ -2217,11 +2153,11 @@ ARDOUR_UI::halt_on_xrun_message ()
 }
 
 void 
-ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::AudioFileSource*>* deletion_list)
+ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
 {
        ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
 
-       for (list<AudioFileSource*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
+       for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
                delete *i;
        }
 
index 678342f32bb6ad683ff64a1dead56dfa9110dec1..297c9c3c65e60a965dd2c2290c1ef8b8bf6ebf39 100644 (file)
@@ -79,7 +79,7 @@ class ColorManager;
 
 namespace Gtkmm2ext {
        class TearOff;
-};
+}
 
 namespace ARDOUR {
        class AudioEngine;
@@ -87,11 +87,11 @@ namespace ARDOUR {
        class Port;
        class IO;
        class ControlProtocolInfo;
-};
+}
 
 namespace ALSA {
        class MultiChannelDevice;
-};
+}
 
 #define FRAME_NAME "BaseFrame"
 
@@ -154,8 +154,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        void toggle_tempo_window ();
        void toggle_editing_space();
 
-       gint32 select_diskstream (GdkEventButton *ev);
-
        Gtk::Tooltips& tooltips() { return _tooltips; }
 
        static sigc::signal<void,bool> Blink;
@@ -522,7 +520,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        sigc::connection point_one_second_connection;
        sigc::connection point_zero_one_second_connection;
 
-       void diskstream_added (ARDOUR::AudioDiskstream*);
+       void diskstream_added (ARDOUR::Diskstream*);
 
        gint session_menu (GdkEventButton *);
 
@@ -536,14 +534,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI
 
        void save_template ();
 
-
        void session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode);
 
-       void add_diskstream_to_menu (ARDOUR::AudioDiskstream&);
-       void diskstream_selected (gint32);
-       Gtk::Menu *diskstream_menu;
-       gint32 selected_dstream;
-       
        void set_transport_sensitivity (bool);
 
        void remove_last_capture ();
@@ -626,11 +618,10 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        void test_binding_action (const char *);
        void start_keyboard_prefix();
 
-       void toggle_record_enable (guint32);
-       void toggle_monitor_enable (guint32);
+       void toggle_record_enable (uint32_t);
 
        uint32_t rec_enabled_diskstreams;
-       void count_recenabled_diskstreams (ARDOUR::AudioDiskstream&);
+       void count_recenabled_diskstreams (ARDOUR::Route&);
 
        About* about;
        bool shown_flag;
@@ -649,7 +640,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        struct timeval last_peak_grab;
        struct timeval last_shuttle_request;
 
-       void delete_sources_in_the_right_thread (list<ARDOUR::AudioFileSource*>*);
+       void delete_sources_in_the_right_thread (list<ARDOUR::Source*>*);
 
        void editor_display_control_changed (Editing::DisplayControl c);
 
@@ -716,5 +707,5 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        void toggle_control_protocol (ARDOUR::ControlProtocolInfo*);
 };
 
-
 #endif /* __ardour_gui_h__ */
+
index f92201e36c543e75bb5dc42238237b7d6bc0987c..44287fe61e79b8757a9fbaa6a45d3b3b096f3210 100644 (file)
@@ -359,10 +359,10 @@ ARDOUR_UI::setup_transport ()
        auditioning_alert_button.set_name ("TransportAuditioningAlert");
        auditioning_alert_button.signal_pressed().connect (mem_fun(*this,&ARDOUR_UI::audition_alert_toggle));
 
-       alert_box.pack_start (solo_alert_button);
-       alert_box.pack_start (auditioning_alert_button);
+       alert_box.pack_start (solo_alert_button, false, false);
+       alert_box.pack_start (auditioning_alert_button, false, false);
 
-       transport_tearoff_hbox.set_border_width (5);
+       transport_tearoff_hbox.set_border_width (3);
 
        transport_tearoff_hbox.pack_start (goto_start_button, false, false);
        transport_tearoff_hbox.pack_start (goto_end_button, false, false);
@@ -398,6 +398,7 @@ ARDOUR_UI::setup_transport ()
        mtc_port_changed ();
        sync_option_combo.set_active_text (positional_sync_strings.front());
        sync_option_combo.signal_changed().connect (mem_fun (*this, &ARDOUR_UI::sync_option_changed));
+       Gtkmm2ext::set_size_request_to_display_given_text (sync_option_combo, "Internal", 22, 10);
 
        shbox->pack_start (*sdframe, false, false);
        shbox->pack_start (shuttle_units_button, true, true);
@@ -406,37 +407,52 @@ ARDOUR_UI::setup_transport ()
        svbox->pack_start (*sframe, false, false);
        svbox->pack_start (*shbox, false, false);
 
-       transport_tearoff_hbox.pack_start (*svbox, false, false, 5);
+       transport_tearoff_hbox.pack_start (*svbox, false, false, 3);
 
        transport_tearoff_hbox.pack_start (auto_loop_button, false, false);
        transport_tearoff_hbox.pack_start (play_selection_button, false, false);
        transport_tearoff_hbox.pack_start (roll_button, false, false);
        transport_tearoff_hbox.pack_start (stop_button, false, false);
-       transport_tearoff_hbox.pack_start (rec_button, false, false, 10);
-
-       transport_tearoff_hbox.pack_start (primary_clock, false, false, 5);
-       transport_tearoff_hbox.pack_start (secondary_clock, false, false, 5);
-
-       transport_tearoff_hbox.pack_start (sync_option_combo, false, false);
-       transport_tearoff_hbox.pack_start (time_master_button, false, false);
-       transport_tearoff_hbox.pack_start (punch_in_button, false, false);
-       transport_tearoff_hbox.pack_start (punch_out_button, false, false);
-       transport_tearoff_hbox.pack_start (auto_input_button, false, false);
-       transport_tearoff_hbox.pack_start (auto_return_button, false, false);
-       transport_tearoff_hbox.pack_start (auto_play_button, false, false);
-       transport_tearoff_hbox.pack_start (click_button, false, false);
+       transport_tearoff_hbox.pack_start (rec_button, false, false, 6);
+
+       HBox* clock_box = manage (new HBox);
+       clock_box->pack_start (primary_clock, false, false);
+       clock_box->pack_start (secondary_clock, false, false);
+       VBox* time_controls_box = manage (new VBox);
+       time_controls_box->pack_start (sync_option_combo, false, false);
+       time_controls_box->pack_start (time_master_button, false, false);
+       clock_box->pack_start (*time_controls_box, false, false, 1);
+       transport_tearoff_hbox.pack_start (*clock_box, false, false, 0);
+       
+       HBox* toggle_box = manage(new HBox);
+       
+       VBox* punch_box = manage (new VBox);
+       punch_box->pack_start (punch_in_button, false, false);
+       punch_box->pack_start (punch_out_button, false, false);
+       toggle_box->pack_start (*punch_box, false, false);
+
+       VBox* auto_box = manage (new VBox);
+       auto_box->pack_start (auto_play_button, false, false);
+       auto_box->pack_start (auto_return_button, false, false);
+       toggle_box->pack_start (*auto_box, false, false);
+       
+       VBox* io_box = manage (new VBox);
+       io_box->pack_start (auto_input_button, false, false);
+       io_box->pack_start (click_button, false, false);
+       toggle_box->pack_start (*io_box, false, false);
        
        /* desensitize */
 
        set_transport_sensitivity (false);
 
-//     transport_tearoff_hbox.pack_start (preroll_button, false, false);
-//     transport_tearoff_hbox.pack_start (preroll_clock, false, false);
+//     toggle_box->pack_start (preroll_button, false, false);
+//     toggle_box->pack_start (preroll_clock, false, false);
 
-//     transport_tearoff_hbox.pack_start (postroll_button, false, false);
-//     transport_tearoff_hbox.pack_start (postroll_clock, false, false);
+//     toggle_box->pack_start (postroll_button, false, false);
+//     toggle_box->pack_start (postroll_clock, false, false);
 
-       transport_tearoff_hbox.pack_start (alert_box, false, false, 5);
+       transport_tearoff_hbox.pack_start (*toggle_box, false, false, 4);
+       transport_tearoff_hbox.pack_start (alert_box, false, false);
 }
 
 void
@@ -820,7 +836,7 @@ ARDOUR_UI::set_shuttle_units (ShuttleUnits u)
                shuttle_units_button.set_label("% ");
                break;
        case Semitones:
-               shuttle_units_button.set_label(_("st"));
+               shuttle_units_button.set_label(_("ST"));
                break;
        }
 }
@@ -864,7 +880,7 @@ ARDOUR_UI::update_speed_display ()
 {
        if (!session) {
                if (last_speed_displayed != 0) {
-                       speed_display_label.set_text (_("stopped"));
+                       speed_display_label.set_text (_("stop"));
                        last_speed_displayed = 0;
                }
                return;
@@ -877,7 +893,7 @@ ARDOUR_UI::update_speed_display ()
 
                if (x != 0) {
                        if (shuttle_units == Percentage) {
-                               snprintf (buf, sizeof (buf), "%.4f", x);
+                               snprintf (buf, sizeof (buf), "%.2f", x);
                        } else {
                                if (x < 0) {
                                        snprintf (buf, sizeof (buf), "< %.1f", 12.0 * fast_log2 (-x));
@@ -887,7 +903,7 @@ ARDOUR_UI::update_speed_display ()
                        }
                        speed_display_label.set_text (buf);
                } else {
-                       speed_display_label.set_text (_("stopped"));
+                       speed_display_label.set_text (_("stop"));
                }
 
                last_speed_displayed = x;
@@ -904,7 +920,7 @@ ARDOUR_UI::set_transport_sensitivity (bool yn)
 void
 ARDOUR_UI::editor_realized ()
 {
-       set_size_request_to_display_given_text (speed_display_box, _("stopped"), 2, 2);
+       set_size_request_to_display_given_text (speed_display_box, _("-0.55"), 2, 2);
        /* XXX: this should really be saved in instant.xml or something similar and restored from there */
        shuttle_style_button.set_active_text (_("sprung"));
        const guint32 FUDGE = 20; // Combo's are stupid - they steal space from the entry for the button
index 202fa88b59f3011a825c4e9bd4c50e245c3e30a7..25f3068a813d39c04d0b38157e98f79dee0e6c7c 100644 (file)
@@ -76,8 +76,8 @@ ARDOUR_UI::connect_to_session (Session *s)
        rec_button.set_sensitive (true);
        shuttle_box.set_sensitive (true);
        
-       if (session->n_audio_diskstreams() == 0) {
-               session->AudioDiskstreamAdded.connect (mem_fun(*this, &ARDOUR_UI::diskstream_added));
+       if (session->n_diskstreams() == 0) {
+               session->DiskstreamAdded.connect (mem_fun(*this, &ARDOUR_UI::diskstream_added));
        }
 
        if (connection_editor) {
index 1bc2de26d1014f3f1c4c3518ff192c7d9e73bfa7..238f81dd4f414973c0a2595c11f37872f5196e85 100644 (file)
@@ -264,31 +264,26 @@ ARDOUR_UI::install_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::transport_sensitive_actions.push_back (act);
 
-       /* XXX the newline in the displayed names of these action is really wrong, but its because we want the button
-          that proxies for these action to be more compact. It would be nice to find a way to override the action
-          name appearance on the buttons.
-       */
-
-       act = ActionManager::register_toggle_action (transport_actions, X_("TogglePunchIn"), _("Punch\nin"), mem_fun(*this, &ARDOUR_UI::toggle_punch_in));
+       act = ActionManager::register_toggle_action (transport_actions, X_("TogglePunchIn"), _("Punch In"), mem_fun(*this, &ARDOUR_UI::toggle_punch_in));
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::transport_sensitive_actions.push_back (act);
-       act = ActionManager::register_toggle_action (transport_actions, X_("TogglePunchOut"), _("Punch\nout"), mem_fun(*this, &ARDOUR_UI::toggle_punch_out));
+       act = ActionManager::register_toggle_action (transport_actions, X_("TogglePunchOut"), _("Punch Out"), mem_fun(*this, &ARDOUR_UI::toggle_punch_out));
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::transport_sensitive_actions.push_back (act);
        act = ActionManager::register_toggle_action (transport_actions, X_("ToggleClick"), _("Click"), mem_fun(*this, &ARDOUR_UI::toggle_click));
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::transport_sensitive_actions.push_back (act);
-       act = ActionManager::register_toggle_action (transport_actions, X_("ToggleAutoInput"), _("Auto\ninput"), mem_fun(*this, &ARDOUR_UI::toggle_auto_input));
+       act = ActionManager::register_toggle_action (transport_actions, X_("ToggleAutoInput"), _("Auto Input"), mem_fun(*this, &ARDOUR_UI::toggle_auto_input));
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::transport_sensitive_actions.push_back (act);
-       act = ActionManager::register_toggle_action (transport_actions, X_("ToggleAutoPlay"), _("Auto\nplay"), mem_fun(*this, &ARDOUR_UI::toggle_auto_play));
+       act = ActionManager::register_toggle_action (transport_actions, X_("ToggleAutoPlay"), _("Auto Play"), mem_fun(*this, &ARDOUR_UI::toggle_auto_play));
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::transport_sensitive_actions.push_back (act);
-       act = ActionManager::register_toggle_action (transport_actions, X_("ToggleAutoReturn"), _("Auto\nreturn"), mem_fun(*this, &ARDOUR_UI::toggle_auto_return));
+       act = ActionManager::register_toggle_action (transport_actions, X_("ToggleAutoReturn"), _("Auto Return"), mem_fun(*this, &ARDOUR_UI::toggle_auto_return));
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::transport_sensitive_actions.push_back (act);
 
-       act = ActionManager::register_toggle_action (transport_actions, X_("ToggleTimeMaster"), _("Time\nmaster"), mem_fun(*this, &ARDOUR_UI::toggle_time_master));
+       act = ActionManager::register_toggle_action (transport_actions, X_("ToggleTimeMaster"), _("Master"), mem_fun(*this, &ARDOUR_UI::toggle_time_master));
        ActionManager::session_sensitive_actions.push_back (act);
 
        act = ActionManager::register_action (common_actions, X_("ToggleRecordEnableTrack1"), _("Toggle Record Enable Track1"), bind (mem_fun(*this, &ARDOUR_UI::toggle_record_enable),  0U));
index 14dc6ba67385057658fde5740001cfbeb5f571f5..9ff5f45ddfca2bb9e7907143220beaa405f98306 100644 (file)
@@ -30,7 +30,7 @@
 
 namespace ARDOUR {
        class Session;
-};
+}
 
 class AudioClock : public Gtk::HBox
 {
@@ -40,7 +40,7 @@ class AudioClock : public Gtk::HBox
                BBT,
                MinSec,
                Frames,
-               Off,
+               Off
        };
        
        AudioClock (const string& name, bool editable, bool is_duration = false, bool with_tempo_meter = false);
@@ -87,7 +87,7 @@ class AudioClock : public Gtk::HBox
                Bars,
                Beats, 
                Ticks,
-               AudioFrames,
+               AudioFrames
        };
 
        Gtk::EventBox  audio_frames_ebox;
diff --git a/gtk2_ardour/audio_region_editor.cc b/gtk2_ardour/audio_region_editor.cc
new file mode 100644 (file)
index 0000000..194f358
--- /dev/null
@@ -0,0 +1,731 @@
+/*
+    Copyright (C) 2001 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$
+*/
+
+#include <ardour/audioregion.h>
+#include <ardour/utils.h>
+#include <gtkmm2ext/utils.h>
+#include <gtkmm2ext/stop_signal.h>
+#include <cmath>
+
+#include "audio_region_editor.h"
+#include "audio_region_view.h"
+#include "ardour_ui.h"
+#include "utils.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+using namespace sigc;
+using namespace std;
+
+AudioRegionEditor::AudioRegionEditor (Session& s, AudioRegion& r, AudioRegionView& rv)
+       : RegionEditor (s),
+         _region (r),
+         _region_view (rv),
+         name_label (_("NAME:")),
+         lock_button (_("lock")),
+         mute_button (_("mute")),
+         opaque_button (_("opaque")),
+         envelope_active_button(_("active")),
+         envelope_view_button(_("visible")),
+         raise_arrow (Gtk::ARROW_UP, Gtk::SHADOW_OUT),
+         lower_arrow (Gtk::ARROW_DOWN, Gtk::SHADOW_OUT),
+         layer_label (_("Layer")),
+         audition_button (_("play")),
+         time_table (3, 2),
+         start_clock ("AudioRegionEditorClock", true),
+         end_clock ("AudioRegionEditorClock", true),
+         length_clock ("AudioRegionEditorClock", true, true),
+         sync_offset_clock ("AudioRegionEditorClock", true, true),
+         envelope_loop_table (1, 3),
+         envelope_label (_("ENVELOPE")),
+         fade_in_table (4, 3),
+         fade_in_length_adjustment (5.0, 0.0, 10000, 0.05, 1),
+         fade_in_length_spinner (fade_in_length_adjustment, 10),
+         fade_out_table (4, 3),
+         fade_out_length_adjustment (5.0, 0.0, 10000, 0.05, 1),
+         fade_out_length_spinner (fade_out_length_adjustment, 10)
+
+{
+       start_clock.set_session (&_session);
+       end_clock.set_session (&_session);
+       length_clock.set_session (&_session);
+
+       name_entry.set_name ("AudioRegionEditorEntry");
+       name_label.set_name ("AudioRegionEditorLabel");
+
+       name_hbox.set_spacing (5);
+       name_hbox.pack_start (name_label, false, false);
+       name_hbox.pack_start (name_entry, false, false);
+
+       raise_button.add (raise_arrow);
+       lower_button.add (lower_arrow);
+       layer_frame.set_name ("BaseFrame");
+       layer_frame.set_shadow_type (Gtk::SHADOW_IN);
+       layer_frame.add (layer_value_label);
+       layer_label.set_name ("AudioRegionEditorLabel");
+       layer_value_label.set_name ("AudioRegionEditorLabel");
+       Gtkmm2ext::set_size_request_to_display_given_text (layer_value_label, "99", 5, 2);
+
+       layer_hbox.set_spacing (5);
+       layer_hbox.pack_start (layer_label, false, false);
+       layer_hbox.pack_start (layer_frame, false, false);
+#if 0
+       layer_hbox.pack_start (raise_button, false, false);
+       layer_hbox.pack_start (lower_button, false, false);
+#endif
+
+       mute_button.set_name ("AudioRegionEditorToggleButton");
+       opaque_button.set_name ("AudioRegionEditorToggleButton");
+       lock_button.set_name ("AudioRegionEditorToggleButton");
+       envelope_active_button.set_name ("AudioRegionEditorToggleButton");
+       envelope_view_button.set_name ("AudioRegionEditorToggleButton");
+       fade_in_active_button.set_name ("AudioRegionEditorToggleButton");
+       fade_out_active_button.set_name ("AudioRegionEditorToggleButton");
+       audition_button.set_name ("AudioRegionEditorToggleButton");
+
+       ARDOUR_UI::instance()->tooltips().set_tip (mute_button, _("mute this region"));
+       ARDOUR_UI::instance()->tooltips().set_tip (opaque_button, _("regions underneath this one cannot be heard"));
+       ARDOUR_UI::instance()->tooltips().set_tip (lock_button, _("prevent any changes to this region"));
+       ARDOUR_UI::instance()->tooltips().set_tip (envelope_active_button, _("use the gain envelope during playback"));
+       ARDOUR_UI::instance()->tooltips().set_tip (envelope_view_button, _("show the gain envelope"));
+       ARDOUR_UI::instance()->tooltips().set_tip (fade_in_active_button, _("use fade in curve during playback"));
+       ARDOUR_UI::instance()->tooltips().set_tip (fade_out_active_button, _("use fade out curve during playback"));
+       ARDOUR_UI::instance()->tooltips().set_tip (audition_button, _("audition this region"));
+
+       mute_button.unset_flags (Gtk::CAN_FOCUS);
+       opaque_button.unset_flags (Gtk::CAN_FOCUS);
+       lock_button.unset_flags (Gtk::CAN_FOCUS);
+       envelope_active_button.unset_flags (Gtk::CAN_FOCUS);
+       envelope_view_button.unset_flags (Gtk::CAN_FOCUS);
+       fade_in_active_button.unset_flags (Gtk::CAN_FOCUS);
+       fade_out_active_button.unset_flags (Gtk::CAN_FOCUS);
+       audition_button.unset_flags (Gtk::CAN_FOCUS);
+       
+       mute_button.set_events (mute_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       opaque_button.set_events (opaque_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       lock_button.set_events (lock_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       envelope_active_button.set_events (envelope_active_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       envelope_view_button.set_events (envelope_view_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       fade_in_active_button.set_events (fade_in_active_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       fade_out_active_button.set_events (fade_out_active_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+       audition_button.set_events (audition_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
+
+       top_row_button_hbox.set_border_width (5);
+       top_row_button_hbox.set_spacing (5);
+       top_row_button_hbox.set_homogeneous (false);
+       top_row_button_hbox.pack_start (mute_button, false, false);
+       top_row_button_hbox.pack_start (opaque_button, false, false);
+       top_row_button_hbox.pack_start (lock_button, false, false);
+       top_row_button_hbox.pack_start (layer_hbox, false, false, 5);
+       top_row_button_hbox.pack_end (audition_button, false, false);
+       
+       top_row_hbox.pack_start (name_hbox, true, true);
+       top_row_hbox.pack_end (top_row_button_hbox, true, true);
+
+       start_label.set_name ("AudioRegionEditorLabel");
+       start_label.set_text (_("START:"));
+       end_label.set_name ("AudioRegionEditorLabel");
+       end_label.set_text (_("END:"));
+       length_label.set_name ("AudioRegionEditorLabel");
+       length_label.set_text (_("LENGTH:"));
+       
+       time_table.set_col_spacings (2);
+       time_table.set_row_spacings (5);
+       time_table.set_border_width (5);
+
+       start_alignment.set (1.0, 0.5);
+       end_alignment.set (1.0, 0.5);
+       length_alignment.set (1.0, 0.5);
+
+       start_alignment.add (start_label);
+       end_alignment.add (end_label);
+       length_alignment.add (length_label);
+
+       time_table.attach (start_alignment, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
+       time_table.attach (start_clock, 1, 2, 0, 1, Gtk::FILL, Gtk::FILL);
+
+       time_table.attach (end_alignment, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL);
+       time_table.attach (end_clock, 1, 2, 1, 2, Gtk::FILL, Gtk::FILL);
+
+       time_table.attach (length_alignment, 0, 1, 2, 3, Gtk::FILL, Gtk::FILL);
+       time_table.attach (length_clock, 1, 2, 2, 3, Gtk::FILL, Gtk::FILL);
+
+       envelope_label.set_name ("AudioRegionEditorLabel");
+
+       envelope_loop_table.set_border_width (5);
+       envelope_loop_table.set_row_spacings (2);
+       envelope_loop_table.attach (envelope_label, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
+       envelope_loop_table.attach (envelope_active_button, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+       envelope_loop_table.attach (envelope_view_button, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       /* fade in */
+
+       fade_in_table.set_border_width (5);
+       fade_in_table.set_homogeneous (false);
+
+       fade_in_label.set_name ("AudioRegionEditorLabel");
+       fade_in_active_button_label.set_name ("AudioRegionEditorSmallLabel");
+       fade_in_length_label.set_name ("AudioRegionEditorSmallLabel");
+
+       fade_in_label.set_text (_("FADE IN"));
+       fade_in_active_button_label.set_text (_("active"));
+       fade_in_length_label.set_text (_("msecs"));
+
+       fade_in_active_button.add (fade_in_active_button_label);
+
+       fade_in_length_spinner.set_name("GenericSpinner");
+
+       fade_in_length_spinner.set_digits (3);
+
+       // fade_in_length_spinner.signal_activate().connect (mem_fun(*this, &AudioRegionEditor::activation));
+
+       Gtkmm2ext::set_size_request_to_display_given_text (fade_in_length_spinner, "500g", 20, -1);
+
+       fade_in_label_align.add (fade_in_label);
+       fade_in_label_align.set (0.5);
+
+
+       fade_in_table.attach (fade_in_label_align,   0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       fade_in_table.attach (fade_in_length_label,   0, 1, 1, 2, Gtk::EXPAND, Gtk::FILL);
+       fade_in_table.attach (fade_in_length_spinner, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       fade_in_table.attach (fade_in_active_button,        0, 2, 3, 5, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       /* fade out */
+
+       fade_out_table.set_border_width (5);
+       fade_out_table.set_homogeneous (false);
+
+       fade_out_label.set_name ("AudioRegionEditorLabel");
+       fade_out_active_button_label.set_name ("AudioRegionEditorSmallLabel");
+       fade_out_length_label.set_name ("AudioRegionEditorSmallLabel");
+
+       fade_out_label.set_text (_("FADE OUT"));
+       fade_out_active_button_label.set_text (_("active"));
+       fade_out_length_label.set_text (_("msecs"));
+
+       fade_out_active_button.add (fade_out_active_button_label);
+
+       fade_out_length_spinner.set_name("GenericSpinner");
+       
+       fade_out_length_spinner.set_digits (3);
+
+       fade_out_length_spinner.signal_activate().connect (mem_fun(*this, &AudioRegionEditor::activation));
+
+       Gtkmm2ext::set_size_request_to_display_given_text (fade_out_length_spinner, "500g", 20, -1);
+
+       fade_out_label_align.add (fade_out_label);
+       fade_out_label_align.set (0.5);
+
+       fade_out_table.attach (fade_out_label_align,   0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       fade_out_table.attach (fade_out_length_label,   0, 1, 1, 2, Gtk::EXPAND, Gtk::FILL);
+       fade_out_table.attach (fade_out_length_spinner, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       fade_out_table.attach (fade_out_active_button,        0, 2, 3, 5, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
+
+       lower_hbox.pack_start (time_table, true, true);
+       lower_hbox.pack_start (sep1, false, false);
+       lower_hbox.pack_start (envelope_loop_table, true, true);
+       lower_hbox.pack_start (sep2, false, false);
+       lower_hbox.pack_start (fade_in_table, true, true);
+       lower_hbox.pack_start (fade_out_table, true, true);
+
+       get_vbox()->pack_start (top_row_hbox, true, true);
+       get_vbox()->pack_start (sep3, false, false);
+       get_vbox()->pack_start (lower_hbox, true, true);
+
+       set_name ("AudioRegionEditorWindow");
+       add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
+
+       signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (this)));
+
+       string title = _("ardour: region ");
+       title += _region.name();
+       set_title (title);
+
+       show_all();
+
+       name_changed ();
+       bounds_changed (Change (StartChanged|LengthChanged|PositionChanged));
+       envelope_active_changed ();
+       mute_changed ();
+       opacity_changed ();
+       lock_changed ();
+       layer_changed ();
+       fade_in_changed ();
+       fade_out_changed ();
+
+       XMLNode *node  = _region.extra_xml ("GUI");
+       XMLProperty *prop = 0;
+       bool showing_envelope = false;
+
+       if (node && (prop = node->property ("envelope-visible")) != 0) {
+               if (prop->value() == "yes") {
+                       showing_envelope = true;
+               } 
+       } 
+
+       if (showing_envelope) {
+               envelope_view_button.set_active (true);
+       } else {
+               envelope_view_button.set_active (false);
+       }
+
+       _region.StateChanged.connect (mem_fun(*this, &AudioRegionEditor::region_changed));
+       
+       spin_arrow_grab = false;
+       
+       connect_editor_events ();
+}
+
+AudioRegionEditor::~AudioRegionEditor ()
+{
+}
+
+void
+AudioRegionEditor::region_changed (Change what_changed)
+{
+       if (what_changed & NameChanged) {
+               name_changed ();
+       }
+       if (what_changed & BoundsChanged) {
+               bounds_changed (what_changed);
+       }
+
+       if (what_changed & Region::OpacityChanged) {
+               opacity_changed ();
+       }
+       if (what_changed & Region::MuteChanged) {
+               mute_changed ();
+       }
+       if (what_changed & Region::LockChanged) {
+               lock_changed ();
+       }
+       if (what_changed & Region::LayerChanged) {
+               layer_changed ();
+       }
+
+       if (what_changed & AudioRegion::EnvelopeActiveChanged) {
+               envelope_active_changed ();
+       }
+       if (what_changed & AudioRegion::FadeInChanged) {
+               fade_in_changed ();
+       }
+       if (what_changed & AudioRegion::FadeOutChanged) {
+               fade_out_changed ();
+       }
+       if (what_changed & AudioRegion::FadeInActiveChanged) {
+               fade_in_active_changed ();
+       }
+       if (what_changed & AudioRegion::FadeOutActiveChanged) {
+               fade_out_active_changed ();
+       }
+}
+
+void
+AudioRegionEditor::fade_in_realized ()
+{
+       fade_in_changed ();
+}
+
+void
+AudioRegionEditor::fade_out_realized ()
+{
+       fade_out_changed ();
+}
+
+gint 
+AudioRegionEditor::bpressed (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)())
+{
+       switch (ev->button) {
+       case 1:
+       case 2:
+       case 3:
+               if (ev->type == GDK_BUTTON_PRESS) { /* no double clicks here */
+                       if (!spin_arrow_grab) {
+                               // GTK2FIX probably nuke the region editor
+                               // if ((ev->window == but->gobj()->panel)) {
+                               // spin_arrow_grab = true;
+                               // (this->*pmf)();
+                               // } 
+                       } 
+               } 
+               break;
+       default:
+               break;
+       }
+       return FALSE;
+}
+
+gint 
+AudioRegionEditor::breleased (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)())
+{
+       if (spin_arrow_grab) {
+               (this->*pmf)();
+               spin_arrow_grab = false;
+       }
+       return FALSE;
+}
+
+void
+AudioRegionEditor::start_editing_fade_in ()
+{
+       _region.freeze ();
+}
+
+void
+AudioRegionEditor::stop_editing_fade_in ()
+{
+       _region.thaw (_("fade in edit"));
+}
+
+void
+AudioRegionEditor::start_editing_fade_out ()
+{
+       _region.freeze ();
+}
+
+void
+AudioRegionEditor::stop_editing_fade_out ()
+{
+       _region.thaw (_("fade out edit"));
+}
+
+void
+AudioRegionEditor::connect_editor_events ()
+{
+  name_entry.signal_changed().connect (mem_fun(*this, &AudioRegionEditor::name_entry_changed));
+
+       start_clock.ValueChanged.connect (mem_fun(*this, &AudioRegionEditor::start_clock_changed));
+       end_clock.ValueChanged.connect (mem_fun(*this, &AudioRegionEditor::end_clock_changed));
+       length_clock.ValueChanged.connect (mem_fun(*this, &AudioRegionEditor::length_clock_changed));
+
+       fade_in_length_spinner.signal_button_press_event().connect (bind (mem_fun(*this, &AudioRegionEditor::bpressed), &fade_in_length_spinner, 
+                                                                &AudioRegionEditor::start_editing_fade_in));
+       fade_in_length_spinner.signal_button_release_event().connect (bind (mem_fun (*this, &AudioRegionEditor::breleased), &fade_in_length_spinner, 
+                                                                  &AudioRegionEditor::stop_editing_fade_in));
+
+       fade_out_length_spinner.signal_button_press_event().connect (bind (mem_fun(*this, &AudioRegionEditor::bpressed), &fade_out_length_spinner, 
+                                                                &AudioRegionEditor::start_editing_fade_out));
+       fade_out_length_spinner.signal_button_release_event().connect (bind (mem_fun (*this, &AudioRegionEditor::breleased), &fade_out_length_spinner, 
+                                                                  &AudioRegionEditor::stop_editing_fade_out));
+
+       fade_in_length_adjustment.signal_value_changed().connect (mem_fun(*this, &AudioRegionEditor::fade_in_length_adjustment_changed));
+       fade_out_length_adjustment.signal_value_changed().connect (mem_fun(*this, &AudioRegionEditor::fade_out_length_adjustment_changed));
+
+       fade_in_active_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::fade_in_active_toggled));
+       fade_out_active_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::fade_out_active_toggled));
+
+       envelope_active_button.signal_button_press_event().connect (mem_fun(*this, &AudioRegionEditor::envelope_active_button_press));
+       envelope_active_button.signal_button_release_event().connect (mem_fun(*this, &AudioRegionEditor::envelope_active_button_release));
+       audition_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::audition_button_toggled));
+       envelope_view_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::envelope_view_button_toggled));
+       lock_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::lock_button_clicked));
+       mute_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::mute_button_clicked));
+       opaque_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::opaque_button_clicked));
+       raise_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::raise_button_clicked));
+       lower_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::lower_button_clicked));
+       _session.AuditionActive.connect (mem_fun(*this, &AudioRegionEditor::audition_state_changed));
+}
+
+void
+AudioRegionEditor::start_clock_changed ()
+{
+       _region.set_position (start_clock.current_time(), this);
+}
+
+void
+AudioRegionEditor::end_clock_changed ()
+{
+       _region.trim_end (end_clock.current_time(), this);
+
+       end_clock.set (_region.position() + _region.length(), true);
+}
+
+void
+AudioRegionEditor::length_clock_changed ()
+{
+       jack_nframes_t frames = length_clock.current_time();
+       _region.trim_end (_region.position() + frames, this);
+
+       length_clock.set (_region.length());
+}
+
+gint
+AudioRegionEditor::envelope_active_button_press(GdkEventButton *ev)
+{
+       return stop_signal (envelope_active_button, "button_press_event");
+}
+
+gint
+AudioRegionEditor::envelope_active_button_release (GdkEventButton *ev)
+{
+       _region.set_envelope_active (!_region.envelope_active());
+       return stop_signal (envelope_active_button, "button_release_event");
+}
+
+void
+AudioRegionEditor::envelope_view_button_toggled ()
+{
+       bool visible = envelope_view_button.get_active ();
+
+       _region_view.set_envelope_visible (visible);
+}
+
+void
+AudioRegionEditor::audition_button_toggled ()
+{
+       if (audition_button.get_active()) {
+               _session.audition_region (_region);
+       } else {
+               _session.cancel_audition ();
+       }
+}
+
+void
+AudioRegionEditor::raise_button_clicked ()
+{
+       _region.raise ();
+}
+
+void
+AudioRegionEditor::lower_button_clicked ()
+{
+       _region.lower ();
+}
+
+void
+AudioRegionEditor::opaque_button_clicked ()
+{
+       bool ractive = _region.opaque();
+
+       if (opaque_button.get_active() != ractive) {
+               _region.set_opaque (!ractive);
+       }
+}
+
+void
+AudioRegionEditor::mute_button_clicked ()
+{
+       bool ractive = _region.muted();
+
+       if (mute_button.get_active() != ractive) {
+               _region.set_muted (!ractive);
+       }
+}
+
+void
+AudioRegionEditor::lock_button_clicked ()
+{
+       bool ractive = _region.locked();
+
+       if (lock_button.get_active() != ractive) {
+               _region.set_locked (!ractive);
+       }
+}
+
+void
+AudioRegionEditor::layer_changed ()
+{
+       char buf[8];
+       snprintf (buf, sizeof(buf), "%d", (int) _region.layer() + 1);
+       layer_value_label.set_text (buf);
+}
+
+void
+AudioRegionEditor::name_changed ()
+{
+       if (name_entry.get_text() != _region.name()) {
+               name_entry.set_text (_region.name());
+       }
+}
+
+void
+AudioRegionEditor::lock_changed ()
+{
+       bool yn;
+
+       if ((yn = _region.locked()) != lock_button.get_active()) {
+               lock_button.set_active (yn);
+       }
+
+       start_clock.set_sensitive (!yn);
+       end_clock.set_sensitive (!yn);
+       length_clock.set_sensitive (!yn);
+}
+
+void
+AudioRegionEditor::envelope_active_changed ()
+{
+       bool yn;
+
+       if ((yn = _region.envelope_active()) != envelope_active_button.get_active()) {
+               envelope_active_button.set_active (yn);
+       }
+}
+
+void
+AudioRegionEditor::opacity_changed ()
+{
+       bool yn;
+       if ((yn = _region.opaque()) != opaque_button.get_active()) {
+               opaque_button.set_active (yn);
+       }
+}
+
+void
+AudioRegionEditor::mute_changed ()
+{
+       bool yn;
+       if ((yn = _region.muted()) != mute_button.get_active()) {
+               mute_button.set_active (yn);
+       }
+}
+
+void
+AudioRegionEditor::bounds_changed (Change what_changed)
+{
+       if (what_changed & Change ((PositionChanged|LengthChanged))) {
+               start_clock.set (_region.position(), true);
+               end_clock.set (_region.position() + _region.length(), true);
+               length_clock.set (_region.length(), true);
+       }
+}
+
+void
+AudioRegionEditor::activation ()
+{
+       
+}      
+
+void
+AudioRegionEditor::name_entry_changed ()
+{
+       if (name_entry.get_text() != _region.name()) {
+               _region.set_name (name_entry.get_text());
+       }
+}
+
+void
+AudioRegionEditor::fade_in_changed ()
+{
+       float msecs = fade_in_length_adjustment.get_value();
+       jack_nframes_t sr = _session.frame_rate();
+       jack_nframes_t adj_frames = (jack_nframes_t) floor (msecs * (sr/1000.0f));
+       jack_nframes_t frames;
+       bool x;
+
+       if (adj_frames != (frames = (jack_nframes_t) _region.fade_in().back()->when)) {
+               fade_in_length_adjustment.set_value ((frames * 1000.0f) / sr);
+       }
+
+       if ((x = _region.fade_in_active()) != fade_in_active_button.get_active()) {
+               fade_in_active_button.set_active (x);
+       }
+}
+
+void
+AudioRegionEditor::fade_out_changed ()
+{
+       float msecs = fade_out_length_adjustment.get_value();
+       jack_nframes_t sr = _session.frame_rate();
+       jack_nframes_t adj_frames = (jack_nframes_t) floor (msecs * (sr/1000.0f));
+       jack_nframes_t frames;
+       bool x;
+       if (adj_frames != (frames = (jack_nframes_t) _region.fade_out().back()->when)) {
+               fade_out_length_adjustment.set_value ((frames * 1000.0f) / sr);
+       }
+
+       if ((x = _region.fade_out_active()) != fade_out_active_button.get_active()) {
+               fade_out_active_button.set_active (x);
+       }
+}
+
+void
+AudioRegionEditor::fade_in_length_adjustment_changed ()
+{
+       jack_nframes_t fade_length = (jack_nframes_t) floor (fade_in_length_adjustment.get_value() * _session.frame_rate() * 0.001); 
+       fade_length = max (fade_length, (jack_nframes_t) 64);
+       fade_length = min (fade_length, _region.length());
+       
+       _region.set_fade_in_length (fade_length);
+       /* region is frozen, no worries */
+       fade_in_changed();
+}
+
+void
+AudioRegionEditor::fade_out_length_adjustment_changed ()
+{
+       jack_nframes_t fade_length = (jack_nframes_t) floor (fade_out_length_adjustment.get_value() * _session.frame_rate() * 0.001); 
+       fade_length = max (fade_length, (jack_nframes_t) 64);
+       fade_length = min (fade_length, _region.length());
+       
+       _region.set_fade_out_length (fade_length);      
+       /* region is frozen, no worries */
+       fade_out_changed();
+}
+
+void
+AudioRegionEditor::fade_in_active_toggled ()
+{
+       _region.set_fade_in_active (fade_in_active_button.get_active());
+}
+
+void
+AudioRegionEditor::fade_out_active_toggled ()
+{
+       _region.set_fade_out_active (fade_out_active_button.get_active());
+}
+
+void
+AudioRegionEditor::fade_out_active_changed ()
+{
+       bool x;
+
+       if ((x = _region.fade_out_active()) != fade_out_active_button.get_active()) {
+               fade_out_active_button.set_active (x);
+       }
+}
+
+void
+AudioRegionEditor::fade_in_active_changed ()
+{
+       bool x;
+
+       if ((x = _region.fade_in_active()) != fade_in_active_button.get_active()) {
+               fade_in_active_button.set_active (x);
+       }
+}
+
+void
+AudioRegionEditor::audition_state_changed (bool yn)
+{
+       ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionEditor::audition_state_changed), yn));
+
+       if (!yn) {
+               audition_button.set_active (false);
+       }
+}
+
diff --git a/gtk2_ardour/audio_region_editor.h b/gtk2_ardour/audio_region_editor.h
new file mode 100644 (file)
index 0000000..38cd920
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+    Copyright (C) 2001 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$
+*/
+
+#ifndef __gtk_ardour_audio_region_edit_h__
+#define __gtk_ardour_audio_region_edit_h__
+
+#include <map>
+
+#include <gtkmm/label.h>
+#include <gtkmm/entry.h>
+#include <gtkmm/box.h>
+#include <gtkmm/togglebutton.h>
+#include <gtkmm/button.h>
+#include <gtkmm/arrow.h>
+#include <gtkmm/frame.h>
+#include <gtkmm/table.h>
+#include <gtkmm/alignment.h>
+#include <gtkmm/adjustment.h>
+#include <gtkmm/separator.h>
+#include <gtkmm/spinbutton.h>
+
+#include <libgnomecanvas/libgnomecanvas.h>
+#include <sigc++/signal.h>
+
+#include "audio_clock.h"
+#include "ardour_dialog.h"
+#include "region_editor.h"
+
+namespace ARDOUR {
+       class AudioRegion;
+       class Session;
+}
+
+class AudioRegionView;
+
+class AudioRegionEditor : public RegionEditor
+{
+  public:
+       AudioRegionEditor (ARDOUR::Session&, ARDOUR::AudioRegion&, AudioRegionView& rv);
+       ~AudioRegionEditor ();
+
+  private:
+       ARDOUR::AudioRegion& _region;
+       AudioRegionView& _region_view;
+
+       void connect_editor_events ();
+
+       Gtk::Label name_label;
+       Gtk::Entry name_entry;
+       Gtk::HBox  name_hbox;
+
+       Gtk::HBox  top_row_hbox;
+       Gtk::HBox  top_row_button_hbox;
+
+       Gtk::ToggleButton lock_button;
+       Gtk::ToggleButton mute_button;
+       Gtk::ToggleButton opaque_button;
+       Gtk::ToggleButton envelope_active_button;
+       Gtk::ToggleButton envelope_view_button;
+
+       Gtk::Button       raise_button;
+       Gtk::Arrow        raise_arrow;
+       Gtk::Button       lower_button;
+       Gtk::Arrow        lower_arrow;
+       Gtk::Frame        layer_frame;
+       Gtk::Label        layer_value_label;
+       Gtk::Label        layer_label;
+       Gtk::HBox         layer_hbox;
+
+       Gtk::ToggleButton  audition_button;
+
+       Gtk::HBox  lower_hbox;
+       
+       Gtk::Table time_table;
+
+       Gtk::Label start_label;
+       Gtk::Label end_label;
+       Gtk::Label length_label;
+       Gtk::Alignment start_alignment;
+       Gtk::Alignment end_alignment;
+       Gtk::Alignment length_alignment;
+
+       AudioClock start_clock;
+       AudioClock end_clock;
+       AudioClock length_clock;
+       AudioClock sync_offset_clock;
+
+       Gtk::Table  envelope_loop_table;
+       Gtk::Button loop_button;
+       Gtk::Label  loop_label;
+       Gtk::Label  envelope_label;
+
+       Gtk::Table fade_in_table;
+       Gtk::Label fade_in_label;
+       Gtk::Alignment fade_in_label_align;
+       Gtk::Label fade_in_active_button_label;
+       Gtk::ToggleButton fade_in_active_button;
+       Gtk::Label fade_in_length_label;
+
+       Gtk::Adjustment fade_in_length_adjustment;
+       Gtk::SpinButton fade_in_length_spinner;
+
+       Gtk::Table fade_out_table;
+       Gtk::Label fade_out_label;
+       Gtk::Alignment fade_out_label_align;
+       Gtk::Label fade_out_active_button_label;
+       Gtk::ToggleButton fade_out_active_button;
+       Gtk::Label fade_out_length_label;
+
+       Gtk::Adjustment fade_out_length_adjustment;
+       Gtk::SpinButton fade_out_length_spinner;
+
+       Gtk::HSeparator sep3;
+       Gtk::VSeparator sep1;
+       Gtk::VSeparator sep2;
+
+       void region_changed (ARDOUR::Change);
+       void bounds_changed (ARDOUR::Change);
+       void name_changed ();
+       void opacity_changed ();
+       void mute_changed ();
+       void envelope_active_changed ();
+       void lock_changed ();
+       void layer_changed ();
+
+       void fade_in_length_adjustment_changed ();
+       void fade_out_length_adjustment_changed ();
+       void fade_in_changed ();
+       void fade_out_changed ();
+       void audition_state_changed (bool);
+
+       void activation ();
+
+       void name_entry_changed ();
+       void start_clock_changed ();
+       void end_clock_changed ();
+       void length_clock_changed ();
+
+       gint envelope_active_button_press (GdkEventButton *);
+       gint envelope_active_button_release (GdkEventButton *);
+
+       void audition_button_toggled ();
+       void envelope_view_button_toggled ();
+       void lock_button_clicked ();
+       void mute_button_clicked ();
+       void opaque_button_clicked ();
+       void raise_button_clicked ();
+       void lower_button_clicked ();
+
+       void fade_in_active_toggled ();
+       void fade_out_active_toggled ();
+       void fade_in_active_changed ();
+       void fade_out_active_changed ();
+
+       void fade_in_realized ();
+       void fade_out_realized ();
+
+       void start_editing_fade_in ();
+       void start_editing_fade_out ();
+       void stop_editing_fade_in ();
+       void stop_editing_fade_out ();
+
+       gint bpressed (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)());
+       gint breleased (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)());
+
+       bool spin_arrow_grab;
+};
+
+#endif /* __gtk_ardour_audio_region_edit_h__ */
diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc
new file mode 100644 (file)
index 0000000..feb8f4f
--- /dev/null
@@ -0,0 +1,1127 @@
+/*
+    Copyright (C) 2001-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
+    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$
+*/
+
+#include <cmath>
+#include <cassert>
+#include <algorithm>
+
+#include <gtkmm.h>
+
+#include <gtkmm2ext/gtk_ui.h>
+
+#include <ardour/playlist.h>
+#include <ardour/audioregion.h>
+#include <ardour/audiosource.h>
+#include <ardour/audio_diskstream.h>
+
+#include "streamview.h"
+#include "audio_region_view.h"
+#include "audio_time_axis.h"
+#include "simplerect.h"
+#include "simpleline.h"
+#include "waveview.h"
+#include "public_editor.h"
+#include "audio_region_editor.h"
+#include "region_gain_line.h"
+#include "ghostregion.h"
+#include "audio_time_axis.h"
+#include "utils.h"
+#include "rgb_macros.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace sigc;
+using namespace ARDOUR;
+using namespace PBD;
+using namespace Editing;
+using namespace ArdourCanvas;
+
+static const int32_t sync_mark_width = 9;
+
+AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, AudioRegion& r, double spu,
+                                 Gdk::Color& basic_color)
+       : RegionView (parent, tv, r, spu, basic_color)
+       , sync_mark(0)
+       , zero_line(0)
+       , fade_in_shape(0)
+       , fade_out_shape(0)
+       , fade_in_handle(0)
+       , fade_out_handle(0)
+       , gain_line(0)
+       , _amplitude_above_axis(1.0)
+       , _flags(0)
+       , fade_color(0)
+{
+}
+
+AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, AudioRegion& r, double spu, 
+                                 Gdk::Color& basic_color, TimeAxisViewItem::Visibility visibility)
+       : RegionView (parent, tv, r, spu, basic_color, visibility)
+       , sync_mark(0)
+       , zero_line(0)
+       , fade_in_shape(0)
+       , fade_out_shape(0)
+       , fade_in_handle(0)
+       , fade_out_handle(0)
+       , gain_line(0)
+       , _amplitude_above_axis(1.0)
+       , _flags(0)
+       , fade_color(0)
+{
+}
+
+void
+AudioRegionView::init (Gdk::Color& basic_color, bool wfd)
+{
+       // FIXME: Some redundancy here with RegionView::init.  Need to figure out
+       // where order is important and where it isn't...
+       
+       RegionView::init(basic_color, wfd);
+
+       XMLNode *node;
+
+       _amplitude_above_axis = 1.0;
+       zero_line             = 0;
+       _flags                = 0;
+
+       if ((node = _region.extra_xml ("GUI")) != 0) {
+               set_flags (node);
+       } else {
+               _flags = WaveformVisible;
+               store_flags ();
+       }
+
+       if (trackview.editor.new_regionviews_display_gain()) {
+               _flags |= EnvelopeVisible;
+       }
+
+       compute_colors (basic_color);
+
+       create_waves ();
+
+       fade_in_shape = new ArdourCanvas::Polygon (*group);
+       fade_in_shape->property_fill_color_rgba() = fade_color;
+       fade_in_shape->set_data ("regionview", this);
+       
+       fade_out_shape = new ArdourCanvas::Polygon (*group);
+       fade_out_shape->property_fill_color_rgba() = fade_color;
+       fade_out_shape->set_data ("regionview", this);
+
+
+       {
+               uint32_t r,g,b,a;
+               UINT_TO_RGBA(fill_color,&r,&g,&b,&a);
+       
+
+               fade_in_handle = new ArdourCanvas::SimpleRect (*group);
+               fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,0);
+               fade_in_handle->property_outline_pixels() = 0;
+               fade_in_handle->property_y1() = 2.0;
+               fade_in_handle->property_y2() = 7.0;
+               
+               fade_in_handle->set_data ("regionview", this);
+               
+               fade_out_handle = new ArdourCanvas::SimpleRect (*group);
+               fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,0);
+               fade_out_handle->property_outline_pixels() = 0;
+               fade_out_handle->property_y1() = 2.0;
+               fade_out_handle->property_y2() = 7.0;
+               
+               fade_out_handle->set_data ("regionview", this);
+       }
+
+       string foo = _region.name();
+       foo += ':';
+       foo += "gain";
+
+       gain_line = new AudioRegionGainLine (foo, trackview.session(), *this, *group, audio_region().envelope());
+
+       if (!(_flags & EnvelopeVisible)) {
+               gain_line->hide ();
+       } else {
+               gain_line->show ();
+       }
+
+       reset_width_dependent_items ((double) _region.length() / samples_per_unit);
+
+       gain_line->reset ();
+
+       set_height (trackview.height);
+
+       region_muted ();
+       region_sync_changed ();
+       region_resized (BoundsChanged);
+       set_waveview_data_src();
+       region_locked ();
+       envelope_active_changed ();
+       fade_in_active_changed ();
+       fade_out_active_changed ();
+
+       _region.StateChanged.connect (mem_fun(*this, &AudioRegionView::region_changed));
+
+       fade_in_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_event), fade_in_shape, this));
+       fade_in_handle->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_handle_event), fade_in_handle, this));
+       fade_out_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_event), fade_out_shape, this));
+       fade_out_handle->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_handle_event), fade_out_handle, this));
+
+       set_colors ();
+
+       /* XXX sync mark drag? */
+}
+
+AudioRegionView::~AudioRegionView ()
+{
+       in_destructor = true;
+
+       RegionViewGoingAway (this); /* EMIT_SIGNAL */
+
+       for (vector<GnomeCanvasWaveViewCache *>::iterator cache = wave_caches.begin(); cache != wave_caches.end() ; ++cache) {
+               gnome_canvas_waveview_cache_destroy (*cache);
+       }
+
+       /* all waveviews etc will be destroyed when the group is destroyed */
+
+       if (gain_line) {
+               delete gain_line;
+       }
+}
+
+ARDOUR::AudioRegion&
+AudioRegionView::audio_region() const
+{
+       // "Guaranteed" to succeed...
+       return dynamic_cast<AudioRegion&>(_region);
+}
+
+void
+AudioRegionView::region_changed (Change what_changed)
+{
+       ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionView::region_changed), what_changed));
+
+       RegionView::region_changed(what_changed);
+
+       if (what_changed & AudioRegion::ScaleAmplitudeChanged) {
+               region_scale_amplitude_changed ();
+       }
+       if (what_changed & AudioRegion::FadeInChanged) {
+               fade_in_changed ();
+       }
+       if (what_changed & AudioRegion::FadeOutChanged) {
+               fade_out_changed ();
+       }
+       if (what_changed & AudioRegion::FadeInActiveChanged) {
+               fade_in_active_changed ();
+       }
+       if (what_changed & AudioRegion::FadeOutActiveChanged) {
+               fade_out_active_changed ();
+       }
+       if (what_changed & AudioRegion::EnvelopeActiveChanged) {
+               envelope_active_changed ();
+       }
+}
+
+void
+AudioRegionView::fade_in_changed ()
+{
+       reset_fade_in_shape ();
+}
+
+void
+AudioRegionView::fade_out_changed ()
+{
+       reset_fade_out_shape ();
+}
+
+void
+AudioRegionView::set_fade_in_active (bool yn)
+{
+       audio_region().set_fade_in_active (yn);
+}
+
+void
+AudioRegionView::set_fade_out_active (bool yn)
+{
+       audio_region().set_fade_out_active (yn);
+}
+
+void
+AudioRegionView::fade_in_active_changed ()
+{
+       uint32_t r,g,b,a;
+       uint32_t col;
+       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+
+       if (audio_region().fade_in_active()) {
+               col = RGBA_TO_UINT(r,g,b,120);
+               fade_in_shape->property_fill_color_rgba() = col;
+               fade_in_shape->property_width_pixels() = 0;
+               fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,0);
+       } else { 
+               col = RGBA_TO_UINT(r,g,b,0);
+               fade_in_shape->property_fill_color_rgba() = col;
+               fade_in_shape->property_width_pixels() = 1;
+               fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,255);
+       }
+}
+
+void
+AudioRegionView::fade_out_active_changed ()
+{
+       uint32_t r,g,b,a;
+       uint32_t col;
+       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+
+       if (audio_region().fade_out_active()) {
+               col = RGBA_TO_UINT(r,g,b,120);
+               fade_out_shape->property_fill_color_rgba() = col;
+               fade_out_shape->property_width_pixels() = 0;
+               fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,0);
+       } else { 
+               col = RGBA_TO_UINT(r,g,b,0);
+               fade_out_shape->property_fill_color_rgba() = col;
+               fade_out_shape->property_width_pixels() = 1;
+               fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,255);
+       }
+}
+
+
+void
+AudioRegionView::region_scale_amplitude_changed ()
+{
+       ENSURE_GUI_THREAD (mem_fun(*this, &AudioRegionView::region_scale_amplitude_changed));
+
+       for (uint32_t n = 0; n < waves.size(); ++n) {
+               // force a reload of the cache
+               waves[n]->property_data_src() = &_region;
+       }
+}
+
+void
+AudioRegionView::region_resized (Change what_changed)
+{
+       RegionView::region_resized(what_changed);
+
+       if (what_changed & Change (StartChanged|LengthChanged)) {
+
+               for (uint32_t n = 0; n < waves.size(); ++n) {
+                       waves[n]->property_region_start() = _region.start();
+               }
+               
+               for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+
+                       for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
+                               (*w)->property_region_start() = _region.start();
+                       }
+               }
+       }
+}
+
+void
+AudioRegionView::reset_width_dependent_items (double pixel_width)
+{
+       RegionView::reset_width_dependent_items(pixel_width);
+       assert(_pixel_width == pixel_width);
+
+       if (zero_line) {
+               zero_line->property_x2() = pixel_width - 1.0;
+       }
+
+       if (fade_in_handle) {
+               if (pixel_width <= 6.0) {
+                       fade_in_handle->hide();
+                       fade_out_handle->hide();
+               } else {
+                       if (_height < 5.0) {
+                               fade_in_handle->hide();
+                               fade_out_handle->hide();
+                       } else {
+                               fade_in_handle->show();
+                               fade_out_handle->show();
+                       }
+               }
+       }
+
+       reset_fade_shapes ();
+}
+
+void
+AudioRegionView::region_muted ()
+{
+       RegionView::region_muted();
+
+       for (uint32_t n=0; n < waves.size(); ++n) {
+               if (_region.muted()) {
+                       waves[n]->property_wave_color() = color_map[cMutedWaveForm];
+               } else {
+                       waves[n]->property_wave_color() = color_map[cWaveForm];
+               }
+       }
+}
+
+
+void
+AudioRegionView::set_height (gdouble height)
+{
+       uint32_t wcnt = waves.size();
+
+       // FIXME: ick
+       TimeAxisViewItem::set_height (height - 2);
+       
+       _height = height;
+
+       for (uint32_t n=0; n < wcnt; ++n) {
+               gdouble ht;
+
+               if ((height) <= NAME_HIGHLIGHT_THRESH) {
+                       ht = ((height-2*wcnt) / (double) wcnt);
+               } else {
+                       ht = (((height-2*wcnt) - NAME_HIGHLIGHT_SIZE) / (double) wcnt);
+               }
+               
+               gdouble yoff = n * (ht+1);
+               
+               waves[n]->property_height() = ht;
+               waves[n]->property_y() = yoff + 2;
+       }
+
+       if (gain_line) {
+               if ((height/wcnt) < NAME_HIGHLIGHT_SIZE) {
+                       gain_line->hide ();
+               } else {
+                       if (_flags & EnvelopeVisible) {
+                               gain_line->show ();
+                       }
+               }
+               gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE));
+       }
+
+       manage_zero_line ();
+       reset_fade_shapes ();
+       
+       if (name_text) {
+               name_text->raise_to_top();
+       }
+}
+
+void
+AudioRegionView::manage_zero_line ()
+{
+       if (!zero_line) {
+               return;
+       }
+
+       if (_height >= 100) {
+               gdouble wave_midpoint = (_height - NAME_HIGHLIGHT_SIZE) / 2.0;
+               zero_line->property_y1() = wave_midpoint;
+               zero_line->property_y2() = wave_midpoint;
+               zero_line->show();
+       } else {
+               zero_line->hide();
+       }
+}
+
+void
+AudioRegionView::reset_fade_shapes ()
+{
+       reset_fade_in_shape ();
+       reset_fade_out_shape ();
+}
+
+void
+AudioRegionView::reset_fade_in_shape ()
+{
+       reset_fade_in_shape_width ((jack_nframes_t) audio_region().fade_in().back()->when);
+}
+       
+void
+AudioRegionView::reset_fade_in_shape_width (jack_nframes_t width)
+{
+       if (fade_in_handle == 0) {
+               return;
+       }
+
+       /* smallest size for a fade is 64 frames */
+
+       width = std::max ((jack_nframes_t) 64, width);
+
+       Points* points;
+       double pwidth = width / samples_per_unit;
+       uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth);
+       double h; 
+       
+       if (_height < 5) {
+               fade_in_shape->hide();
+               fade_in_handle->hide();
+               return;
+       }
+
+       double handle_center;
+       handle_center = pwidth;
+       
+       if (handle_center > 7.0) {
+               handle_center -= 3.0;
+       } else {
+               handle_center = 3.0;
+       }
+       
+       fade_in_handle->property_x1() =  handle_center - 3.0;
+       fade_in_handle->property_x2() =  handle_center + 3.0;
+       
+       if (pwidth < 5) {
+               fade_in_shape->hide();
+               return;
+       }
+
+       fade_in_shape->show();
+
+       float curve[npoints];
+       audio_region().fade_in().get_vector (0, audio_region().fade_in().back()->when, curve, npoints);
+
+       points = get_canvas_points ("fade in shape", npoints+3);
+
+       if (_height > NAME_HIGHLIGHT_THRESH) {
+               h = _height - NAME_HIGHLIGHT_SIZE;
+       } else {
+               h = _height;
+       }
+
+       /* points *MUST* be in anti-clockwise order */
+
+       uint32_t pi, pc;
+       double xdelta = pwidth/npoints;
+
+       for (pi = 0, pc = 0; pc < npoints; ++pc) {
+               (*points)[pi].set_x(1 + (pc * xdelta));
+               (*points)[pi++].set_y(2 + (h - (curve[pc] * h)));
+       }
+       
+       /* fold back */
+
+       (*points)[pi].set_x(pwidth);
+       (*points)[pi++].set_y(2);
+
+       (*points)[pi].set_x(1);
+       (*points)[pi++].set_y(2);
+
+       /* connect the dots ... */
+
+       (*points)[pi] = (*points)[0];
+       
+       fade_in_shape->property_points() = *points;
+       delete points;
+}
+
+void
+AudioRegionView::reset_fade_out_shape ()
+{
+       reset_fade_out_shape_width ((jack_nframes_t) audio_region().fade_out().back()->when);
+}
+
+void
+AudioRegionView::reset_fade_out_shape_width (jack_nframes_t width)
+{      
+       if (fade_out_handle == 0) {
+               return;
+       }
+
+       /* smallest size for a fade is 64 frames */
+
+       width = std::max ((jack_nframes_t) 64, width);
+
+       Points* points;
+       double pwidth = width / samples_per_unit;
+       uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth);
+       double h;
+
+       if (_height < 5) {
+               fade_out_shape->hide();
+               fade_out_handle->hide();
+               return;
+       }
+
+       double handle_center;
+       handle_center = (_region.length() - width) / samples_per_unit;
+       
+       if (handle_center > 7.0) {
+               handle_center -= 3.0;
+       } else {
+               handle_center = 3.0;
+       }
+       
+       fade_out_handle->property_x1() =  handle_center - 3.0;
+       fade_out_handle->property_x2() =  handle_center + 3.0;
+
+       /* don't show shape if its too small */
+       
+       if (pwidth < 5) {
+               fade_out_shape->hide();
+               return;
+       } 
+       
+       fade_out_shape->show();
+
+       float curve[npoints];
+       audio_region().fade_out().get_vector (0, audio_region().fade_out().back()->when, curve, npoints);
+
+       if (_height > NAME_HIGHLIGHT_THRESH) {
+               h = _height - NAME_HIGHLIGHT_SIZE;
+       } else {
+               h = _height;
+       }
+
+       /* points *MUST* be in anti-clockwise order */
+
+       points = get_canvas_points ("fade out shape", npoints+3);
+
+       uint32_t pi, pc;
+       double xdelta = pwidth/npoints;
+
+       for (pi = 0, pc = 0; pc < npoints; ++pc) {
+               (*points)[pi].set_x(_pixel_width - 1 - pwidth + (pc*xdelta));
+               (*points)[pi++].set_y(2 + (h - (curve[pc] * h)));
+       }
+       
+       /* fold back */
+
+       (*points)[pi].set_x(_pixel_width);
+       (*points)[pi++].set_y(h);
+
+       (*points)[pi].set_x(_pixel_width);
+       (*points)[pi++].set_y(2);
+
+       /* connect the dots ... */
+
+       (*points)[pi] = (*points)[0];
+
+       fade_out_shape->property_points() = *points;
+       delete points;
+}
+
+void
+AudioRegionView::set_samples_per_unit (gdouble spu)
+{
+       RegionView::set_samples_per_unit (spu);
+
+       for (uint32_t n=0; n < waves.size(); ++n) {
+               waves[n]->property_samples_per_unit() = spu;
+       }
+
+       if (gain_line) {
+               gain_line->reset ();
+       }
+       reset_fade_shapes ();
+}
+
+void
+AudioRegionView::set_amplitude_above_axis (gdouble spp)
+{
+       for (uint32_t n=0; n < waves.size(); ++n) {
+               waves[n]->property_amplitude_above_axis() = spp;
+       }
+}
+
+void
+AudioRegionView::compute_colors (Gdk::Color& basic_color)
+{
+       RegionView::compute_colors(basic_color);
+       
+       uint32_t r, g, b, a;
+
+       /* gain color computed in envelope_active_changed() */
+
+       UINT_TO_RGBA (fill_color, &r, &g, &b, &a);
+       fade_color = RGBA_TO_UINT(r,g,b,120);
+}
+
+void
+AudioRegionView::set_colors ()
+{
+       RegionView::set_colors();
+       
+       if (gain_line) {
+               gain_line->set_line_color (audio_region().envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]);
+       }
+
+       for (uint32_t n=0; n < waves.size(); ++n) {
+               if (_region.muted()) {
+                       waves[n]->property_wave_color() = color_map[cMutedWaveForm];
+               } else {
+                       waves[n]->property_wave_color() = color_map[cWaveForm];
+               }
+       }
+}
+
+void
+AudioRegionView::show_region_editor ()
+{
+       if (editor == 0) {
+               editor = new AudioRegionEditor (trackview.session(), audio_region(), *this);
+               // GTK2FIX : how to ensure float without realizing
+               // editor->realize ();
+               // trackview.editor.ensure_float (*editor);
+       } 
+
+       editor->show_all ();
+       editor->get_window()->raise();
+}
+
+void
+AudioRegionView::set_waveform_visible (bool yn)
+{
+       if (((_flags & WaveformVisible) != yn)) {
+               if (yn) {
+                       for (uint32_t n=0; n < waves.size(); ++n) {
+                               waves[n]->show();
+                       }
+                       _flags |= WaveformVisible;
+               } else {
+                       for (uint32_t n=0; n < waves.size(); ++n) {
+                               waves[n]->hide();
+                       }
+                       _flags &= ~WaveformVisible;
+               }
+               store_flags ();
+       }
+}
+
+void
+AudioRegionView::temporarily_hide_envelope ()
+{
+       if (gain_line) {
+               gain_line->hide ();
+       }
+}
+
+void
+AudioRegionView::unhide_envelope ()
+{
+       if (gain_line && (_flags & EnvelopeVisible)) {
+               gain_line->show ();
+       }
+}
+
+void
+AudioRegionView::set_envelope_visible (bool yn)
+{
+       if (gain_line && ((_flags & EnvelopeVisible) != yn)) {
+               if (yn) {
+                       gain_line->show ();
+                       _flags |= EnvelopeVisible;
+               } else {
+                       gain_line->hide ();
+                       _flags &= ~EnvelopeVisible;
+               }
+               store_flags ();
+       }
+}
+
+void
+AudioRegionView::create_waves ()
+{
+       bool create_zero_line = true;
+
+       RouteTimeAxisView& atv (*(dynamic_cast<RouteTimeAxisView*>(&trackview))); // ick
+
+       if (!atv.get_diskstream()) {
+               return;
+       }
+
+       uint32_t nchans = atv.get_diskstream()->n_channels();
+       
+       /* in tmp_waves, set up null pointers for each channel so the vector is allocated */
+       for (uint32_t n = 0; n < nchans; ++n) {
+               tmp_waves.push_back (0);
+       }
+       
+       for (uint32_t n = 0; n < nchans; ++n) {
+               
+               if (n >= audio_region().n_channels()) {
+                       break;
+               }
+               
+               wave_caches.push_back (WaveView::create_cache ());
+
+               if (wait_for_data) {
+                       if (audio_region().source(n).peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), data_ready_connection)) {
+                               create_one_wave (n, true);
+                       } else {
+                               create_zero_line = false;
+                       }
+               } else {
+                       create_one_wave (n, true);
+               }
+       }
+
+       if (create_zero_line) {
+               zero_line = new ArdourCanvas::SimpleLine (*group);
+               zero_line->property_x1() = (gdouble) 1.0;
+               zero_line->property_x2() = (gdouble) (_region.length() / samples_per_unit) - 1.0;
+               zero_line->property_color_rgba() = (guint) color_map[cZeroLine];
+               manage_zero_line ();
+       }
+}
+
+void
+AudioRegionView::create_one_wave (uint32_t which, bool direct)
+{
+       RouteTimeAxisView& atv (*(dynamic_cast<RouteTimeAxisView*>(&trackview))); // ick
+       uint32_t nchans = atv.get_diskstream()->n_channels();
+       uint32_t n;
+       uint32_t nwaves = std::min (nchans, audio_region().n_channels());
+       gdouble ht;
+
+       if (trackview.height < NAME_HIGHLIGHT_SIZE) {
+               ht = ((trackview.height) / (double) nchans);
+       } else {
+               ht = ((trackview.height - NAME_HIGHLIGHT_SIZE) / (double) nchans);
+       }
+
+       gdouble yoff = which * ht;
+
+       WaveView *wave = new WaveView(*group);
+
+       wave->property_data_src() = (gpointer) &_region;
+       wave->property_cache() =  wave_caches[which];
+       wave->property_cache_updater() = true;
+       wave->property_channel() =  which;
+       wave->property_length_function() = (gpointer) region_length_from_c;
+       wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c;
+       wave->property_peak_function() =  (gpointer) region_read_peaks_from_c;
+       wave->property_x() =  0.0;
+       wave->property_y() =  yoff;
+       wave->property_height() =  (double) ht;
+       wave->property_samples_per_unit() =  samples_per_unit;
+       wave->property_amplitude_above_axis() =  _amplitude_above_axis;
+       wave->property_wave_color() = _region.muted() ? color_map[cMutedWaveForm] : color_map[cWaveForm];
+       wave->property_region_start() = _region.start();
+
+       if (!(_flags & WaveformVisible)) {
+               wave->hide();
+       }
+
+       /* note: calling this function is serialized by the lock
+          held in the peak building thread that signals that
+          peaks are ready for use *or* by the fact that it is
+          called one by one from the GUI thread.
+       */
+
+       if (which < nchans) {
+               tmp_waves[which] = wave;
+       } else {
+               /* n-channel track, >n-channel source */
+       }
+       
+       /* see if we're all ready */
+       
+       for (n = 0; n < nchans; ++n) {
+               if (tmp_waves[n] == 0) {
+                       break;
+               }
+       }
+       
+       if (n == nwaves && waves.empty()) {
+               /* all waves are ready */
+               tmp_waves.resize(nwaves);
+
+               waves = tmp_waves;
+               tmp_waves.clear ();
+
+               if (!zero_line) {
+                       zero_line = new ArdourCanvas::SimpleLine (*group);
+                       zero_line->property_x1() = (gdouble) 1.0;
+                       zero_line->property_x2() = (gdouble) (_region.length() / samples_per_unit) - 1.0;
+                       zero_line->property_color_rgba() = (guint) color_map[cZeroLine];
+                       manage_zero_line ();
+               }
+       }
+}
+
+void
+AudioRegionView::peaks_ready_handler (uint32_t which)
+{
+       Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &AudioRegionView::create_one_wave), which, false));
+
+       if (!waves.empty()) {
+               /* all waves created, don't hook into peaks ready anymore */
+               data_ready_connection.disconnect ();            
+       }
+}
+
+void
+AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
+{
+       if (gain_line == 0) {
+               return;
+       }
+
+       double x, y;
+
+       /* don't create points that can't be seen */
+
+       set_envelope_visible (true);
+       
+       x = ev->button.x;
+       y = ev->button.y;
+
+       item->w2i (x, y);
+
+       jack_nframes_t fx = trackview.editor.pixel_to_frame (x);
+
+       if (fx > _region.length()) {
+               return;
+       }
+
+       /* compute vertical fractional position */
+
+       y = 1.0 - (y / (trackview.height - NAME_HIGHLIGHT_SIZE));
+       
+       /* map using gain line */
+
+       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());
+
+
+       if (!audio_region().envelope_active()) {
+               trackview.session().add_undo( bind( mem_fun(audio_region(), &AudioRegion::set_envelope_active), false) );
+               audio_region().set_envelope_active(true);
+               trackview.session().add_redo( bind( mem_fun(audio_region(), &AudioRegion::set_envelope_active), true) );
+       }
+
+       audio_region().envelope().add (fx, y);
+       
+       trackview.session().add_redo_no_execute (audio_region().envelope().get_memento());
+       trackview.session().commit_reversible_command ();
+}
+
+void
+AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
+{
+        ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
+       audio_region().envelope().erase (cp->model);
+}
+
+void
+AudioRegionView::store_flags()
+{
+       XMLNode *node = new XMLNode ("GUI");
+
+       node->add_property ("waveform-visible", (_flags & WaveformVisible) ? "yes" : "no");
+       node->add_property ("envelope-visible", (_flags & EnvelopeVisible) ? "yes" : "no");
+
+       _region.add_extra_xml (*node);
+}
+
+void
+AudioRegionView::set_flags (XMLNode* node)
+{
+       XMLProperty *prop;
+
+       if ((prop = node->property ("waveform-visible")) != 0) {
+               if (prop->value() == "yes") {
+                       _flags |= WaveformVisible;
+               }
+       }
+
+       if ((prop = node->property ("envelope-visible")) != 0) {
+               if (prop->value() == "yes") {
+                       _flags |= EnvelopeVisible;
+               }
+       }
+}
+       
+void
+AudioRegionView::set_waveform_shape (WaveformShape shape)
+{
+       bool yn;
+
+       /* this slightly odd approach is to leave the door open to 
+          other "shapes" such as spectral displays, etc.
+       */
+
+       switch (shape) {
+       case Rectified:
+               yn = true;
+               break;
+
+       default:
+               yn = false;
+               break;
+       }
+
+       if (yn != (bool) (_flags & WaveformRectified)) {
+               for (vector<WaveView *>::iterator wave = waves.begin(); wave != waves.end() ; ++wave) {
+                       (*wave)->property_rectified() = yn;
+               }
+
+               if (zero_line) {
+                       if (yn) {
+                               zero_line->hide();
+                       } else {
+                               zero_line->show();
+                       }
+               }
+
+               if (yn) {
+                       _flags |= WaveformRectified;
+               } else {
+                       _flags &= ~WaveformRectified;
+               }
+       }
+}
+
+GhostRegion*
+AudioRegionView::add_ghost (AutomationTimeAxisView& atv)
+{
+       RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&trackview);
+       assert(rtv);
+
+       double unit_position = _region.position () / samples_per_unit;
+       GhostRegion* ghost = new GhostRegion (atv, unit_position);
+       uint32_t nchans;
+       
+       nchans = rtv->get_diskstream()->n_channels();
+
+       for (uint32_t n = 0; n < nchans; ++n) {
+               
+               if (n >= audio_region().n_channels()) {
+                       break;
+               }
+               
+               WaveView *wave = new WaveView(*ghost->group);
+
+               wave->property_data_src() =  &_region;
+               wave->property_cache() =  wave_caches[n];
+               wave->property_cache_updater() = false;
+               wave->property_channel() = n;
+               wave->property_length_function() = (gpointer)region_length_from_c;
+               wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c;
+               wave->property_peak_function() =  (gpointer) region_read_peaks_from_c;
+               wave->property_x() =  0.0;
+               wave->property_samples_per_unit() =  samples_per_unit;
+               wave->property_amplitude_above_axis() =  _amplitude_above_axis;
+               wave->property_wave_color() = color_map[cGhostTrackWave];
+               wave->property_region_start() = _region.start();
+
+               ghost->waves.push_back(wave);
+       }
+
+       ghost->set_height ();
+       ghost->set_duration (_region.length() / samples_per_unit);
+       ghosts.push_back (ghost);
+
+       ghost->GoingAway.connect (mem_fun(*this, &AudioRegionView::remove_ghost));
+
+       return ghost;
+}
+
+void
+AudioRegionView::entered ()
+{
+       if (gain_line && _flags & EnvelopeVisible) {
+               gain_line->show_all_control_points ();
+       }
+
+       uint32_t r,g,b,a;
+       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+       a=255;
+       
+       if (fade_in_handle) {
+               fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
+               fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
+       }
+}
+
+void
+AudioRegionView::exited ()
+{
+       if (gain_line) {
+               gain_line->hide_all_but_selected_control_points ();
+       }
+       
+       uint32_t r,g,b,a;
+       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+       a=0;
+       
+       if (fade_in_handle) {
+               fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
+               fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
+       }
+}
+
+void
+AudioRegionView::envelope_active_changed ()
+{
+       if (gain_line) {
+               gain_line->set_line_color (audio_region().envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]);
+       }
+}
+
+void
+AudioRegionView::set_waveview_data_src()
+{
+
+       double unit_length= _region.length() / samples_per_unit;
+
+       for (uint32_t n = 0; n < waves.size(); ++n) {
+               // TODO: something else to let it know the channel
+               waves[n]->property_data_src() = &_region;
+       }
+       
+       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+               
+               (*i)->set_duration (unit_length);
+               
+               for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
+                       (*w)->property_data_src() = &_region;
+               }
+       }
+
+}
+
+void
+AudioRegionView::color_handler (ColorID id, uint32_t val)
+{
+       switch (id) {
+       case cMutedWaveForm:
+       case cWaveForm:
+               set_colors ();
+               break;
+
+       case cGainLineInactive:
+       case cGainLine:
+               envelope_active_changed();
+               break;
+               
+       case cZeroLine:
+               if (zero_line) {
+                       zero_line->property_color_rgba() = (guint) color_map[cZeroLine];
+               }
+               break;
+
+       case cGhostTrackWave:
+               break;
+
+       default:
+               break;
+       }
+}
diff --git a/gtk2_ardour/audio_region_view.h b/gtk2_ardour/audio_region_view.h
new file mode 100644 (file)
index 0000000..ec3ea6c
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+    Copyright (C) 2001-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
+    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.
+*/
+
+#ifndef __gtk_ardour_audio_region_view_h__
+#define __gtk_ardour_audio_region_view_h__
+
+#include <vector>
+
+#include <libgnomecanvasmm.h>
+#include <libgnomecanvasmm/polygon.h>
+#include <sigc++/signal.h>
+#include <ardour/region.h>
+
+#include "region_view.h"
+#include "route_time_axis.h"
+#include "time_axis_view_item.h"
+#include "automation_line.h"
+#include "enums.h"
+#include "waveview.h"
+#include "canvas.h"
+#include "color.h"
+
+namespace ARDOUR {
+       class AudioRegion;
+       class PeakData;
+};
+
+class AudioTimeAxisView;
+class AudioRegionGainLine;
+class AudioRegionEditor;
+class GhostRegion;
+class AutomationTimeAxisView;
+
+class AudioRegionView : public RegionView
+{
+  public:
+       AudioRegionView (ArdourCanvas::Group *, 
+                        RouteTimeAxisView&,
+                        ARDOUR::AudioRegion&,
+                        double initial_samples_per_unit,
+                        Gdk::Color& basic_color);
+
+       ~AudioRegionView ();
+       
+       virtual void init (Gdk::Color& base_color, bool wait_for_data = false);
+       
+       ARDOUR::AudioRegion& audio_region() const;
+    
+    void set_height (double);
+    void set_samples_per_unit (double);
+
+    void set_amplitude_above_axis (gdouble spp);
+
+    void temporarily_hide_envelope (); ///< Dangerous!
+    void unhide_envelope ();           ///< Dangerous!
+
+    void set_envelope_visible (bool);
+    void set_waveform_visible (bool yn);
+    void set_waveform_shape (WaveformShape);
+
+    bool waveform_rectified() const { return _flags & WaveformRectified; }
+    bool waveform_visible()   const { return _flags & WaveformVisible; }
+    bool envelope_visible()   const { return _flags & EnvelopeVisible; }
+    
+    void show_region_editor ();
+
+    void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event);
+    void remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event);
+
+    AudioRegionGainLine* get_gain_line() const { return gain_line; }
+
+    void region_changed (ARDOUR::Change);
+    void envelope_active_changed ();
+
+    GhostRegion* add_ghost (AutomationTimeAxisView&);
+
+    void reset_fade_in_shape_width (jack_nframes_t);
+    void reset_fade_out_shape_width (jack_nframes_t);
+    void set_fade_in_active (bool);
+    void set_fade_out_active (bool);
+
+    virtual void entered ();
+    virtual void exited ();
+
+  protected:
+
+    /* this constructor allows derived types
+       to specify their visibility requirements
+       to the TimeAxisViewItem parent class
+    */
+    
+    AudioRegionView (ArdourCanvas::Group *, 
+                            RouteTimeAxisView&,
+                            ARDOUR::AudioRegion&,
+                            double      samples_per_unit,
+                            Gdk::Color& basic_color,
+                            TimeAxisViewItem::Visibility);
+    
+    enum Flags {
+           EnvelopeVisible = 0x1,
+           WaveformVisible = 0x4,
+           WaveformRectified = 0x8
+    };
+    
+    void reset_fade_shapes ();
+    void reset_fade_in_shape ();
+    void reset_fade_out_shape ();
+    void fade_in_changed ();
+    void fade_out_changed ();
+    void fade_in_active_changed ();
+    void fade_out_active_changed ();
+
+    void region_resized (ARDOUR::Change);
+    void region_moved (void *);
+    void region_muted ();
+    void region_scale_amplitude_changed ();
+
+    void create_waves ();
+    void create_one_wave (uint32_t, bool);
+    void manage_zero_line ();
+    void peaks_ready_handler (uint32_t);
+    void set_flags (XMLNode *);
+    void store_flags ();
+
+    void set_colors ();
+    void compute_colors (Gdk::Color&);
+    void reset_width_dependent_items (double pixel_width);
+    void set_waveview_data_src();
+    
+       void color_handler (ColorID, uint32_t);
+
+    vector<GnomeCanvasWaveViewCache*> wave_caches;
+    vector<ArdourCanvas::WaveView *>  waves;
+    vector<ArdourCanvas::WaveView *>  tmp_waves; ///< see ::create_waves()
+    ArdourCanvas::Polygon*            sync_mark; ///< polgyon for sync position 
+    ArdourCanvas::SimpleLine*         zero_line;
+    ArdourCanvas::Polygon*            fade_in_shape;
+    ArdourCanvas::Polygon*            fade_out_shape;
+    ArdourCanvas::SimpleRect*         fade_in_handle;
+    ArdourCanvas::SimpleRect*         fade_out_handle;
+    AudioRegionGainLine*              gain_line;
+
+    double _amplitude_above_axis;
+
+    uint32_t _flags;
+    uint32_t fade_color;
+};
+
+#endif /* __gtk_ardour_audio_region_view_h__ */
diff --git a/gtk2_ardour/audio_regionview.cc b/gtk2_ardour/audio_regionview.cc
new file mode 100644 (file)
index 0000000..e2d20c0
--- /dev/null
@@ -0,0 +1,1408 @@
+/*
+    Copyright (C) 2001 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: regionview.cc 678 2006-07-11 15:45:19Z paul $
+*/
+
+#include <cmath>
+#include <algorithm>
+
+#include <gtkmm.h>
+
+#include <gtkmm2ext/gtk_ui.h>
+
+#include <ardour/playlist.h>
+#include <ardour/audioregion.h>
+#include <ardour/audiosource.h>
+#include <ardour/audio_diskstream.h>
+
+#include "streamview.h"
+#include "region_view.h"
+#include "audio_time_axis.h"
+#include "simplerect.h"
+#include "simpleline.h"
+#include "waveview.h"
+#include "public_editor.h"
+#include "region_editor.h"
+#include "region_gain_line.h"
+#include "ghostregion.h"
+#include "audio_time_axis.h"
+#include "utils.h"
+#include "rgb_macros.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace sigc;
+using namespace ARDOUR;
+using namespace PBD;
+using namespace Editing;
+using namespace ArdourCanvas;
+
+static const int32_t sync_mark_width = 9;
+
+sigc::signal<void,AudioRegionView*> AudioRegionView::AudioRegionViewGoingAway;
+
+AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, AudioTimeAxisView &tv, AudioRegion& r, double spu,
+                                 Gdk::Color& basic_color)
+       : TimeAxisViewItem (r.name(), *parent, tv, spu, basic_color, r.position(), r.length(),
+                           TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText|
+                                                         TimeAxisViewItem::ShowNameHighlight|
+                                                         TimeAxisViewItem::ShowFrame)),
+         region (r)
+{
+}
+
+AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, AudioTimeAxisView &tv, AudioRegion& r, double spu, 
+                                 Gdk::Color& basic_color, TimeAxisViewItem::Visibility visibility)
+       : TimeAxisViewItem (r.name(), *parent, tv, spu, basic_color, r.position(), r.length(), visibility),
+         region (r)
+{
+}
+
+void
+AudioRegionView::init (double amplitude_above_axis, Gdk::Color& basic_color, bool wfw)
+{
+        ArdourCanvas::Points shape;
+       XMLNode *node;
+
+       editor = 0;
+       valid = true;
+       in_destructor = false;
+       _amplitude_above_axis = amplitude_above_axis;
+       zero_line = 0;
+       wait_for_waves = wfw;
+       _height = 0;
+
+       _flags = 0;
+
+       if ((node = region.extra_xml ("GUI")) != 0) {
+               set_flags (node);
+       } else {
+               _flags = WaveformVisible;
+               store_flags ();
+       }
+
+       if (trackview.editor.new_regionviews_display_gain()) {
+               _flags |= EnvelopeVisible;
+       }
+
+       compute_colors (basic_color);
+
+       create_waves ();
+
+       name_highlight->set_data ("regionview", this);
+       name_text->set_data ("regionview", this);
+
+       //      shape = new ArdourCanvas::Points ();
+
+       /* an equilateral triangle */
+
+       shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1));
+       shape.push_back (Gnome::Art::Point ((sync_mark_width - 1)/2, 1));
+       shape.push_back (Gnome::Art::Point (0, sync_mark_width - 1));
+       shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1));
+
+       sync_mark =  new ArdourCanvas::Polygon (*group);
+       sync_mark->property_points() = shape;
+       sync_mark->property_fill_color_rgba() = fill_color;
+       sync_mark->hide();
+
+       fade_in_shape = new ArdourCanvas::Polygon (*group);
+       fade_in_shape->property_fill_color_rgba() = fade_color;
+       fade_in_shape->set_data ("regionview", this);
+       
+       fade_out_shape = new ArdourCanvas::Polygon (*group);
+       fade_out_shape->property_fill_color_rgba() = fade_color;
+       fade_out_shape->set_data ("regionview", this);
+
+
+       {
+               uint32_t r,g,b,a;
+               UINT_TO_RGBA(fill_color,&r,&g,&b,&a);
+       
+
+               fade_in_handle = new ArdourCanvas::SimpleRect (*group);
+               fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,0);
+               fade_in_handle->property_outline_pixels() = 0;
+               fade_in_handle->property_y1() = 2.0;
+               fade_in_handle->property_y2() = 7.0;
+               
+               fade_in_handle->set_data ("regionview", this);
+               
+               fade_out_handle = new ArdourCanvas::SimpleRect (*group);
+               fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,0);
+               fade_out_handle->property_outline_pixels() = 0;
+               fade_out_handle->property_y1() = 2.0;
+               fade_out_handle->property_y2() = 7.0;
+               
+               fade_out_handle->set_data ("regionview", this);
+       }
+
+       string foo = region.name();
+       foo += ':';
+       foo += "gain";
+
+       gain_line = new AudioRegionGainLine (foo, trackview.session(), *this, *group, region.envelope());
+
+       if (!(_flags & EnvelopeVisible)) {
+               gain_line->hide ();
+       } else {
+               gain_line->show ();
+       }
+
+       reset_width_dependent_items ((double) region.length() / samples_per_unit);
+
+       gain_line->reset ();
+
+       set_height (trackview.height);
+
+       region_muted ();
+       region_sync_changed ();
+       region_resized (BoundsChanged);
+       set_waveview_data_src();
+       region_locked ();
+       envelope_active_changed ();
+       fade_in_active_changed ();
+       fade_out_active_changed ();
+
+       region.StateChanged.connect (mem_fun(*this, &AudioRegionView::region_changed));
+
+       group->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_event), group, this));
+       name_highlight->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_name_highlight_event), name_highlight, this));
+       fade_in_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_event), fade_in_shape, this));
+       fade_in_handle->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_handle_event), fade_in_handle, this));
+       fade_out_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_event), fade_out_shape, this));
+       fade_out_handle->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_handle_event), fade_out_handle, this));
+
+       set_colors ();
+
+       ColorChanged.connect (mem_fun (*this, &AudioRegionView::color_handler));
+
+       /* XXX sync mark drag? */
+}
+
+AudioRegionView::~AudioRegionView ()
+{
+       in_destructor = true;
+
+       AudioRegionViewGoingAway (this); /* EMIT_SIGNAL */
+
+       for (vector<GnomeCanvasWaveViewCache *>::iterator cache = wave_caches.begin(); cache != wave_caches.end() ; ++cache) {
+               gnome_canvas_waveview_cache_destroy (*cache);
+       }
+
+       /* all waveviews etc will be destroyed when the group is destroyed */
+
+       for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
+               delete *g;
+       }
+
+       if (editor) {
+               delete editor;
+       }
+
+       if (gain_line) {
+               delete gain_line;
+       }
+}
+
+gint
+AudioRegionView::_lock_toggle (ArdourCanvas::Item* item, GdkEvent* ev, void* arg)
+{
+       switch (ev->type) {
+       case GDK_BUTTON_RELEASE:
+               static_cast<AudioRegionView*>(arg)->lock_toggle ();
+               return TRUE;
+               break;
+       default:
+               break;
+       } 
+       return FALSE;
+}
+
+void
+AudioRegionView::lock_toggle ()
+{
+       region.set_locked (!region.locked());
+}
+
+void
+AudioRegionView::region_changed (Change what_changed)
+{
+       ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionView::region_changed), what_changed));
+
+       if (what_changed & BoundsChanged) {
+               region_resized (what_changed);
+               region_sync_changed ();
+       }
+       if (what_changed & Region::MuteChanged) {
+               region_muted ();
+       }
+       if (what_changed & Region::OpacityChanged) {
+               region_opacity ();
+       }
+       if (what_changed & ARDOUR::NameChanged) {
+               region_renamed ();
+       }
+       if (what_changed & Region::SyncOffsetChanged) {
+               region_sync_changed ();
+       }
+       if (what_changed & Region::LayerChanged) {
+               region_layered ();
+       }
+       if (what_changed & Region::LockChanged) {
+               region_locked ();
+       }
+       if (what_changed & AudioRegion::ScaleAmplitudeChanged) {
+               region_scale_amplitude_changed ();
+       }
+       if (what_changed & AudioRegion::FadeInChanged) {
+               fade_in_changed ();
+       }
+       if (what_changed & AudioRegion::FadeOutChanged) {
+               fade_out_changed ();
+       }
+       if (what_changed & AudioRegion::FadeInActiveChanged) {
+               fade_in_active_changed ();
+       }
+       if (what_changed & AudioRegion::FadeOutActiveChanged) {
+               fade_out_active_changed ();
+       }
+       if (what_changed & AudioRegion::EnvelopeActiveChanged) {
+               envelope_active_changed ();
+       }
+}
+
+void
+AudioRegionView::fade_in_changed ()
+{
+       reset_fade_in_shape ();
+}
+
+void
+AudioRegionView::fade_out_changed ()
+{
+       reset_fade_out_shape ();
+}
+
+void
+AudioRegionView::set_fade_in_active (bool yn)
+{
+       region.set_fade_in_active (yn);
+}
+
+void
+AudioRegionView::set_fade_out_active (bool yn)
+{
+       region.set_fade_out_active (yn);
+}
+
+void
+AudioRegionView::fade_in_active_changed ()
+{
+       uint32_t r,g,b,a;
+       uint32_t col;
+       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+
+       if (region.fade_in_active()) {
+               col = RGBA_TO_UINT(r,g,b,120);
+               fade_in_shape->property_fill_color_rgba() = col;
+               fade_in_shape->property_width_pixels() = 0;
+               fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,0);
+       } else { 
+               col = RGBA_TO_UINT(r,g,b,0);
+               fade_in_shape->property_fill_color_rgba() = col;
+               fade_in_shape->property_width_pixels() = 1;
+               fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,255);
+       }
+}
+
+void
+AudioRegionView::fade_out_active_changed ()
+{
+       uint32_t r,g,b,a;
+       uint32_t col;
+       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+
+       if (region.fade_out_active()) {
+               col = RGBA_TO_UINT(r,g,b,120);
+               fade_out_shape->property_fill_color_rgba() = col;
+               fade_out_shape->property_width_pixels() = 0;
+               fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,0);
+       } else { 
+               col = RGBA_TO_UINT(r,g,b,0);
+               fade_out_shape->property_fill_color_rgba() = col;
+               fade_out_shape->property_width_pixels() = 1;
+               fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,255);
+       }
+}
+
+
+void
+AudioRegionView::region_scale_amplitude_changed ()
+{
+       ENSURE_GUI_THREAD (mem_fun(*this, &AudioRegionView::region_scale_amplitude_changed));
+
+       for (uint32_t n = 0; n < waves.size(); ++n) {
+               // force a reload of the cache
+               waves[n]->property_data_src() = &region;
+       }
+}
+
+void
+AudioRegionView::region_locked ()
+{
+       /* name will show locked status */
+       region_renamed ();
+}
+
+void
+AudioRegionView::region_resized (Change what_changed)
+{
+       double unit_length;
+
+       if (what_changed & ARDOUR::PositionChanged) {
+               set_position (region.position(), 0);
+       }
+
+       if (what_changed & Change (StartChanged|LengthChanged)) {
+
+               set_duration (region.length(), 0);
+
+               unit_length = region.length() / samples_per_unit;
+               
+               reset_width_dependent_items (unit_length);
+               
+               for (uint32_t n = 0; n < waves.size(); ++n) {
+                       waves[n]->property_region_start() = region.start();
+               }
+               
+               for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+
+                       (*i)->set_duration (unit_length);
+
+                       for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
+                               (*w)->property_region_start() = region.start();
+                       }
+               }
+       }
+}
+
+void
+AudioRegionView::reset_width_dependent_items (double pixel_width)
+{
+       TimeAxisViewItem::reset_width_dependent_items (pixel_width);
+       _pixel_width = pixel_width;
+
+       if (zero_line) {
+               zero_line->property_x2() = pixel_width - 1.0;
+       }
+
+       if (fade_in_handle) {
+               if (pixel_width <= 6.0) {
+                       fade_in_handle->hide();
+                       fade_out_handle->hide();
+               } else {
+                       if (_height < 5.0) {
+                               fade_in_handle->hide();
+                               fade_out_handle->hide();
+                       } else {
+                               fade_in_handle->show();
+                               fade_out_handle->show();
+                       }
+               }
+       }
+
+       reset_fade_shapes ();
+}
+
+void
+AudioRegionView::region_layered ()
+{
+       AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (&get_time_axis_view());
+       atv->view->region_layered (this);
+}
+       
+void
+AudioRegionView::region_muted ()
+{
+       set_frame_color ();
+       region_renamed ();
+
+       for (uint32_t n=0; n < waves.size(); ++n) {
+               if (region.muted()) {
+                       waves[n]->property_wave_color() = color_map[cMutedWaveForm];
+               } else {
+                       waves[n]->property_wave_color() = color_map[cWaveForm];
+               }
+       }
+}
+
+void
+AudioRegionView::region_opacity ()
+{
+       set_frame_color ();
+}
+
+void
+AudioRegionView::raise ()
+{
+       region.raise ();
+}
+
+void
+AudioRegionView::raise_to_top ()
+{
+       region.raise_to_top ();
+}
+
+void
+AudioRegionView::lower ()
+{
+       region.lower ();
+}
+
+void
+AudioRegionView::lower_to_bottom ()
+{
+       region.lower_to_bottom ();
+}
+
+bool
+AudioRegionView::set_position (jack_nframes_t pos, void* src, double* ignored)
+{
+       double delta;
+       bool ret;
+
+       if (!(ret = TimeAxisViewItem::set_position (pos, this, &delta))) {
+               return false;
+       }
+
+       if (ignored) {
+               *ignored = delta;
+       }
+
+       if (delta) {
+               for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+                       (*i)->group->move (delta, 0.0);
+               }
+       }
+
+       return ret;
+}
+
+void
+AudioRegionView::set_height (gdouble height)
+{
+       uint32_t wcnt = waves.size();
+
+       TimeAxisViewItem::set_height (height - 2);
+       
+       _height = height;
+
+       for (uint32_t n=0; n < wcnt; ++n) {
+               gdouble ht;
+
+               if ((height) <= NAME_HIGHLIGHT_THRESH) {
+                       ht = ((height-2*wcnt) / (double) wcnt);
+               } else {
+                       ht = (((height-2*wcnt) - NAME_HIGHLIGHT_SIZE) / (double) wcnt);
+               }
+               
+               gdouble yoff = n * (ht+1);
+               
+               waves[n]->property_height() = ht;
+               waves[n]->property_y() = yoff + 2;
+       }
+
+       if (gain_line) {
+               if ((height/wcnt) < NAME_HIGHLIGHT_SIZE) {
+                       gain_line->hide ();
+               } else {
+                       if (_flags & EnvelopeVisible) {
+                               gain_line->show ();
+                       }
+               }
+               gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE));
+       }
+
+       manage_zero_line ();
+       reset_fade_shapes ();
+       
+       if (name_text) {
+               name_text->raise_to_top();
+       }
+}
+
+void
+AudioRegionView::manage_zero_line ()
+{
+       if (!zero_line) {
+               return;
+       }
+
+       if (_height >= 100) {
+               gdouble wave_midpoint = (_height - NAME_HIGHLIGHT_SIZE) / 2.0;
+               zero_line->property_y1() = wave_midpoint;
+               zero_line->property_y2() = wave_midpoint;
+               zero_line->show();
+       } else {
+               zero_line->hide();
+       }
+}
+
+void
+AudioRegionView::reset_fade_shapes ()
+{
+       reset_fade_in_shape ();
+       reset_fade_out_shape ();
+}
+
+void
+AudioRegionView::reset_fade_in_shape ()
+{
+       reset_fade_in_shape_width ((jack_nframes_t) region.fade_in().back()->when);
+}
+       
+void
+AudioRegionView::reset_fade_in_shape_width (jack_nframes_t width)
+{
+       if (fade_in_handle == 0) {
+               return;
+       }
+
+       /* smallest size for a fade is 64 frames */
+
+       width = std::max ((jack_nframes_t) 64, width);
+
+       Points* points;
+       double pwidth = width / samples_per_unit;
+       uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth);
+       double h; 
+       
+       if (_height < 5) {
+               fade_in_shape->hide();
+               fade_in_handle->hide();
+               return;
+       }
+
+       double handle_center;
+       handle_center = pwidth;
+       
+       if (handle_center > 7.0) {
+               handle_center -= 3.0;
+       } else {
+               handle_center = 3.0;
+       }
+       
+       fade_in_handle->property_x1() =  handle_center - 3.0;
+       fade_in_handle->property_x2() =  handle_center + 3.0;
+       
+       if (pwidth < 5) {
+               fade_in_shape->hide();
+               return;
+       }
+
+       fade_in_shape->show();
+
+       float curve[npoints];
+       region.fade_in().get_vector (0, region.fade_in().back()->when, curve, npoints);
+
+       points = get_canvas_points ("fade in shape", npoints+3);
+
+       if (_height > NAME_HIGHLIGHT_THRESH) {
+               h = _height - NAME_HIGHLIGHT_SIZE;
+       } else {
+               h = _height;
+       }
+
+       /* points *MUST* be in anti-clockwise order */
+
+       uint32_t pi, pc;
+       double xdelta = pwidth/npoints;
+
+       for (pi = 0, pc = 0; pc < npoints; ++pc) {
+               (*points)[pi].set_x(1 + (pc * xdelta));
+               (*points)[pi++].set_y(2 + (h - (curve[pc] * h)));
+       }
+       
+       /* fold back */
+
+       (*points)[pi].set_x(pwidth);
+       (*points)[pi++].set_y(2);
+
+       (*points)[pi].set_x(1);
+       (*points)[pi++].set_y(2);
+
+       /* connect the dots ... */
+
+       (*points)[pi] = (*points)[0];
+       
+       fade_in_shape->property_points() = *points;
+       delete points;
+}
+
+void
+AudioRegionView::reset_fade_out_shape ()
+{
+       reset_fade_out_shape_width ((jack_nframes_t) region.fade_out().back()->when);
+}
+
+void
+AudioRegionView::reset_fade_out_shape_width (jack_nframes_t width)
+{      
+       if (fade_out_handle == 0) {
+               return;
+       }
+
+       /* smallest size for a fade is 64 frames */
+
+       width = std::max ((jack_nframes_t) 64, width);
+
+       Points* points;
+       double pwidth = width / samples_per_unit;
+       uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth);
+       double h;
+
+       if (_height < 5) {
+               fade_out_shape->hide();
+               fade_out_handle->hide();
+               return;
+       }
+
+       double handle_center;
+       handle_center = (region.length() - width) / samples_per_unit;
+       
+       if (handle_center > 7.0) {
+               handle_center -= 3.0;
+       } else {
+               handle_center = 3.0;
+       }
+       
+       fade_out_handle->property_x1() =  handle_center - 3.0;
+       fade_out_handle->property_x2() =  handle_center + 3.0;
+
+       /* don't show shape if its too small */
+       
+       if (pwidth < 5) {
+               fade_out_shape->hide();
+               return;
+       } 
+       
+       fade_out_shape->show();
+
+       float curve[npoints];
+       region.fade_out().get_vector (0, region.fade_out().back()->when, curve, npoints);
+
+       if (_height > NAME_HIGHLIGHT_THRESH) {
+               h = _height - NAME_HIGHLIGHT_SIZE;
+       } else {
+               h = _height;
+       }
+
+       /* points *MUST* be in anti-clockwise order */
+
+       points = get_canvas_points ("fade out shape", npoints+3);
+
+       uint32_t pi, pc;
+       double xdelta = pwidth/npoints;
+
+       for (pi = 0, pc = 0; pc < npoints; ++pc) {
+               (*points)[pi].set_x(_pixel_width - 1 - pwidth + (pc*xdelta));
+               (*points)[pi++].set_y(2 + (h - (curve[pc] * h)));
+       }
+       
+       /* fold back */
+
+       (*points)[pi].set_x(_pixel_width);
+       (*points)[pi++].set_y(h);
+
+       (*points)[pi].set_x(_pixel_width);
+       (*points)[pi++].set_y(2);
+
+       /* connect the dots ... */
+
+       (*points)[pi] = (*points)[0];
+
+       fade_out_shape->property_points() = *points;
+       delete points;
+}
+
+void
+AudioRegionView::set_samples_per_unit (gdouble spu)
+{
+       TimeAxisViewItem::set_samples_per_unit (spu);
+
+       for (uint32_t n=0; n < waves.size(); ++n) {
+               waves[n]->property_samples_per_unit() = spu;
+       }
+
+       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+               (*i)->set_samples_per_unit (spu);
+               (*i)->set_duration (region.length() / samples_per_unit);
+       }
+
+       if (gain_line) {
+               gain_line->reset ();
+       }
+       reset_fade_shapes ();
+       region_sync_changed ();
+}
+
+bool
+AudioRegionView::set_duration (jack_nframes_t frames, void *src)
+{
+       if (!TimeAxisViewItem::set_duration (frames, src)) {
+               return false;
+       }
+       
+       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+               (*i)->set_duration (region.length() / samples_per_unit);
+       }
+
+       return true;
+}
+
+void
+AudioRegionView::set_amplitude_above_axis (gdouble spp)
+{
+       for (uint32_t n=0; n < waves.size(); ++n) {
+               waves[n]->property_amplitude_above_axis() = spp;
+       }
+}
+
+void
+AudioRegionView::compute_colors (Gdk::Color& basic_color)
+{
+       TimeAxisViewItem::compute_colors (basic_color);
+       uint32_t r, g, b, a;
+
+       /* gain color computed in envelope_active_changed() */
+
+       UINT_TO_RGBA (fill_color, &r, &g, &b, &a);
+       fade_color = RGBA_TO_UINT(r,g,b,120);
+}
+
+void
+AudioRegionView::set_colors ()
+{
+       TimeAxisViewItem::set_colors ();
+       
+       if (gain_line) {
+               gain_line->set_line_color (region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]);
+       }
+
+       if (sync_mark) {
+               sync_mark->property_fill_color_rgba() = fill_color;
+       }
+
+       for (uint32_t n=0; n < waves.size(); ++n) {
+               if (region.muted()) {
+                       waves[n]->property_wave_color() = color_map[cMutedWaveForm];
+               } else {
+                       waves[n]->property_wave_color() = color_map[cWaveForm];
+               }
+       }
+}
+
+void
+AudioRegionView::set_frame_color ()
+{
+       if (region.opaque()) {
+               fill_opacity = 180;
+       } else {
+               fill_opacity = 100;
+       }
+
+       TimeAxisViewItem::set_frame_color ();
+}
+
+void
+AudioRegionView::show_region_editor ()
+{
+       if (editor == 0) {
+               editor = new AudioRegionEditor (trackview.session(), region, *this);
+               // GTK2FIX : how to ensure float without realizing
+               // editor->realize ();
+               // trackview.editor.ensure_float (*editor);
+       } 
+
+       editor->show_all ();
+       editor->get_window()->raise();
+}
+
+void
+AudioRegionView::hide_region_editor()
+{
+       if (editor) {
+               editor->hide_all ();
+       }
+}
+
+void
+AudioRegionView::region_renamed ()
+{
+       string str;
+
+       if (region.locked()) {
+               str += '>';
+               str += region.name();
+               str += '<';
+       } else {
+               str = region.name();
+       }
+
+       if (region.speed_mismatch (trackview.session().frame_rate())) {
+               str = string ("*") + str;
+       }
+
+       if (region.muted()) {
+               str = string ("!") + str;
+       }
+
+       set_item_name (str, this);
+       set_name_text (str);
+}
+
+void
+AudioRegionView::region_sync_changed ()
+{
+       if (sync_mark == 0) {
+               return;
+       }
+
+       int sync_dir;
+       jack_nframes_t sync_offset;
+
+       sync_offset = region.sync_offset (sync_dir);
+
+       /* this has to handle both a genuine change of position, a change of samples_per_unit,
+          and a change in the bounds of the region.
+        */
+
+       if (sync_offset == 0) {
+
+               /* no sync mark - its the start of the region */
+
+               sync_mark->hide();
+
+       } else {
+
+               if ((sync_dir < 0) || ((sync_dir > 0) && (sync_offset > region.length()))) { 
+
+                       /* no sync mark - its out of the bounds of the region */
+
+                       sync_mark->hide();
+
+               } else {
+
+                       /* lets do it */
+
+                       Points points;
+                       
+                       //points = sync_mark->property_points().get_value();
+                       
+                       double offset = sync_offset / samples_per_unit;
+                       points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1));
+                       points.push_back (Gnome::Art::Point (offset + ((sync_mark_width-1)/2), 1));
+                       points.push_back (Gnome::Art::Point (offset, sync_mark_width - 1));
+                       points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1));     
+                       sync_mark->property_points().set_value (points);
+                       sync_mark->show();
+
+               }
+       }
+}
+
+void
+AudioRegionView::set_waveform_visible (bool yn)
+{
+       if (((_flags & WaveformVisible) != yn)) {
+               if (yn) {
+                       for (uint32_t n=0; n < waves.size(); ++n) {
+                               waves[n]->show();
+                       }
+                       _flags |= WaveformVisible;
+               } else {
+                       for (uint32_t n=0; n < waves.size(); ++n) {
+                               waves[n]->hide();
+                       }
+                       _flags &= ~WaveformVisible;
+               }
+               store_flags ();
+       }
+}
+
+void
+AudioRegionView::temporarily_hide_envelope ()
+{
+       if (gain_line) {
+               gain_line->hide ();
+       }
+}
+
+void
+AudioRegionView::unhide_envelope ()
+{
+       if (gain_line && (_flags & EnvelopeVisible)) {
+               gain_line->show ();
+       }
+}
+
+void
+AudioRegionView::set_envelope_visible (bool yn)
+{
+       if (gain_line && ((_flags & EnvelopeVisible) != yn)) {
+               if (yn) {
+                       gain_line->show ();
+                       _flags |= EnvelopeVisible;
+               } else {
+                       gain_line->hide ();
+                       _flags &= ~EnvelopeVisible;
+               }
+               store_flags ();
+       }
+}
+
+void
+AudioRegionView::create_waves ()
+{
+       bool create_zero_line = true;
+
+       AudioTimeAxisView& atv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick
+
+       if (!atv.get_diskstream()) {
+               return;
+       }
+
+       uint32_t nchans = atv.get_diskstream()->n_channels();
+       
+       /* in tmp_waves, set up null pointers for each channel so the vector is allocated */
+       for (uint32_t n = 0; n < nchans; ++n) {
+               tmp_waves.push_back (0);
+       }
+       
+       for (uint32_t n = 0; n < nchans; ++n) {
+               
+               if (n >= region.n_channels()) {
+                       break;
+               }
+               
+               wave_caches.push_back (WaveView::create_cache ());
+
+               if (wait_for_waves) {
+                       if (region.source(n).peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), peaks_ready_connection)) {
+                               create_one_wave (n, true);
+                       } else {
+                               create_zero_line = false;
+                       }
+               } else {
+                       create_one_wave (n, true);
+               }
+       }
+
+       if (create_zero_line) {
+               zero_line = new ArdourCanvas::SimpleLine (*group);
+               zero_line->property_x1() = (gdouble) 1.0;
+               zero_line->property_x2() = (gdouble) (region.length() / samples_per_unit) - 1.0;
+               zero_line->property_color_rgba() = (guint) color_map[cZeroLine];
+               manage_zero_line ();
+       }
+}
+
+void
+AudioRegionView::create_one_wave (uint32_t which, bool direct)
+{
+       AudioTimeAxisView& atv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick
+       uint32_t nchans = atv.get_diskstream()->n_channels();
+       uint32_t n;
+       uint32_t nwaves = std::min (nchans, region.n_channels());
+       gdouble ht;
+
+       if (trackview.height < NAME_HIGHLIGHT_SIZE) {
+               ht = ((trackview.height) / (double) nchans);
+       } else {
+               ht = ((trackview.height - NAME_HIGHLIGHT_SIZE) / (double) nchans);
+       }
+
+       gdouble yoff = which * ht;
+
+       WaveView *wave = new WaveView(*group);
+
+       wave->property_data_src() = (gpointer) &region;
+       wave->property_cache() =  wave_caches[which];
+       wave->property_cache_updater() = true;
+       wave->property_channel() =  which;
+       wave->property_length_function() = (gpointer) region_length_from_c;
+       wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c;
+       wave->property_peak_function() =  (gpointer) region_read_peaks_from_c;
+       wave->property_x() =  0.0;
+       wave->property_y() =  yoff;
+       wave->property_height() =  (double) ht;
+       wave->property_samples_per_unit() =  samples_per_unit;
+       wave->property_amplitude_above_axis() =  _amplitude_above_axis;
+       wave->property_wave_color() = region.muted() ? color_map[cMutedWaveForm] : color_map[cWaveForm];
+       wave->property_region_start() = region.start();
+
+       if (!(_flags & WaveformVisible)) {
+               wave->hide();
+       }
+
+       /* note: calling this function is serialized by the lock
+          held in the peak building thread that signals that
+          peaks are ready for use *or* by the fact that it is
+          called one by one from the GUI thread.
+       */
+
+       if (which < nchans) {
+               tmp_waves[which] = wave;
+       } else {
+               /* n-channel track, >n-channel source */
+       }
+       
+       /* see if we're all ready */
+       
+       for (n = 0; n < nchans; ++n) {
+               if (tmp_waves[n] == 0) {
+                       break;
+               }
+       }
+       
+       if (n == nwaves && waves.empty()) {
+               /* all waves are ready */
+               tmp_waves.resize(nwaves);
+
+               waves = tmp_waves;
+               tmp_waves.clear ();
+
+               if (!zero_line) {
+                       zero_line = new ArdourCanvas::SimpleLine (*group);
+                       zero_line->property_x1() = (gdouble) 1.0;
+                       zero_line->property_x2() = (gdouble) (region.length() / samples_per_unit) - 1.0;
+                       zero_line->property_color_rgba() = (guint) color_map[cZeroLine];
+                       manage_zero_line ();
+               }
+       }
+}
+
+void
+AudioRegionView::peaks_ready_handler (uint32_t which)
+{
+       Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &AudioRegionView::create_one_wave), which, false));
+
+       if (!waves.empty()) {
+               /* all waves created, don't hook into peaks ready anymore */
+               peaks_ready_connection.disconnect ();           
+       }
+}
+
+void
+AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
+{
+       if (gain_line == 0) {
+               return;
+       }
+
+       double x, y;
+
+       /* don't create points that can't be seen */
+
+       set_envelope_visible (true);
+       
+       x = ev->button.x;
+       y = ev->button.y;
+
+       item->w2i (x, y);
+
+       jack_nframes_t fx = trackview.editor.pixel_to_frame (x);
+
+       if (fx > region.length()) {
+               return;
+       }
+
+       /* compute vertical fractional position */
+
+       y = 1.0 - (y / (trackview.height - NAME_HIGHLIGHT_SIZE));
+       
+       /* map using gain line */
+
+       gain_line->view_to_model_y (y);
+
+       trackview.session().begin_reversible_command (_("add gain control point"));
+       trackview.session().add_undo (region.envelope().get_memento());
+
+
+       if (!region.envelope_active()) {
+               trackview.session().add_undo( bind( mem_fun(region, &AudioRegion::set_envelope_active), false) );
+               region.set_envelope_active(true);
+               trackview.session().add_redo( bind( mem_fun(region, &AudioRegion::set_envelope_active), true) );
+       }
+
+       region.envelope().add (fx, y);
+       
+       trackview.session().add_redo_no_execute (region.envelope().get_memento());
+       trackview.session().commit_reversible_command ();
+}
+
+void
+AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
+{
+        ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
+       region.envelope().erase (cp->model);
+}
+
+void
+AudioRegionView::store_flags()
+{
+       XMLNode *node = new XMLNode ("GUI");
+
+       node->add_property ("waveform-visible", (_flags & WaveformVisible) ? "yes" : "no");
+       node->add_property ("envelope-visible", (_flags & EnvelopeVisible) ? "yes" : "no");
+
+       region.add_extra_xml (*node);
+}
+
+void
+AudioRegionView::set_flags (XMLNode* node)
+{
+       XMLProperty *prop;
+
+       if ((prop = node->property ("waveform-visible")) != 0) {
+               if (prop->value() == "yes") {
+                       _flags |= WaveformVisible;
+               }
+       }
+
+       if ((prop = node->property ("envelope-visible")) != 0) {
+               if (prop->value() == "yes") {
+                       _flags |= EnvelopeVisible;
+               }
+       }
+}
+       
+void
+AudioRegionView::set_waveform_shape (WaveformShape shape)
+{
+       bool yn;
+
+       /* this slightly odd approach is to leave the door open to 
+          other "shapes" such as spectral displays, etc.
+       */
+
+       switch (shape) {
+       case Rectified:
+               yn = true;
+               break;
+
+       default:
+               yn = false;
+               break;
+       }
+
+       if (yn != (bool) (_flags & WaveformRectified)) {
+               for (vector<WaveView *>::iterator wave = waves.begin(); wave != waves.end() ; ++wave) {
+                       (*wave)->property_rectified() = yn;
+               }
+
+               if (zero_line) {
+                       if (yn) {
+                               zero_line->hide();
+                       } else {
+                               zero_line->show();
+                       }
+               }
+
+               if (yn) {
+                       _flags |= WaveformRectified;
+               } else {
+                       _flags &= ~WaveformRectified;
+               }
+       }
+}
+
+void
+AudioRegionView::move (double x_delta, double y_delta)
+{
+       if (region.locked() || (x_delta == 0 && y_delta == 0)) {
+               return;
+       }
+
+       get_canvas_group()->move (x_delta, y_delta);
+
+       /* note: ghosts never leave their tracks so y_delta for them is always zero */
+
+       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+               (*i)->group->move (x_delta, 0.0);
+       }
+}
+
+GhostRegion*
+AudioRegionView::add_ghost (AutomationTimeAxisView& atv)
+{
+       AudioTimeAxisView& myatv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick
+       double unit_position = region.position () / samples_per_unit;
+       GhostRegion* ghost = new GhostRegion (atv, unit_position);
+       uint32_t nchans;
+       
+       nchans = myatv.get_diskstream()->n_channels();
+
+       for (uint32_t n = 0; n < nchans; ++n) {
+               
+               if (n >= region.n_channels()) {
+                       break;
+               }
+               
+               WaveView *wave = new WaveView(*ghost->group);
+
+               wave->property_data_src() =  &region;
+               wave->property_cache() =  wave_caches[n];
+               wave->property_cache_updater() = false;
+               wave->property_channel() = n;
+               wave->property_length_function() = (gpointer)region_length_from_c;
+               wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c;
+               wave->property_peak_function() =  (gpointer) region_read_peaks_from_c;
+               wave->property_x() =  0.0;
+               wave->property_samples_per_unit() =  samples_per_unit;
+               wave->property_amplitude_above_axis() =  _amplitude_above_axis;
+               wave->property_wave_color() = color_map[cGhostTrackWave];
+               wave->property_region_start() = region.start();
+
+               ghost->waves.push_back(wave);
+       }
+
+       ghost->set_height ();
+       ghost->set_duration (region.length() / samples_per_unit);
+       ghosts.push_back (ghost);
+
+       ghost->GoingAway.connect (mem_fun(*this, &AudioRegionView::remove_ghost));
+
+       return ghost;
+}
+
+void
+AudioRegionView::remove_ghost (GhostRegion* ghost)
+{
+       if (in_destructor) {
+               return;
+       }
+
+       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+               if (*i == ghost) {
+                       ghosts.erase (i);
+                       break;
+               }
+       }
+}
+
+uint32_t
+AudioRegionView::get_fill_color ()
+{
+       return fill_color;
+}
+
+void
+AudioRegionView::entered ()
+{
+       if (gain_line && _flags & EnvelopeVisible) {
+               gain_line->show_all_control_points ();
+       }
+
+       uint32_t r,g,b,a;
+       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+       a=255;
+       
+       if (fade_in_handle) {
+               fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
+               fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
+       }
+}
+
+void
+AudioRegionView::exited ()
+{
+       if (gain_line) {
+               gain_line->hide_all_but_selected_control_points ();
+       }
+       
+       uint32_t r,g,b,a;
+       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+       a=0;
+       
+       if (fade_in_handle) {
+               fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
+               fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
+       }
+}
+
+void
+AudioRegionView::envelope_active_changed ()
+{
+       if (gain_line) {
+               gain_line->set_line_color (region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]);
+       }
+}
+
+void
+AudioRegionView::set_waveview_data_src()
+{
+
+       double unit_length= region.length() / samples_per_unit;
+
+       for (uint32_t n = 0; n < waves.size(); ++n) {
+               // TODO: something else to let it know the channel
+               waves[n]->property_data_src() = &region;
+       }
+       
+       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+               
+               (*i)->set_duration (unit_length);
+               
+               for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
+                       (*w)->property_data_src() = &region;
+               }
+       }
+
+}
+
+void
+AudioRegionView::color_handler (ColorID id, uint32_t val)
+{
+       switch (id) {
+       case cMutedWaveForm:
+       case cWaveForm:
+               set_colors ();
+               break;
+
+       case cGainLineInactive:
+       case cGainLine:
+               envelope_active_changed();
+               break;
+               
+       case cZeroLine:
+               if (zero_line) {
+                       zero_line->property_color_rgba() = (guint) color_map[cZeroLine];
+               }
+               break;
+
+       case cGhostTrackWave:
+               break;
+
+       default:
+               break;
+       }
+}
diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc
new file mode 100644 (file)
index 0000000..8234994
--- /dev/null
@@ -0,0 +1,700 @@
+/*
+    Copyright (C) 2001, 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
+    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 <cmath>
+#include <cassert>
+
+#include <gtkmm.h>
+
+#include <gtkmm2ext/gtk_ui.h>
+
+#include <ardour/audioplaylist.h>
+#include <ardour/audioregion.h>
+#include <ardour/audiosource.h>
+#include <ardour/audio_diskstream.h>
+#include <ardour/audio_track.h>
+#include <ardour/playlist_templates.h>
+#include <ardour/source.h>
+
+#include "audio_streamview.h"
+#include "audio_region_view.h"
+#include "tape_region_view.h"
+#include "audio_time_axis.h"
+#include "canvas-waveview.h"
+#include "canvas-simplerect.h"
+#include "region_selection.h"
+#include "selection.h"
+#include "public_editor.h"
+#include "ardour_ui.h"
+#include "crossfade_view.h"
+#include "rgb_macros.h"
+#include "gui_thread.h"
+#include "utils.h"
+#include "color.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+using namespace Editing;
+
+AudioStreamView::AudioStreamView (AudioTimeAxisView& tv)
+       : StreamView (tv)
+{
+       crossfades_visible = true;
+
+       if (tv.is_audio_track())
+               stream_base_color = color_map[cAudioTrackBase];
+       else
+               stream_base_color = color_map[cAudioBusBase];
+       
+       canvas_rect->property_fill_color_rgba() = stream_base_color;
+       canvas_rect->property_outline_color_rgba() = color_map[cAudioTrackOutline];
+
+       _amplitude_above_axis = 1.0;
+
+       use_rec_regions = tv.editor.show_waveforms_recording ();
+       last_rec_peak_frame = 0;
+}
+
+AudioStreamView::~AudioStreamView ()
+{
+}
+
+int
+AudioStreamView::set_height (gdouble h)
+{
+       /* limit the values to something sane-ish */
+       if (h < 10.0 || h > 1000.0) {
+               return -1;
+       }
+
+       StreamView::set_height(h);
+
+       for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+               (*i)->set_height (h);
+       }
+
+       return 0;
+}
+
+int 
+AudioStreamView::set_samples_per_unit (gdouble spp)
+{
+       StreamView::set_samples_per_unit(spp);
+
+       for (CrossfadeViewList::iterator xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) {
+               (*xi)->set_samples_per_unit (spp);
+       }
+
+       return 0;
+}
+
+int 
+AudioStreamView::set_amplitude_above_axis (gdouble app)
+{
+       RegionViewList::iterator i;
+
+       if (app < 1.0) {
+               return -1;
+       }
+
+       _amplitude_above_axis = app;
+
+       for (i = region_views.begin(); i != region_views.end(); ++i) {
+               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+               if (arv)
+                       arv->set_amplitude_above_axis (app);
+       }
+
+       return 0;
+}
+
+void
+AudioStreamView::add_region_view_internal (Region *r, bool wait_for_waves)
+{
+       ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_region_view), r));
+
+       AudioRegion* region = dynamic_cast<AudioRegion*> (r);
+
+       if (region == 0) {
+               return;
+       }
+
+       AudioRegionView *region_view;
+       list<RegionView *>::iterator i;
+
+       for (i = region_views.begin(); i != region_views.end(); ++i) {
+               if (&(*i)->region() == r) {
+                       
+                       /* great. we already have a AudioRegionView for this Region. use it again. */
+
+                       (*i)->set_valid (true);
+                       return;
+               }
+       }
+       
+       switch (_trackview.audio_track()->mode()) {
+       case Normal:
+               region_view = new AudioRegionView (canvas_group, _trackview, *region, 
+                                                  _samples_per_unit, region_color);
+               break;
+       case Destructive:
+               region_view = new TapeAudioRegionView (canvas_group, _trackview, *region, 
+                                                      _samples_per_unit, region_color);
+               break;
+       }
+
+       region_view->init (region_color, wait_for_waves);
+       region_view->set_amplitude_above_axis(_amplitude_above_axis);
+       region_views.push_front (region_view);
+       
+       /* follow global waveform setting */
+
+       region_view->set_waveform_visible(_trackview.editor.show_waveforms());
+
+       /* catch regionview going away */
+
+       region->GoingAway.connect (mem_fun (*this, &AudioStreamView::remove_region_view));
+       
+       RegionViewAdded (region_view);
+}
+
+void
+AudioStreamView::remove_region_view (Region *r)
+{
+       ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::remove_region_view), r));
+
+       for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end();) {
+               list<CrossfadeView*>::iterator tmp;
+               
+               tmp = i;
+               ++tmp;
+               
+               AudioRegion* ar = dynamic_cast<AudioRegion*>(r);
+               if (ar && (*i)->crossfade.involves (*ar)) {
+                       delete *i;
+                       crossfade_views.erase (i);
+               }
+               
+               i = tmp;
+       }
+
+       StreamView::remove_region_view(r);
+}
+
+void
+AudioStreamView::undisplay_diskstream ()
+{
+       StreamView::undisplay_diskstream();
+
+       for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+               delete *i;
+       }
+
+       crossfade_views.clear ();
+}
+
+void
+AudioStreamView::playlist_modified ()
+{
+       ENSURE_GUI_THREAD (mem_fun (*this, &AudioStreamView::playlist_modified));
+
+       StreamView::playlist_modified();
+       
+       /* if the playlist is modified, make sure xfades are on top and all the regionviews are stacked 
+          correctly.
+       */
+
+       for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+               (*i)->get_canvas_group()->raise_to_top();
+       }
+}
+
+void
+AudioStreamView::playlist_changed (Diskstream *ds)
+{
+       ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::playlist_changed), ds));
+
+       StreamView::playlist_changed(ds);
+
+       AudioPlaylist* apl = dynamic_cast<AudioPlaylist*>(ds->playlist());
+       if (apl)
+               playlist_connections.push_back (apl->NewCrossfade.connect (mem_fun (*this, &AudioStreamView::add_crossfade)));
+}
+
+void
+AudioStreamView::add_crossfade (Crossfade *crossfade)
+{
+       AudioRegionView* lview = 0;
+       AudioRegionView* rview = 0;
+
+       ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_crossfade), crossfade));
+
+       /* first see if we already have a CrossfadeView for this Crossfade */
+
+       for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+               if (&(*i)->crossfade == crossfade) {
+                       if (!crossfades_visible) {
+                               (*i)->hide();
+                       } else {
+                               (*i)->show ();
+                       }
+                       (*i)->set_valid (true);
+                       return;
+               }
+       }
+
+       /* create a new one */
+
+       for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+               AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*i);
+
+               if (!lview && arv && &(arv->region()) == &crossfade->out()) {
+                       lview = arv;
+               }
+               if (!rview && arv && &(arv->region()) == &crossfade->in()) {
+                       rview = arv;
+               }
+       }
+
+       CrossfadeView *cv = new CrossfadeView (_trackview.canvas_display,
+                                              _trackview,
+                                              *crossfade,
+                                              _samples_per_unit,
+                                              region_color,
+                                              *lview, *rview);
+
+       crossfade->Invalidated.connect (mem_fun (*this, &AudioStreamView::remove_crossfade));
+       crossfade_views.push_back (cv);
+
+       if (!crossfades_visible) {
+               cv->hide ();
+       }
+}
+
+void
+AudioStreamView::remove_crossfade (Crossfade *xfade)
+{
+       ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::remove_crossfade), xfade));
+
+       for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+               if (&(*i)->crossfade == xfade) {
+                       delete *i;
+                       crossfade_views.erase (i);
+                       break;
+               }
+       }
+}
+
+void
+AudioStreamView::redisplay_diskstream ()
+{
+       list<RegionView *>::iterator i, tmp;
+       list<CrossfadeView*>::iterator xi, tmpx;
+
+       
+       for (i = region_views.begin(); i != region_views.end(); ++i) {
+               (*i)->set_valid (false);
+       }
+
+       for (xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) {
+               (*xi)->set_valid (false);
+               if ((*xi)->visible()) {
+                       (*xi)->show ();
+               }
+       }
+
+       if (_trackview.is_audio_track()) {
+               _trackview.get_diskstream()->playlist()->foreach_region (static_cast<StreamView*>(this), &StreamView::add_region_view);
+               AudioPlaylist* apl = dynamic_cast<AudioPlaylist*>(_trackview.get_diskstream()->playlist());
+               if (apl)
+                       apl->foreach_crossfade (this, &AudioStreamView::add_crossfade);
+       }
+
+       for (i = region_views.begin(); i != region_views.end(); ) {
+               tmp = i;
+               tmp++;
+
+               if (!(*i)->is_valid()) {
+                       delete *i;
+                       region_views.erase (i);
+               } 
+
+               i = tmp;
+       }
+
+       for (xi = crossfade_views.begin(); xi != crossfade_views.end();) {
+               tmpx = xi;
+               tmpx++;
+
+               if (!(*xi)->valid()) {
+                       delete *xi;
+                       crossfade_views.erase (xi);
+               }
+
+               xi = tmpx;
+       }
+
+       /* now fix layering */
+
+       playlist_modified ();
+}
+
+void
+AudioStreamView::set_show_waveforms (bool yn)
+{
+       for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+               if (arv)
+                       arv->set_waveform_visible (yn);
+       }
+}
+
+void
+AudioStreamView::set_waveform_shape (WaveformShape shape)
+{
+       for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+               if (arv)
+                       arv->set_waveform_shape (shape);
+       }
+}              
+               
+void
+AudioStreamView::setup_rec_box ()
+{
+       // cerr << _trackview.name() << " streamview SRB\n";
+
+       if (_trackview.session().transport_rolling()) {
+
+               // cerr << "\trolling\n";
+
+               if (!rec_active && 
+                   _trackview.session().record_status() == Session::Recording && 
+                   _trackview.get_diskstream()->record_enabled()) {
+
+                       if (_trackview.audio_track()->mode() == Normal && use_rec_regions && rec_regions.size() == rec_rects.size()) {
+
+                               /* add a new region, but don't bother if they set use_rec_regions mid-record */
+
+                               AudioRegion::SourceList sources;
+
+                               for (list<sigc::connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) {
+                                       (*prc).disconnect();
+                               }
+                               peak_ready_connections.clear();
+                                       
+                               // FIXME
+                               AudioDiskstream* ads = dynamic_cast<AudioDiskstream*>(_trackview.get_diskstream());
+                               assert(ads);
+
+                               for (uint32_t n=0; n < ads->n_channels(); ++n) {
+                                       AudioSource *src = (AudioSource *) ads->write_source (n);
+                                       if (src) {
+                                               sources.push_back (src);
+                                               peak_ready_connections.push_back (src->PeakRangeReady.connect (bind (mem_fun (*this, &AudioStreamView::rec_peak_range_ready), src))); 
+                                       }
+                               }
+
+                               // handle multi
+                               
+                               jack_nframes_t start = 0;
+                               if (rec_regions.size() > 0) {
+                                       start = rec_regions.back()->start() + _trackview.get_diskstream()->get_captured_frames(rec_regions.size()-1);
+                               }
+                               
+                               AudioRegion * region = new AudioRegion(sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false);
+                               region->set_position (_trackview.session().transport_frame(), this);
+                               rec_regions.push_back (region);
+                               /* catch it if it goes away */
+                               region->GoingAway.connect (mem_fun (*this, &AudioStreamView::remove_rec_region));
+
+                               /* we add the region later */
+                       }
+                       
+                       /* start a new rec box */
+
+                       AudioTrack* at;
+
+                       at = _trackview.audio_track(); /* we know what it is already */
+                       AudioDiskstream& ds = at->audio_diskstream();
+                       jack_nframes_t frame_pos = ds.current_capture_start ();
+                       gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos);
+                       gdouble xend;
+                       uint32_t fill_color;
+
+                       switch (_trackview.audio_track()->mode()) {
+                       case Normal:
+                               xend = xstart;
+                               fill_color = color_map[cRecordingRectFill];
+                               break;
+
+                       case Destructive:
+                               xend = xstart + 2;
+                               fill_color = color_map[cRecordingRectFill];
+                               /* make the recording rect translucent to allow
+                                  the user to see the peak data coming in, etc.
+                               */
+                               fill_color = UINT_RGBA_CHANGE_A (fill_color, 120);
+                               break;
+                       }
+                       
+                       ArdourCanvas::SimpleRect * rec_rect = new Gnome::Canvas::SimpleRect (*canvas_group);
+                       rec_rect->property_x1() = xstart;
+                       rec_rect->property_y1() = 1.0;
+                       rec_rect->property_x2() = xend;
+                       rec_rect->property_y2() = (double) _trackview.height - 1;
+                       rec_rect->property_outline_color_rgba() = color_map[cRecordingRectOutline];
+                       rec_rect->property_fill_color_rgba() = fill_color;
+                       
+                       RecBoxInfo recbox;
+                       recbox.rectangle = rec_rect;
+                       recbox.start = _trackview.session().transport_frame();
+                       recbox.length = 0;
+                       
+                       rec_rects.push_back (recbox);
+                       
+                       screen_update_connection.disconnect();
+                       screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &AudioStreamView::update_rec_box));   
+                       rec_updating = true;
+                       rec_active = true;
+
+               } else if (rec_active &&
+                          (_trackview.session().record_status() != Session::Recording ||
+                           !_trackview.get_diskstream()->record_enabled())) {
+
+                       screen_update_connection.disconnect();
+                       rec_active = false;
+                       rec_updating = false;
+
+               }
+               
+       } else {
+
+               // cerr << "\tNOT rolling, rec_rects = " << rec_rects.size() << " rec_regions = " << rec_regions.size() << endl;
+
+               if (!rec_rects.empty() || !rec_regions.empty()) {
+
+                       /* disconnect rapid update */
+                       screen_update_connection.disconnect();
+
+                       for (list<sigc::connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) {
+                               (*prc).disconnect();
+                       }
+                       peak_ready_connections.clear();
+
+                       rec_updating = false;
+                       rec_active = false;
+                       last_rec_peak_frame = 0;
+                       
+                       /* remove temp regions */
+                       for (list<Region*>::iterator iter=rec_regions.begin(); iter != rec_regions.end(); )
+                       {
+                               list<Region*>::iterator tmp;
+
+                               tmp = iter;
+                               ++tmp;
+
+                               /* this will trigger the remove_region_view */
+                               delete *iter;
+
+                               iter = tmp;
+                       }
+                       
+                       rec_regions.clear();
+
+                       // cerr << "\tclear " << rec_rects.size() << " rec rects\n";
+               
+
+                       /* transport stopped, clear boxes */
+                       for (vector<RecBoxInfo>::iterator iter=rec_rects.begin(); iter != rec_rects.end(); ++iter) {
+                               RecBoxInfo &rect = (*iter);
+                               delete rect.rectangle;
+                       }
+                       
+                       rec_rects.clear();
+                       
+               }
+       }
+}
+
+void
+AudioStreamView::foreach_crossfadeview (void (CrossfadeView::*pmf)(void))
+{
+       for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+               ((*i)->*pmf) ();
+       }
+}
+
+void
+AudioStreamView::rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, Source * src)
+{
+       // this is called from the peak building thread
+
+       ENSURE_GUI_THREAD(bind (mem_fun (*this, &AudioStreamView::rec_peak_range_ready), start, cnt, src));
+       
+       if (rec_peak_ready_map.size() == 0 || start+cnt > last_rec_peak_frame) {
+               last_rec_peak_frame = start + cnt;
+       }
+
+       rec_peak_ready_map[src] = true;
+
+       if (rec_peak_ready_map.size() == _trackview.get_diskstream()->n_channels()) {
+               this->update_rec_regions ();
+               rec_peak_ready_map.clear();
+       }
+}
+
+void
+AudioStreamView::update_rec_regions ()
+{
+       if (use_rec_regions) {
+
+               uint32_t n = 0;
+
+               for (list<Region*>::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) {
+
+                       list<Region*>::iterator tmp;
+
+                       tmp = iter;
+                       ++tmp;
+
+                       if (!canvas_item_visible (rec_rects[n].rectangle)) {
+                               /* rect already hidden, this region is done */
+                               iter = tmp;
+                               continue;
+                       }
+                       
+                       // FIXME
+                       AudioRegion * region = dynamic_cast<AudioRegion*>(*iter);
+                       assert(region);
+
+                       jack_nframes_t origlen = region->length();
+
+                       if (region == rec_regions.back() && rec_active) {
+
+                               if (last_rec_peak_frame > region->start()) {
+
+                                       jack_nframes_t nlen = last_rec_peak_frame - region->start();
+
+                                       if (nlen != region->length()) {
+
+                                               region->freeze ();
+                                               region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
+                                               region->set_length (nlen, this);
+                                               region->thaw ("updated");
+
+                                               if (origlen == 1) {
+                                                       /* our special initial length */
+                                                       add_region_view_internal (region, false);
+                                               }
+
+                                               /* also update rect */
+                                               ArdourCanvas::SimpleRect * rect = rec_rects[n].rectangle;
+                                               gdouble xend = _trackview.editor.frame_to_pixel (region->position() + region->length());
+                                               rect->property_x2() = xend;
+                                       }
+                               }
+
+                       } else {
+
+                               jack_nframes_t nlen = _trackview.get_diskstream()->get_captured_frames(n);
+
+                               if (nlen != region->length()) {
+
+                                       if (region->source(0).length() >= region->start() + nlen) {
+
+                                               region->freeze ();
+                                               region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
+                                               region->set_length (nlen, this);
+                                               region->thaw ("updated");
+                                               
+                                               if (origlen == 1) {
+                                                       /* our special initial length */
+                                                       add_region_view_internal (region, false);
+                                               }
+                                               
+                                               /* also hide rect */
+                                               ArdourCanvas::Item * rect = rec_rects[n].rectangle;
+                                               rect->hide();
+
+                                       }
+                               }
+                       }
+
+                       iter = tmp;
+               }
+       }
+}
+
+void
+AudioStreamView::show_all_xfades ()
+{
+       foreach_crossfadeview (&CrossfadeView::show);
+       crossfades_visible = true;
+}
+
+void
+AudioStreamView::hide_all_xfades ()
+{
+       foreach_crossfadeview (&CrossfadeView::hide);
+       crossfades_visible = false;
+}
+
+void
+AudioStreamView::hide_xfades_involving (AudioRegionView& rv)
+{
+       for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+               if ((*i)->crossfade.involves (rv.audio_region())) {
+                       (*i)->fake_hide ();
+               }
+       }
+}
+
+void
+AudioStreamView::reveal_xfades_involving (AudioRegionView& rv)
+{
+       for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+               if ((*i)->crossfade.involves (rv.audio_region()) && (*i)->visible()) {
+                       (*i)->show ();
+               }
+       }
+}
+
+void
+AudioStreamView::color_handler (ColorID id, uint32_t val)
+{
+       switch (id) {
+       case cAudioTrackBase:
+               if (_trackview.is_track()) {
+                       canvas_rect->property_fill_color_rgba() = val;
+               } 
+               break;
+       case cAudioBusBase:
+               if (!_trackview.is_track()) {
+                       canvas_rect->property_fill_color_rgba() = val;
+               }
+               break;
+       case cAudioTrackOutline:
+               canvas_rect->property_outline_color_rgba() = val;
+               break;
+
+       default:
+               break;
+       }
+}
+
diff --git a/gtk2_ardour/audio_streamview.h b/gtk2_ardour/audio_streamview.h
new file mode 100644 (file)
index 0000000..05ce812
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+    Copyright (C) 2001, 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
+    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.
+*/
+
+#ifndef __ardour_audio_streamview_h__
+#define __ardour_audio_streamview_h__
+
+#include <list>
+#include <map>
+#include <cmath>
+
+#include <ardour/location.h>
+#include "enums.h"
+#include "simplerect.h"
+#include "color.h"
+#include "streamview.h"
+
+namespace Gdk {
+       class Color;
+}
+
+namespace ARDOUR {
+       class Route;
+       class Diskstream;
+       class Crossfade;
+       class PeakData;
+       class AudioRegion;
+       class Source;
+}
+
+class PublicEditor;
+class Selectable;
+class AudioTimeAxisView;
+class AudioRegionView;
+class RegionSelection;
+class CrossfadeView;
+class Selection;
+
+class AudioStreamView : public StreamView
+{
+  public:
+       AudioStreamView (AudioTimeAxisView&);
+       ~AudioStreamView ();
+
+       void set_waveform_shape (WaveformShape);
+
+       int set_height (gdouble h);
+       int set_samples_per_unit (gdouble spp);
+
+       int     set_amplitude_above_axis (gdouble app);
+       gdouble get_amplitude_above_axis () { return _amplitude_above_axis; }
+
+       void set_show_waveforms (bool yn);
+       void set_show_waveforms_recording (bool yn) { use_rec_regions = yn; }
+
+       void foreach_crossfadeview (void (CrossfadeView::*pmf)(void));
+
+       void show_all_xfades ();
+       void hide_all_xfades ();
+       void hide_xfades_involving (AudioRegionView&);
+       void reveal_xfades_involving (AudioRegionView&);
+
+  private:
+       void setup_rec_box ();
+       void rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, ARDOUR::Source* src); 
+       void update_rec_regions ();
+       
+       void add_region_view_internal (ARDOUR::Region*, bool wait_for_waves);
+       void remove_region_view (ARDOUR::Region* );
+       void remove_audio_region_view (ARDOUR::AudioRegion* );
+       void remove_audio_rec_region (ARDOUR::AudioRegion*);
+
+       void undisplay_diskstream ();
+       void redisplay_diskstream ();
+       void playlist_modified ();
+       void playlist_changed (ARDOUR::Diskstream *ds);
+
+       void add_crossfade (ARDOUR::Crossfade*);
+       void remove_crossfade (ARDOUR::Crossfade*);
+
+       void color_handler (ColorID id, uint32_t val);
+       
+
+       double _amplitude_above_axis;
+       
+       typedef list<CrossfadeView*> CrossfadeViewList;
+       CrossfadeViewList crossfade_views;
+       bool              crossfades_visible;
+
+       list<sigc::connection>     peak_ready_connections;
+       jack_nframes_t             last_rec_peak_frame;
+       map<ARDOUR::Source*, bool> rec_peak_ready_map;
+       
+};
+
+#endif /* __ardour_audio_streamview_h__ */
index 857adff6b97070e8944b6f3b84a42d068da67d54..9ae94d1fe0ac6c201fd9b3136236fb2b6a80951a 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
@@ -20,6 +20,7 @@
 
 #include <cstdlib>
 #include <cmath>
+#include <cassert>
 
 #include <algorithm>
 #include <string>
 #include <pbd/whitespace.h>
 #include <pbd/memento_command.h>
 
-#include <gtkmm2ext/bindable_button.h>
 #include <gtkmm2ext/gtk_ui.h>
 #include <gtkmm2ext/selector.h>
 #include <gtkmm2ext/stop_signal.h>
+#include <gtkmm2ext/bindable_button.h>
 #include <gtkmm2ext/utils.h>
 
 #include <ardour/audioplaylist.h>
 #include <ardour/audio_diskstream.h>
 #include <ardour/insert.h>
-#include <ardour/ladspa_plugin.h>
 #include <ardour/location.h>
 #include <ardour/panner.h>
 #include <ardour/playlist.h>
 #include "audio_time_axis.h"
 #include "automation_gain_line.h"
 #include "automation_pan_line.h"
-#include "automation_time_axis.h"
 #include "canvas_impl.h"
 #include "crossfade_view.h"
 #include "enums.h"
 #include "gain_automation_time_axis.h"
-#include "gui_thread.h"
 #include "keyboard.h"
 #include "pan_automation_time_axis.h"
 #include "playlist_selector.h"
 #include "plugin_selector.h"
 #include "plugin_ui.h"
-#include "point_selection.h"
 #include "prompter.h"
 #include "public_editor.h"
-#include "redirect_automation_line.h"
-#include "redirect_automation_time_axis.h"
-#include "regionview.h"
-#include "rgb_macros.h"
-#include "selection.h"
+#include "audio_region_view.h"
 #include "simplerect.h"
-#include "streamview.h"
+#include "audio_streamview.h"
 #include "utils.h"
 
 #include <ardour/audio_track.h>
 
 using namespace ARDOUR;
 using namespace PBD;
-using namespace LADSPA;
 using namespace Gtk;
 using namespace Editing;
 
 
-AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt, Canvas& canvas)
-       : AxisView(sess),
-         RouteUI(rt, sess, _("m"), _("s"), _("r")), // mute, solo, and record
-         TimeAxisView(sess,ed,(TimeAxisView*) 0, canvas),
-         parent_canvas (canvas),
-         button_table (3, 3),
-         edit_group_button (_("g")), // group
-         playlist_button (_("p")), 
-         size_button (_("h")), // height
-         automation_button (_("a")),
-         visual_button (_("v"))
-
+AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, boost::shared_ptr<Route> rt, Canvas& canvas)
+       : AxisView(sess)
+       , RouteTimeAxisView(ed, sess, rt, canvas)
 {
-       _has_state = true;
+       // Make sure things are sane...
+       assert(!is_track() || is_audio_track());
+
        subplugin_menu.set_name ("ArdourContextMenu");
-       playlist_menu = 0;
-       playlist_action_menu = 0;
-       automation_action_menu = 0;
        gain_track = 0;
        pan_track = 0;
-       view = 0;
-       timestretch_rect = 0;
        waveform_item = 0;
        pan_automation_item = 0;
        gain_automation_item = 0;
-       no_redraw = false;
 
-       view = new StreamView (*this);
+       _view = new AudioStreamView (*this);
 
        add_gain_automation_child ();
        add_pan_automation_child ();
 
        ignore_toggle = false;
 
-       rec_enable_button->set_active (false);
        mute_button->set_active (false);
        solo_button->set_active (false);
        
-       rec_enable_button->set_name ("TrackRecordEnableButton");
-       mute_button->set_name ("TrackMuteButton");
-       solo_button->set_name ("SoloButton");
-       edit_group_button.set_name ("TrackGroupButton");
-       playlist_button.set_name ("TrackPlaylistButton");
-       automation_button.set_name ("TrackAutomationButton");
-       size_button.set_name ("TrackSizeButton");
-       visual_button.set_name ("TrackVisualButton");
-       hide_button.set_name ("TrackRemoveButton");
-
-       hide_button.add (*(manage (new Image (get_xpm("small_x.xpm")))));
-
-       solo_button->signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
-       mute_button->signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
-       rec_enable_button->signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
-       playlist_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
-       automation_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
-       size_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
-       visual_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
-       hide_button.signal_button_press_event().connect (mem_fun (*this, &AudioTimeAxisView::select_me), false);
-
-       solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press), false);
-       solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release), false);
-       mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false);
-       mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release), false);
-       rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press));
-       edit_group_button.signal_button_release_event().connect (mem_fun(*this, &AudioTimeAxisView::edit_click), false);
-       playlist_button.signal_clicked().connect (mem_fun(*this, &AudioTimeAxisView::playlist_click));
-       automation_button.signal_clicked().connect (mem_fun(*this, &AudioTimeAxisView::automation_click));
-       size_button.signal_button_release_event().connect (mem_fun(*this, &AudioTimeAxisView::size_click), false);
-       visual_button.signal_clicked().connect (mem_fun(*this, &AudioTimeAxisView::visual_click));
-       hide_button.signal_clicked().connect (mem_fun(*this, &AudioTimeAxisView::hide_click));
-
-       if (is_audio_track()) {
-               controls_table.attach (*rec_enable_button, 5, 6, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
-       }
-       controls_table.attach (*mute_button, 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
-       controls_table.attach (*solo_button, 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::FILL|Gtk::EXPAND, 0, 0);
-
-       controls_table.attach (edit_group_button, 6, 7, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
-
-       ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record"));
-       ARDOUR_UI::instance()->tooltips().set_tip(*solo_button,_("Solo"));
-       ARDOUR_UI::instance()->tooltips().set_tip(*mute_button,_("Mute"));
-       ARDOUR_UI::instance()->tooltips().set_tip(edit_group_button,_("Edit Group"));
-       ARDOUR_UI::instance()->tooltips().set_tip(size_button,_("Display Height"));
-       ARDOUR_UI::instance()->tooltips().set_tip(playlist_button,_("Playlist"));
-       ARDOUR_UI::instance()->tooltips().set_tip(automation_button, _("Automation"));
-       ARDOUR_UI::instance()->tooltips().set_tip(visual_button, _("Visual options"));
-       ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("Hide this track"));
-       
-       label_view ();
-
-       controls_table.attach (hide_button, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-       controls_table.attach (visual_button, 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-       controls_table.attach (size_button, 2, 3, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-       controls_table.attach (automation_button, 3, 4, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-
-       if (is_audio_track() && audio_track()->mode() == ARDOUR::Normal) {
-               controls_table.attach (playlist_button, 5, 6, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-       }
-
-       /* remove focus from the buttons */
-       
-       automation_button.unset_flags (Gtk::CAN_FOCUS);
-       solo_button->unset_flags (Gtk::CAN_FOCUS);
-       mute_button->unset_flags (Gtk::CAN_FOCUS);
-       edit_group_button.unset_flags (Gtk::CAN_FOCUS);
-       size_button.unset_flags (Gtk::CAN_FOCUS);
-       playlist_button.unset_flags (Gtk::CAN_FOCUS);
-       hide_button.unset_flags (Gtk::CAN_FOCUS);
-       visual_button.unset_flags (Gtk::CAN_FOCUS);
+       if (is_audio_track())
+               controls_ebox.set_name ("AudioTimeAxisViewControlsBaseUnselected");
+       else // bus
+               controls_ebox.set_name ("AudioBusControlsBaseUnselected");
 
        /* map current state of the route */
 
-       update_diskstream_display ();
-       solo_changed(0);
-       mute_changed(0);
        redirects_changed (0);
        reset_redirect_automation_curves ();
-       y_position = -1;
 
        ensure_xml_node ();
 
        set_state (*xml_node);
        
-       _route.mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
-       _route.solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
-       _route.redirects_changed.connect (mem_fun(*this, &AudioTimeAxisView::redirects_changed));
-       _route.name_changed.connect (mem_fun(*this, &AudioTimeAxisView::route_name_changed));
-       _route.solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
-       _route.panner().Changed.connect (mem_fun(*this, &AudioTimeAxisView::update_pans));
+       _route->panner().Changed.connect (mem_fun(*this, &AudioTimeAxisView::update_pans));
 
        if (is_audio_track()) {
 
-               /* track */
-
-               audio_track()->FreezeChange.connect (mem_fun(*this, &AudioTimeAxisView::map_frozen));
-
-               audio_track()->diskstream_changed.connect (mem_fun(*this, &AudioTimeAxisView::diskstream_changed));
-               get_diskstream()->speed_changed.connect (mem_fun(*this, &AudioTimeAxisView::speed_changed));
-
                controls_ebox.set_name ("AudioTrackControlsBaseUnselected");
                controls_base_selected_name = "AudioTrackControlsBaseSelected";
                controls_base_unselected_name = "AudioTrackControlsBaseUnselected";
 
                /* ask for notifications of any new RegionViews */
+               _view->RegionViewAdded.connect (mem_fun(*this, &AudioTimeAxisView::region_view_added));
+               _view->attach ();
 
-               view->AudioRegionViewAdded.connect (mem_fun(*this, &AudioTimeAxisView::region_view_added));
-
-               view->attach ();
+       } else { /* bus */
 
-               /* pick up the correct freeze state */
-
-               map_frozen ();
-
-       } else {
-
-               /* bus */
-
-               controls_ebox.set_name ("BusControlsBaseUnselected");
-               controls_base_selected_name = "BusControlsBaseSelected";
-               controls_base_unselected_name = "BusControlsBaseUnselected";
+               controls_ebox.set_name ("AudioBusControlsBaseUnselected");
+               controls_base_selected_name = "AudioBusControlsBaseSelected";
+               controls_base_unselected_name = "AudioBusControlsBaseUnselected";
        }
-
-       editor.ZoomChanged.connect (mem_fun(*this, &AudioTimeAxisView::reset_samples_per_unit));
-       ColorChanged.connect (mem_fun (*this, &AudioTimeAxisView::color_handler));
 }
 
 AudioTimeAxisView::~AudioTimeAxisView ()
 {
-       GoingAway (); /* EMIT_SIGNAL */
-
-       if (playlist_menu) {
-               delete playlist_menu;
-               playlist_menu = 0;
-       }
-  
-       if (playlist_action_menu) {
-               delete playlist_action_menu;
-               playlist_action_menu = 0;
-       }
-
-       vector_delete (&redirect_automation_curves);
-
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               delete *i;
-       }
+}
 
-       if (view) {
-               delete view;
-               view = 0;
-       }
+AudioStreamView*
+AudioTimeAxisView::audio_view()
+{
+       return dynamic_cast<AudioStreamView*>(_view);
 }
 
 guint32
@@ -298,233 +165,6 @@ AudioTimeAxisView::hide ()
        TimeAxisView::hide ();
 }
 
-void
-AudioTimeAxisView::set_playlist (AudioPlaylist *newplaylist)
-{
-       AudioPlaylist *pl;
-
-       modified_connection.disconnect ();
-       state_changed_connection.disconnect ();
-       
-       if ((pl = dynamic_cast<AudioPlaylist*> (playlist())) != 0) {
-               state_changed_connection = pl->StateChanged.connect (mem_fun(*this, &AudioTimeAxisView::playlist_state_changed));
-               modified_connection = pl->Modified.connect (mem_fun(*this, &AudioTimeAxisView::playlist_modified));
-       }
-}
-
-void
-AudioTimeAxisView::playlist_modified ()
-{
-}
-
-gint
-AudioTimeAxisView::edit_click (GdkEventButton *ev)
-{
-       if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
-               _route.set_edit_group (0, this);
-               return FALSE;
-       } 
-
-       using namespace Menu_Helpers;
-
-       MenuList& items = edit_group_menu.items ();
-       RadioMenuItem::Group group;
-
-       items.clear ();
-       items.push_back (RadioMenuElem (group, _("No group"), 
-                                       bind (mem_fun(*this, &AudioTimeAxisView::set_edit_group_from_menu), (RouteGroup *) 0)));
-       
-       if (_route.edit_group() == 0) {
-               static_cast<RadioMenuItem*>(&items.back())->set_active ();
-       }
-       
-       _session.foreach_edit_group (bind (mem_fun (*this, &AudioTimeAxisView::add_edit_group_menu_item), &group));
-       edit_group_menu.popup (ev->button, ev->time);
-
-       return FALSE;
-}
-
-void
-AudioTimeAxisView::add_edit_group_menu_item (RouteGroup *eg, RadioMenuItem::Group* group)
-{
-       using namespace Menu_Helpers;
-
-       MenuList &items = edit_group_menu.items();
-
-       cerr << "adding edit group called " << eg->name() << endl;
-
-       items.push_back (RadioMenuElem (*group, eg->name(), bind (mem_fun(*this, &AudioTimeAxisView::set_edit_group_from_menu), eg)));
-       if (_route.edit_group() == eg) {
-               static_cast<RadioMenuItem*>(&items.back())->set_active ();
-       }
-}
-
-void
-AudioTimeAxisView::set_edit_group_from_menu (RouteGroup *eg)
-
-{
-       _route.set_edit_group (eg, this);
-}
-
-void
-AudioTimeAxisView::playlist_state_changed (Change ignored)
-{
-       // ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioTimeAxisView::playlist_state_changed), ignored));
-       // why are we here ?
-}
-
-void
-AudioTimeAxisView::playlist_changed ()
-
-{
-       label_view ();
-
-       if (is_audio_track()) {
-               set_playlist (get_diskstream()->playlist());
-       }
-}
-
-void
-AudioTimeAxisView::label_view ()
-{
-       string x = _route.name();
-
-       if (x != name_entry.get_text()) {
-               name_entry.set_text (x);
-       }
-
-       ARDOUR_UI::instance()->tooltips().set_tip (name_entry, x);
-}
-
-void
-AudioTimeAxisView::route_name_changed (void *src)
-{
-       editor.route_name_changed (this);
-       label_view ();
-}
-
-void
-AudioTimeAxisView::take_name_changed (void *src)
-
-{
-       if (src != this) {
-               label_view ();
-       }
-}
-
-void
-AudioTimeAxisView::playlist_click ()
-{
-       // always build a new action menu
-       
-       if (playlist_action_menu == 0) {
-               playlist_action_menu = new Menu;
-               playlist_action_menu->set_name ("ArdourContextMenu");
-       }
-       
-       build_playlist_menu(playlist_action_menu);
-
-       playlist_action_menu->popup (1, 0);
-}
-
-void
-AudioTimeAxisView::automation_click ()
-{
-       if (automation_action_menu == 0) {
-               /* this seems odd, but the automation action
-                  menu is built as part of the display menu.
-               */
-               build_display_menu ();
-       }
-       automation_action_menu->popup (1, 0);
-}
-
-void
-AudioTimeAxisView::show_timestretch (jack_nframes_t start, jack_nframes_t end)
-{
-       double x1;
-       double x2;
-       double y2;
-       
-       TimeAxisView::show_timestretch (start, end);
-
-       hide_timestretch ();
-
-#if 0  
-       if (ts.empty()) {
-               return;
-       }
-
-
-       /* check that the time selection was made in our route, or our edit group.
-          remember that edit_group() == 0 implies the route is *not* in a edit group.
-       */
-
-       if (!(ts.track == this || (ts.group != 0 && ts.group == _route.edit_group()))) {
-               /* this doesn't apply to us */
-               return;
-       }
-
-       /* ignore it if our edit group is not active */
-       
-       if ((ts.track != this) && _route.edit_group() && !_route.edit_group()->is_active()) {
-               return;
-       }
-#endif
-
-       if (timestretch_rect == 0) {
-               timestretch_rect = new SimpleRect (*canvas_display);
-               timestretch_rect->property_x1() =  0.0;
-               timestretch_rect->property_y1() =  0.0;
-               timestretch_rect->property_x2() =  0.0;
-               timestretch_rect->property_y2() =  0.0;
-               timestretch_rect->property_fill_color_rgba() =  color_map[cTimeStretchFill];
-               timestretch_rect->property_outline_color_rgba() = color_map[cTimeStretchOutline];
-       }
-
-       timestretch_rect->show ();
-       timestretch_rect->raise_to_top ();
-
-       x1 = start / editor.get_current_zoom();
-       x2 = (end - 1) / editor.get_current_zoom();
-       y2 = height - 2;
-       
-       timestretch_rect->property_x1() = x1;
-       timestretch_rect->property_y1() = 1.0;
-       timestretch_rect->property_x2() = x2;
-       timestretch_rect->property_y2() = y2;
-}
-
-void
-AudioTimeAxisView::hide_timestretch ()
-{
-       TimeAxisView::hide_timestretch ();
-
-       if (timestretch_rect) {
-               timestretch_rect->hide ();
-       }
-}
-
-void
-AudioTimeAxisView::show_selection (TimeSelection& ts)
-{
-
-#if 0
-       /* ignore it if our edit group is not active or if the selection was started
-          in some other track or edit group (remember that edit_group() == 0 means
-          that the track is not in an edit group).
-       */
-
-       if (((ts.track != this && !is_child (ts.track)) && _route.edit_group() && !_route.edit_group()->is_active()) ||
-           (!(ts.track == this || is_child (ts.track) || (ts.group != 0 && ts.group == _route.edit_group())))) {
-               hide_selection ();
-               return;
-       }
-#endif
-
-       TimeAxisView::show_selection (ts);
-}
-
 void
 AudioTimeAxisView::set_state (const XMLNode& node)
 {
@@ -578,153 +218,14 @@ AudioTimeAxisView::set_state (const XMLNode& node)
 }
 
 void
-AudioTimeAxisView::set_height (TrackHeight h)
-{
-       bool height_changed = (height == 0) || (h != height_style);
-
-       TimeAxisView::set_height (h);
-
-       ensure_xml_node ();
-
-       view->set_height ((double) height);
-
-       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");
-               show_name_entry ();
-               hide_name_label ();
-               controls_table.show_all();
-               break;
-       case Smaller:
-               xml_node->add_property ("track_height", "smaller");
-               controls_table.show_all ();
-               show_name_entry ();
-               hide_name_label ();
-               edit_group_button.hide ();
-               hide_button.hide ();
-               visual_button.hide ();
-               size_button.hide ();
-               automation_button.hide ();
-               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 ();
-               name_label.set_text (_route.name());
-               break;
-       }
-
-       if (height_changed) {
-               /* only emit the signal if the height really changed */
-                _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
-       }
-}
-
-void
-AudioTimeAxisView::select_track_color ()
-{
-       if (RouteUI::choose_color ()) {
-
-               if (view) {
-                       view->apply_color (_color, StreamView::RegionColor);
-               }
-       }
-}
-
-void
-AudioTimeAxisView::reset_redirect_automation_curves ()
-{
-       for (vector<RedirectAutomationLine*>::iterator i = redirect_automation_curves.begin(); i != redirect_automation_curves.end(); ++i) {
-               (*i)->reset();
-       }
-}
-
-void
-AudioTimeAxisView::reset_samples_per_unit ()
-{
-       set_samples_per_unit (editor.get_current_zoom());
-}
-
-void
-AudioTimeAxisView::set_samples_per_unit (double spu)
-{
-       double speed = 1.0;
-
-       if (get_diskstream() != 0) {
-               speed = get_diskstream()->speed();
-       }
-       
-       if (view) {
-               view->set_samples_per_unit (spu * speed);
-       }
-
-       TimeAxisView::set_samples_per_unit (spu * speed);
-}
-
-void
-AudioTimeAxisView::build_display_menu ()
+AudioTimeAxisView::build_automation_action_menu ()
 {
        using namespace Menu_Helpers;
 
-       /* get the size menu ready */
-
-       build_size_menu ();
-
-       /* prepare it */
-
-       TimeAxisView::build_display_menu ();
-
-       /* now fill it with our stuff */
-
-       MenuList& items = display_menu->items();
-       display_menu->set_name ("ArdourContextMenu");
-       
-       items.push_back (MenuElem (_("Height"), *size_menu));
-       items.push_back (MenuElem (_("Color"), mem_fun(*this, &AudioTimeAxisView::select_track_color)));
-
-
-       items.push_back (SeparatorElem());
-       items.push_back (MenuElem (_("Hide all crossfades"), mem_fun(*this, &AudioTimeAxisView::hide_all_xfades)));
-       items.push_back (MenuElem (_("Show all crossfades"), mem_fun(*this, &AudioTimeAxisView::show_all_xfades)));
-       items.push_back (SeparatorElem());
-
-       build_remote_control_menu ();
-       items.push_back (MenuElem (_("Remote Control ID"), *remote_control_menu));
+       RouteTimeAxisView::build_automation_action_menu ();
 
-       automation_action_menu = manage (new Menu);
        MenuList& automation_items = automation_action_menu->items();
-       automation_action_menu->set_name ("ArdourContextMenu");
        
-       automation_items.push_back (MenuElem (_("Show all automation"),
-                                             mem_fun(*this, &AudioTimeAxisView::show_all_automation)));
-
-       automation_items.push_back (MenuElem (_("Show existing automation"),
-                                             mem_fun(*this, &AudioTimeAxisView::show_existing_automation)));
-
-       automation_items.push_back (MenuElem (_("Hide all automation"),
-                                             mem_fun(*this, &AudioTimeAxisView::hide_all_automation)));
-
        automation_items.push_back (SeparatorElem());
 
        automation_items.push_back (CheckMenuElem (_("Fader"), 
@@ -736,11 +237,21 @@ AudioTimeAxisView::build_display_menu ()
                                                   mem_fun(*this, &AudioTimeAxisView::toggle_pan_track)));
        pan_automation_item = static_cast<CheckMenuItem*> (&automation_items.back());
        pan_automation_item->set_active(show_pan_automation);
+       
+}
+
+void
+AudioTimeAxisView::append_extra_display_menu_items ()
+{
+       using namespace Menu_Helpers;
 
-       automation_items.push_back (MenuElem (_("Plugins"), subplugin_menu));
+       MenuList& items = display_menu->items();
 
-       items.push_back (MenuElem (_("Automation"), *automation_action_menu));
+       // crossfade stuff
+       items.push_back (MenuElem (_("Hide all crossfades"), mem_fun(*this, &AudioTimeAxisView::hide_all_xfades)));
+       items.push_back (MenuElem (_("Show all crossfades"), mem_fun(*this, &AudioTimeAxisView::show_all_xfades)));
 
+       // waveform menu
        Menu *waveform_menu = manage(new Menu);
        MenuList& waveform_items = waveform_menu->items();
        waveform_menu->set_name ("ArdourContextMenu");
@@ -760,399 +271,53 @@ AudioTimeAxisView::build_display_menu ()
        rectified_item = static_cast<RadioMenuItem *> (&waveform_items.back());
 
        items.push_back (MenuElem (_("Waveform"), *waveform_menu));
-
-       if (is_audio_track()) {
-
-               Menu* alignment_menu = manage (new Menu);
-               MenuList& alignment_items = alignment_menu->items();
-               alignment_menu->set_name ("ArdourContextMenu");
-
-               RadioMenuItem::Group align_group;
-               
-               alignment_items.push_back (RadioMenuElem (align_group, _("Align with existing material"), bind (mem_fun(*this, &AudioTimeAxisView::set_align_style), ExistingMaterial)));
-               align_existing_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back());
-               if (get_diskstream()->alignment_style() == ExistingMaterial) {
-                       align_existing_item->set_active();
-               }
-               alignment_items.push_back (RadioMenuElem (align_group, _("Align with capture time"), bind (mem_fun(*this, &AudioTimeAxisView::set_align_style), CaptureTime)));
-               align_capture_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back());
-               if (get_diskstream()->alignment_style() == CaptureTime) {
-                       align_capture_item->set_active();
-               }
-               
-               items.push_back (MenuElem (_("Alignment"), *alignment_menu));
-
-               get_diskstream()->AlignmentStyleChanged.connect (mem_fun(*this, &AudioTimeAxisView::align_style_changed));
-       }
-
-       items.push_back (SeparatorElem());
-       items.push_back (CheckMenuElem (_("Active"), mem_fun(*this, &RouteUI::toggle_route_active)));
-       route_active_menu_item = dynamic_cast<CheckMenuItem *> (&items.back());
-       route_active_menu_item->set_active (_route.active());
-
-       items.push_back (SeparatorElem());
-       items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route)));
-
-}
-
-void
-AudioTimeAxisView::align_style_changed ()
-{
-       switch (get_diskstream()->alignment_style()) {
-       case ExistingMaterial:
-               if (!align_existing_item->get_active()) {
-                       align_existing_item->set_active();
-               }
-               break;
-       case CaptureTime:
-               if (!align_capture_item->get_active()) {
-                       align_capture_item->set_active();
-               }
-               break;
-       }
-}
-
-void
-AudioTimeAxisView::set_align_style (AlignStyle style)
-{
-       get_diskstream()->set_align_style (style);
-}
-
-void
-AudioTimeAxisView::rename_current_playlist ()
-{
-       ArdourPrompter prompter (true);
-       string name;
-
-       AudioPlaylist *pl;
-       AudioDiskstream *ds;
-
-       if (((ds = get_diskstream()) == 0) || ds->destructive() || ((pl = ds->playlist()) == 0)) {
-               return;
-       }
-
-       prompter.set_prompt (_("Name for playlist"));
-       prompter.set_initial_text (pl->name());
-       prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
-       prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
-
-       switch (prompter.run ()) {
-       case Gtk::RESPONSE_ACCEPT:
-               prompter.get_result (name);
-               if (name.length()) {
-                       pl->set_name (name);
-               }
-               break;
-
-       default:
-               break;
-       }
-}
-
-void
-AudioTimeAxisView::use_copy_playlist (bool prompt)
-{
-       AudioPlaylist *pl;
-       AudioDiskstream *ds;
-       string name;
-
-       if (((ds = get_diskstream()) == 0) || ds->destructive() || ((pl = ds->playlist()) == 0)) {
-               return;
-       }
-       
-       name = Playlist::bump_name (pl->name(), _session);
-
-       if (prompt) {
-
-               ArdourPrompter prompter (true);
-               
-               prompter.set_prompt (_("Name for Playlist"));
-               prompter.set_initial_text (name);
-               prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT);
-               prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
-               prompter.show_all ();
-               
-               switch (prompter.run ()) {
-               case Gtk::RESPONSE_ACCEPT:
-                       prompter.get_result (name);
-                       break;
-                       
-               default:
-                       return;
-               }
-       }
-
-       if (name.length()) {
-               ds->use_copy_playlist ();
-               pl = ds->playlist();
-               pl->set_name (name);
-       }
-}
-
-void
-AudioTimeAxisView::use_new_playlist (bool prompt)
-{
-       AudioPlaylist *pl;
-       AudioDiskstream *ds;
-       string name;
-
-       if (((ds = get_diskstream()) == 0) || ds->destructive() || ((pl = ds->playlist()) == 0)) {
-               return;
-       }
-       
-       name = Playlist::bump_name (pl->name(), _session);
-
-       if (prompt) {
-               
-               ArdourPrompter prompter (true);
-               
-               prompter.set_prompt (_("Name for Playlist"));
-               prompter.set_initial_text (name);
-               prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT);
-               prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
-               
-               switch (prompter.run ()) {
-               case Gtk::RESPONSE_ACCEPT:
-                       prompter.get_result (name);
-                       break;
-                       
-               default:
-                       return;
-               }
-       }
-
-       if (name.length()) {
-               ds->use_new_playlist ();
-               pl = ds->playlist();
-               pl->set_name (name);
-       }
-}
-
-void
-AudioTimeAxisView::clear_playlist ()
-{
-       AudioPlaylist *pl;
-       AudioDiskstream *ds;
-       
-       if ((ds = get_diskstream()) != 0) {
-               if ((pl = ds->playlist()) != 0) {
-                       editor.clear_playlist (*pl);
-               }
-       }
 }
 
 void
 AudioTimeAxisView::toggle_waveforms ()
 {
-       if (view && waveform_item && !ignore_toggle) {
-               view->set_show_waveforms (waveform_item->get_active());
+       AudioStreamView* asv = audio_view();
+       assert(asv);
+
+       if (asv && waveform_item && !ignore_toggle) {
+               asv->set_show_waveforms (waveform_item->get_active());
        }
 }
 
 void
 AudioTimeAxisView::set_show_waveforms (bool yn)
 {
+       AudioStreamView* asv = audio_view();
+       assert(asv);
+
        if (waveform_item) {
                waveform_item->set_active (yn);
        } else {
-               view->set_show_waveforms (yn);
+               asv->set_show_waveforms (yn);
        }
 }
 
 void
 AudioTimeAxisView::set_show_waveforms_recording (bool yn)
 {
-       if (view) {
-               view->set_show_waveforms_recording (yn);
-       }
-}
-
-void
-AudioTimeAxisView::set_waveform_shape (WaveformShape shape)
-{
-       if (view) {
-               view->set_waveform_shape (shape);
-       }
-}
-
-void
-AudioTimeAxisView::speed_changed ()
-{
-       Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &AudioTimeAxisView::reset_samples_per_unit));
-}
-
-void
-AudioTimeAxisView::diskstream_changed (void *src)
-{
-       Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &AudioTimeAxisView::update_diskstream_display));
-}      
-
-void
-AudioTimeAxisView::update_diskstream_display ()
-{
-       AudioDiskstream *ds;
-
-       if ((ds = get_diskstream()) != 0) {
-               set_playlist (ds->playlist ());
-       }
-
-       map_frozen ();
-}      
-
-void
-AudioTimeAxisView::selection_click (GdkEventButton* ev)
-{
-       PublicEditor::TrackViewList* tracks = editor.get_valid_views (this, _route.edit_group());
-
-       switch (Keyboard::selection_type (ev->state)) {
-       case Selection::Toggle:
-               /* XXX this is not right */
-               editor.get_selection().add (*tracks);
-               break;
-               
-       case Selection::Set:
-               editor.get_selection().set (*tracks);
-               break;
-
-       case Selection::Extend:
-               /* not defined yet */
-               break;
-       }
-
-       delete tracks;
-}
-
-void
-AudioTimeAxisView::set_selected_regionviews (AudioRegionSelection& regions)
-{
-       if (view) {
-               view->set_selected_regionviews (regions);
-       }
-}
-
-void
-AudioTimeAxisView::set_selected_points (PointSelection& points)
-{
-       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
-               (*i)->set_selected_points (points);
-       }
-}
-
-void
-AudioTimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable*>& results)
-{
-       double speed = 1.0;
-       
-       if (get_diskstream() != 0) {
-               speed = get_diskstream()->speed();
-       }
-       
-       jack_nframes_t start_adjusted = session_frame_to_track_frame(start, speed);
-       jack_nframes_t end_adjusted   = session_frame_to_track_frame(end, speed);
-
-       if (view && ((top < 0.0 && bot < 0.0)) || touched (top, bot)) {
-               view->get_selectables (start_adjusted, end_adjusted, results);
-       }
-
-       /* pick up visible automation tracks */
-       
-       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
-               if (!(*i)->hidden()) {
-                       (*i)->get_selectables (start_adjusted, end_adjusted, top, bot, results);
-               }
-       }
-}
-
-void
-AudioTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& results)
-{
-       if (view) {
-               view->get_inverted_selectables (sel, results);
-       }
-
-       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
-               if (!(*i)->hidden()) {
-                       (*i)->get_inverted_selectables (sel, results);
-               }
-       }
-
-       return;
-}
-
-RouteGroup*
-AudioTimeAxisView::edit_group() const
-{
-       return _route.edit_group();
-}
-
-string
-AudioTimeAxisView::name() const
-{
-       return _route.name();
-}
-
-Playlist *
-AudioTimeAxisView::playlist () const 
-{
-       AudioDiskstream *ds;
+       AudioStreamView* asv = audio_view();
 
-       if ((ds = get_diskstream()) != 0) {
-               return ds->playlist(); 
-       } else {
-               return 0; 
-       }
-}
-
-void
-AudioTimeAxisView::name_entry_changed ()
-{
-       string x;
-
-       x = name_entry.get_text ();
-       
-       if (x == _route.name()) {
-               return;
-       }
-
-       if (x.length() == 0) {
-               name_entry.set_text (_route.name());
-               return;
+       if (asv) {
+               asv->set_show_waveforms_recording (yn);
        }
-
-       strip_whitespace_edges(x);
-
-       if (_session.route_name_unique (x)) {
-               _route.set_name (x, this);
-       } else {
-               ARDOUR_UI::instance()->popup_error (_("a track already exists with that name"));
-               name_entry.set_text (_route.name());
-       }
-}
-
-void
-AudioTimeAxisView::visual_click ()
-{
-       popup_display_menu (0);
 }
 
 void
-AudioTimeAxisView::hide_click ()
-{
-       editor.hide_track_in_display (*this);
-}
-
-Region*
-AudioTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir)
+AudioTimeAxisView::set_waveform_shape (WaveformShape shape)
 {
-       AudioDiskstream *stream;
-       AudioPlaylist *playlist;
+       AudioStreamView* asv = audio_view();
 
-       if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) {
-               return playlist->find_next_region (pos, point, dir);
+       if (asv) {
+               asv->set_waveform_shape (shape);
        }
 
-       return 0;
-}
+       map_frozen ();
+}      
 
 void
 AudioTimeAxisView::add_gain_automation_child ()
@@ -1166,13 +331,13 @@ AudioTimeAxisView::add_gain_automation_child ()
                                                     *this,
                                                     parent_canvas,
                                                     _("gain"),
-                                                    _route.gain_automation_curve());
+                                                    _route->gain_automation_curve());
        
        line = new AutomationGainLine ("automation gain",
                                       _session,
                                       *gain_track,
                                       *gain_track->canvas_display,
-                                      _route.gain_automation_curve());
+                                      _route->gain_automation_curve());
 
        line->set_line_color (color_map[cAutomationLine]);
        
@@ -1241,11 +406,11 @@ AudioTimeAxisView::update_pans ()
        /* we don't draw lines for "greater than stereo" panning.
         */
 
-       if (_route.n_outputs() > 2) {
+       if (_route->n_outputs() > 2) {
                return;
        }
 
-       for (p = _route.panner().begin(); p != _route.panner().end(); ++p) {
+       for (p = _route->panner().begin(); p != _route->panner().end(); ++p) {
 
                AutomationLine* line;
 
@@ -1253,7 +418,7 @@ AudioTimeAxisView::update_pans ()
                                              *pan_track->canvas_display, 
                                              (*p)->automation());
 
-               if (p == _route.panner().begin()) {
+               if (p == _route->panner().begin()) {
                        /* first line is a nice orange */
                        line->set_line_color (color_map[cLeftPanAutomationLine]);
                } else {
@@ -1285,7 +450,7 @@ AudioTimeAxisView::toggle_gain_track ()
                /* now trigger a redisplay */
                
                if (!no_redraw) {
-                        _route.gui_changed (X_("track_height"), (void *) 0); /* EMIT_SIGNAL */
+                        _route->gui_changed (X_("track_height"), (void *) 0); /* EMIT_SIGNAL */
                }
        }
 }
@@ -1299,7 +464,7 @@ AudioTimeAxisView::gain_hidden ()
                gain_automation_item->set_active (false);
        }
 
-        _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
 }
 
 void
@@ -1321,7 +486,7 @@ AudioTimeAxisView::toggle_pan_track ()
                /* now trigger a redisplay */
                
                if (!no_redraw) {
-                        _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+                        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
                }
        }
 }
@@ -1335,322 +500,7 @@ AudioTimeAxisView::pan_hidden ()
                pan_automation_item->set_active (false);
        }
 
-        _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
-}
-
-AudioTimeAxisView::RedirectAutomationInfo::~RedirectAutomationInfo ()
-{
-       for (vector<RedirectAutomationNode*>::iterator i = lines.begin(); i != lines.end(); ++i) {
-               delete *i;
-       }
-}
-
-
-AudioTimeAxisView::RedirectAutomationNode::~RedirectAutomationNode ()
-{
-       parent.remove_ran (this);
-
-       if (view) {
-               delete view;
-       }
-}
-
-void
-AudioTimeAxisView::remove_ran (RedirectAutomationNode* ran)
-{
-       if (ran->view) {
-               remove_child (ran->view);
-       }
-}
-
-AudioTimeAxisView::RedirectAutomationNode*
-AudioTimeAxisView::find_redirect_automation_node (Redirect *redirect, uint32_t what)
-{
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-
-               if ((*i)->redirect == redirect) {
-
-                       for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
-                               if ((*ii)->what == what) {
-                                       return *ii;
-                               }
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static string 
-legalize_for_xml_node (string str)
-{
-       string::size_type pos;
-       string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=:";
-       string legal;
-
-       legal = str;
-       pos = 0;
-
-       while ((pos = legal.find_first_not_of (legal_chars, pos)) != string::npos) {
-               legal.replace (pos, 1, "_");
-               pos += 1;
-       }
-
-       return legal;
-}
-
-
-void
-AudioTimeAxisView::add_redirect_automation_curve (Redirect *redirect, uint32_t what)
-{
-       RedirectAutomationLine* ral;
-       string name;
-       RedirectAutomationNode* ran;
-
-       if ((ran = find_redirect_automation_node (redirect, what)) == 0) {
-               fatal << _("programming error: ")
-                     << string_compose (X_("redirect automation curve for %1:%2 not registered with audio track!"),
-                                 redirect->name(), what)
-                     << endmsg;
-               /*NOTREACHED*/
-               return;
-       }
-
-       if (ran->view) {
-               return;
-       }
-
-       name = redirect->describe_parameter (what);
-
-       /* create a string that is a legal XML node name that can be used to refer to this redirect+port combination */
-
-       char state_name[256];
-       snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (redirect->name()).c_str(), what);
-
-       ran->view = new RedirectAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *redirect, state_name);
-
-       ral = new RedirectAutomationLine (name, 
-                                         *redirect, what, _session, *ran->view,
-                                         *ran->view->canvas_display, redirect->automation_list (what));
-       
-       ral->set_line_color (color_map[cRedirectAutomationLine]);
-       ral->queue_reset ();
-
-       ran->view->add_line (*ral);
-
-       ran->view->Hiding.connect (bind (mem_fun(*this, &AudioTimeAxisView::redirect_automation_track_hidden), ran, redirect));
-
-       if (!ran->view->marked_for_display()) {
-               ran->view->hide ();
-       } else {
-               ran->menu_item->set_active (true);
-       }
-
-       add_child (ran->view);
-
-       view->foreach_regionview (bind (mem_fun(*this, &AudioTimeAxisView::add_ghost_to_redirect), ran->view));
-
-       redirect->mark_automation_visible (what, true);
-}
-
-void
-AudioTimeAxisView::redirect_automation_track_hidden (AudioTimeAxisView::RedirectAutomationNode* ran, Redirect* r)
-{
-       if (!_hidden) {
-               ran->menu_item->set_active (false);
-       }
-
-       r->mark_automation_visible (ran->what, false);
-
-        _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
-}
-
-void
-AudioTimeAxisView::add_existing_redirect_automation_curves (Redirect *redirect)
-{
-       set<uint32_t> s;
-       RedirectAutomationLine *ral;
-
-       redirect->what_has_visible_automation (s);
-
-       for (set<uint32_t>::iterator i = s.begin(); i != s.end(); ++i) {
-               
-               if ((ral = find_redirect_automation_curve (redirect, *i)) != 0) {
-                       ral->queue_reset ();
-               } else {
-                       add_redirect_automation_curve (redirect, (*i));
-               }
-       }
-}
-
-void
-AudioTimeAxisView::add_redirect_to_subplugin_menu (Redirect* r)
-{
-       using namespace Menu_Helpers;
-       RedirectAutomationInfo *rai;
-       list<RedirectAutomationInfo*>::iterator x;
-       
-       const std::set<uint32_t>& automatable = r->what_can_be_automated ();
-       std::set<uint32_t> has_visible_automation;
-
-       r->what_has_visible_automation(has_visible_automation);
-
-       if (automatable.empty()) {
-               return;
-       }
-
-       for (x = redirect_automation.begin(); x != redirect_automation.end(); ++x) {
-               if ((*x)->redirect == r) {
-                       break;
-               }
-       }
-
-       if (x == redirect_automation.end()) {
-
-               rai = new RedirectAutomationInfo (r);
-               redirect_automation.push_back (rai);
-
-       } else {
-
-               rai = *x;
-
-       }
-
-       /* any older menu was deleted at the top of redirects_changed()
-          when we cleared the subplugin menu.
-       */
-
-       rai->menu = manage (new Menu);
-       MenuList& items = rai->menu->items();
-       rai->menu->set_name ("ArdourContextMenu");
-
-       items.clear ();
-
-       for (std::set<uint32_t>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) {
-
-               RedirectAutomationNode* ran;
-               CheckMenuItem* mitem;
-               
-               string name = r->describe_parameter (*i);
-               
-               items.push_back (CheckMenuElem (name));
-               mitem = dynamic_cast<CheckMenuItem*> (&items.back());
-
-               if (has_visible_automation.find((*i)) != has_visible_automation.end()) {
-                       mitem->set_active(true);
-               }
-
-               if ((ran = find_redirect_automation_node (r, *i)) == 0) {
-
-                       /* new item */
-                       
-                       ran = new RedirectAutomationNode (*i, mitem, *this);
-                       
-                       rai->lines.push_back (ran);
-
-               } else {
-
-                       ran->menu_item = mitem;
-
-               }
-
-               mitem->signal_toggled().connect (bind (mem_fun(*this, &AudioTimeAxisView::redirect_menu_item_toggled), rai, ran));
-       }
-
-       /* add the menu for this redirect, because the subplugin
-          menu is always cleared at the top of redirects_changed().
-          this is the result of some poor design in gtkmm and/or
-          GTK+.
-       */
-
-       subplugin_menu.items().push_back (MenuElem (r->name(), *rai->menu));
-       rai->valid = true;
-}
-
-void
-AudioTimeAxisView::redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutomationInfo* rai,
-                                              AudioTimeAxisView::RedirectAutomationNode* ran)
-{
-       bool showit = ran->menu_item->get_active();
-       bool redraw = false;
-
-       if (ran->view == 0 && showit) {
-               add_redirect_automation_curve (rai->redirect, ran->what);
-               redraw = true;
-       }
-
-       if (showit != ran->view->marked_for_display()) {
-
-               if (showit) {
-                       ran->view->set_marked_for_display (true);
-                       ran->view->canvas_display->show();
-               } else {
-                       rai->redirect->mark_automation_visible (ran->what, true);
-                       ran->view->set_marked_for_display (false);
-                       ran->view->hide ();
-               }
-
-               redraw = true;
-
-       }
-
-       if (redraw && !no_redraw) {
-
-               /* now trigger a redisplay */
-               
-                _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
-
-       }
-}
-
-void
-AudioTimeAxisView::redirects_changed (void *src)
-{
-       using namespace Menu_Helpers;
-
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               (*i)->valid = false;
-       }
-
-       subplugin_menu.items().clear ();
-
-       _route.foreach_redirect (this, &AudioTimeAxisView::add_redirect_to_subplugin_menu);
-       _route.foreach_redirect (this, &AudioTimeAxisView::add_existing_redirect_automation_curves);
-
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ) {
-
-               list<RedirectAutomationInfo*>::iterator tmp;
-
-               tmp = i;
-               ++tmp;
-
-               if (!(*i)->valid) {
-
-                       delete *i;
-                       redirect_automation.erase (i);
-
-               } 
-
-               i = tmp;
-       }
-
-       /* change in visibility was possible */
-
-       _route.gui_changed ("track_height", this);
-}
-
-RedirectAutomationLine *
-AudioTimeAxisView::find_redirect_automation_curve (Redirect *redirect, uint32_t what)
-{
-       RedirectAutomationNode* ran;
-
-       if ((ran = find_redirect_automation_node (redirect, what)) != 0) {
-               if (ran->view) {
-                       return dynamic_cast<RedirectAutomationLine*> (ran->view->lines.front());
-               } 
-       }
-
-       return 0;
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
 }
 
 void
@@ -1661,19 +511,11 @@ AudioTimeAxisView::show_all_automation ()
        pan_automation_item->set_active (true);
        gain_automation_item->set_active (true);
        
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
-                       if ((*ii)->view == 0) {
-                               add_redirect_automation_curve ((*i)->redirect, (*ii)->what);
-                       } 
-
-                       (*ii)->menu_item->set_active (true);
-               }
-       }
+       RouteTimeAxisView::show_all_automation ();
 
        no_redraw = false;
 
-        _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
 }
 
 void
@@ -1684,17 +526,11 @@ AudioTimeAxisView::show_existing_automation ()
        pan_automation_item->set_active (true);
        gain_automation_item->set_active (true);
 
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
-                       if ((*ii)->view != 0) {
-                               (*ii)->menu_item->set_active (true);
-                       }
-               }
-       }
+       RouteTimeAxisView::show_existing_automation ();
 
        no_redraw = false;
 
-        _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
 }
 
 void
@@ -1705,236 +541,61 @@ AudioTimeAxisView::hide_all_automation ()
        pan_automation_item->set_active (false);
        gain_automation_item->set_active (false);
 
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
-                       (*ii)->menu_item->set_active (false);
-               }
-       }
+       RouteTimeAxisView::hide_all_automation();
 
        no_redraw = false;
-        _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
-}
-
-bool
-AudioTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
-{
-       Playlist* what_we_got;
-       AudioDiskstream* ds = get_diskstream();
-       Playlist* playlist;
-       bool ret = false;
-
-       if (ds == 0) {
-               /* route is a bus, not a track */
-               return false;
-       }
-
-       playlist = ds->playlist();
-
-
-       TimeSelection time (selection.time);
-       float speed = ds->speed();
-       if (speed != 1.0f) {
-               for (TimeSelection::iterator i = time.begin(); i != time.end(); ++i) {
-                       (*i).start = session_frame_to_track_frame((*i).start, speed);
-                       (*i).end   = session_frame_to_track_frame((*i).end,   speed);
-               }
-       }
-       
-       XMLNode &before = playlist->get_state();
-       switch (op) {
-       case Cut:
-               if ((what_we_got = playlist->cut (time)) != 0) {
-                       editor.get_cut_buffer().add (what_we_got);
-                        XMLNode &after = playlist->get_state();
-                       _session.add_command (new MementoCommand<Playlist>(*playlist, before, after));
-                       ret = true;
-               }
-               break;
-       case Copy:
-               if ((what_we_got = playlist->copy (time)) != 0) {
-                       editor.get_cut_buffer().add (what_we_got);
-               }
-               break;
-
-       case Clear:
-               if ((what_we_got = playlist->cut (time)) != 0) {
-                       XMLNode &after = playlist->get_state();
-                       _session.add_command(new MementoCommand<Playlist>(*playlist, before, after));
-                       what_we_got->unref ();
-                       ret = true;
-               }
-               break;
-       }
-
-       return ret;
-}
-
-bool
-AudioTimeAxisView::paste (jack_nframes_t pos, float times, Selection& selection, size_t nth)
-{
-       if (!is_audio_track()) {
-               return false;
-       }
-
-       Playlist* playlist = get_diskstream()->playlist();
-       PlaylistSelection::iterator p;
-       
-       for (p = selection.playlists.begin(); p != selection.playlists.end() && nth; ++p, --nth);
-
-       if (p == selection.playlists.end()) {
-               return false;
-       }
-
-       if (get_diskstream()->speed() != 1.0f)
-               pos = session_frame_to_track_frame(pos, get_diskstream()->speed() );
-       
-        XMLNode &before = playlist->get_state();
-       playlist->paste (**p, pos, times);
-        _session.add_command(new MementoCommand<Playlist>(*playlist, before, 
-                                                      playlist->get_state()));
-
-       return true;
-}
-
-void
-AudioTimeAxisView::region_view_added (AudioRegionView* arv)
-{
-       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
-               AutomationTimeAxisView* atv;
-
-               if ((atv = dynamic_cast<AutomationTimeAxisView*> (*i)) != 0) {
-                       arv->add_ghost (*atv);
-               }
-       }
-}
-
-void
-AudioTimeAxisView::add_ghost_to_redirect (AudioRegionView* arv, AutomationTimeAxisView* atv)
-{
-       arv->add_ghost (*atv);
-}
-
-list<TimeAxisView*>
-AudioTimeAxisView::get_child_list()
-{
-  
-       list<TimeAxisView*>redirect_children;
-       
-       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
-               if (!(*i)->hidden()) {
-                       redirect_children.push_back(*i);
-               }
-       }
-       return redirect_children;
-}
-
-
-void
-AudioTimeAxisView::build_playlist_menu (Gtk::Menu * menu)
-{
-       using namespace Menu_Helpers;
-
-       if (!menu || !is_audio_track()) {
-               return;
-       }
-
-       MenuList& playlist_items = menu->items();
-       menu->set_name ("ArdourContextMenu");
-       playlist_items.clear();
-
-       if (playlist_menu) {
-               delete playlist_menu;
-       }
-       playlist_menu = new Menu;
-       playlist_menu->set_name ("ArdourContextMenu");
-
-       playlist_items.push_back (MenuElem (string_compose (_("Current: %1"), get_diskstream()->playlist()->name())));
-       playlist_items.push_back (SeparatorElem());
-       
-       playlist_items.push_back (MenuElem (_("Rename"), mem_fun(*this, &AudioTimeAxisView::rename_current_playlist)));
-       playlist_items.push_back (SeparatorElem());
-
-       playlist_items.push_back (MenuElem (_("New"), mem_fun(editor, &PublicEditor::new_playlists)));
-       playlist_items.push_back (MenuElem (_("New Copy"), mem_fun(editor, &PublicEditor::copy_playlists)));
-       playlist_items.push_back (SeparatorElem());
-       playlist_items.push_back (MenuElem (_("Clear Current"), mem_fun(editor, &PublicEditor::clear_playlists)));
-       playlist_items.push_back (SeparatorElem());
-       playlist_items.push_back (MenuElem(_("Select"), mem_fun(*this, &AudioTimeAxisView::show_playlist_selector)));
-
-}
-
-void
-AudioTimeAxisView::show_playlist_selector ()
-{
-       editor.playlist_selector().show_for (this);
-}
-
-
-void
-AudioTimeAxisView::map_frozen ()
-{
-       if (!is_audio_track()) {
-               return;
-       }
-
-       ENSURE_GUI_THREAD (mem_fun(*this, &AudioTimeAxisView::map_frozen));
-
-
-       switch (audio_track()->freeze_state()) {
-       case AudioTrack::Frozen:
-               playlist_button.set_sensitive (false);
-               rec_enable_button->set_sensitive (false);
-               break;
-       default:
-               playlist_button.set_sensitive (true);
-               rec_enable_button->set_sensitive (true);
-               break;
-       }
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
 }
 
 void
 AudioTimeAxisView::show_all_xfades ()
 {
-       if (view) {
-               view->show_all_xfades ();
+       AudioStreamView* asv = audio_view();
+
+       if (asv) {
+               asv->show_all_xfades ();
        }
 }
 
 void
 AudioTimeAxisView::hide_all_xfades ()
 {
-       if (view) {
-               view->hide_all_xfades ();
+       AudioStreamView* asv = audio_view();
+       
+       if (asv) {
+               asv->hide_all_xfades ();
        }
 }
 
 void
 AudioTimeAxisView::hide_dependent_views (TimeAxisViewItem& tavi)
 {
+       AudioStreamView* asv = audio_view();
        AudioRegionView* rv;
 
-       if (view && (rv = dynamic_cast<AudioRegionView*>(&tavi)) != 0) {
-               view->hide_xfades_involving (*rv);
+       if (asv && (rv = dynamic_cast<AudioRegionView*>(&tavi)) != 0) {
+               asv->hide_xfades_involving (*rv);
        }
 }
 
 void
 AudioTimeAxisView::reveal_dependent_views (TimeAxisViewItem& tavi)
 {
+       AudioStreamView* asv = audio_view();
        AudioRegionView* rv;
 
-       if (view && (rv = dynamic_cast<AudioRegionView*>(&tavi)) != 0) {
-               view->reveal_xfades_involving (*rv);
+       if (asv && (rv = dynamic_cast<AudioRegionView*>(&tavi)) != 0) {
+               asv->reveal_xfades_involving (*rv);
        }
 }
 
 void
 AudioTimeAxisView::route_active_changed ()
 {
-       RouteUI::route_active_changed ();
+       RouteTimeAxisView::route_active_changed ();
 
        if (is_audio_track()) {
-               if (_route.active()) {
+               if (_route->active()) {
                        controls_ebox.set_name ("AudioTrackControlsBaseUnselected");
                        controls_base_selected_name = "AudioTrackControlsBaseSelected";
                        controls_base_unselected_name = "AudioTrackControlsBaseUnselected";
@@ -1944,7 +605,7 @@ AudioTimeAxisView::route_active_changed ()
                        controls_base_unselected_name = "AudioTrackControlsBaseInactiveUnselected";
                }
        } else {
-               if (_route.active()) {
+               if (_route->active()) {
                        controls_ebox.set_name ("BusControlsBaseUnselected");
                        controls_base_selected_name = "BusControlsBaseSelected";
                        controls_base_unselected_name = "BusControlsBaseUnselected";
@@ -1962,24 +623,3 @@ AudioTimeAxisView::get_child_xml_node (const string & childname)
        return RouteUI::get_child_xml_node (childname);
 }
 
-void
-AudioTimeAxisView::color_handler (ColorID id, uint32_t val)
-{
-       switch (id) {
-       case cTimeStretchOutline:
-               timestretch_rect->property_outline_color_rgba() = val;
-               break;
-       case cTimeStretchFill:
-               timestretch_rect->property_fill_color_rgba() = val;
-               break;
-       default:
-               break;
-       }
-}
-
-bool
-AudioTimeAxisView::select_me (GdkEventButton* ev)
-{
-       editor.get_selection().add (this);
-       return false;
-}
index b319d0ea9945c08733712f68a0cf3f222c908ded..2162771285c32f915c2a45baedcaa2cfdd9884a1 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_trackview_h__
-#define __ardour_trackview_h__
+#ifndef __ardour_audio_time_axis_h__
+#define __ardour_audio_time_axis_h__
 
 #include <gtkmm/table.h>
 #include <gtkmm/button.h>
 #include <list>
 
 #include <ardour/types.h>
-#include <ardour/region.h>
 
 #include "ardour_dialog.h"
 #include "route_ui.h"
 #include "enums.h"
-#include "time_axis_view.h"
+#include "route_time_axis.h"
 #include "canvas.h"
 #include "color.h"
 
-namespace ALSA {
-       class MultiChannelDevice;
-}
-
 namespace ARDOUR {
        class Session;
        class AudioDiskstream;
@@ -56,247 +51,58 @@ namespace ARDOUR {
        class AudioPlaylist;
 }
 
-namespace LADSPA {
-       class Manager;
-       class Plugin;
-}
-
 class PublicEditor;
 class AudioThing;
-class StreamView;
+class AudioStreamView;
 class Selection;
 class Selectable;
+class RegionView;
 class AudioRegionView;
 class AutomationLine;
 class AutomationGainLine;
 class AutomationPanLine;
-class RedirectAutomationLine;
 class TimeSelection;
 class AutomationTimeAxisView;
 
-class AudioTimeAxisView : public RouteUI, public TimeAxisView
+class AudioTimeAxisView : public RouteTimeAxisView
 {
   public:
-       AudioTimeAxisView (PublicEditor&, ARDOUR::Session&, ARDOUR::Route&, ArdourCanvas::Canvas& canvas);
+       AudioTimeAxisView (PublicEditor&, ARDOUR::Session&, boost::shared_ptr<ARDOUR::Route>, ArdourCanvas::Canvas& canvas);
        virtual ~AudioTimeAxisView ();
+       
+       AudioStreamView* audio_view();
 
-       void show_selection (TimeSelection&);
-       void automation_control_point_changed (ARDOUR::AutomationType);
-
-       void set_samples_per_unit (double);
-       void set_height (TimeAxisView::TrackHeight);
        void set_show_waveforms (bool yn);
        void set_show_waveforms_recording (bool yn);
-       void show_timestretch (jack_nframes_t start, jack_nframes_t end);
-       void hide_timestretch ();
-       void selection_click (GdkEventButton*);
-       void set_selected_regionviews (AudioRegionSelection&);
-       void set_selected_points (PointSelection&);
-       void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable *>&);
-       void get_inverted_selectables (Selection&, list<Selectable*>&);
        void show_all_xfades ();
        void hide_all_xfades ();
        void hide_dependent_views (TimeAxisViewItem&);
        void reveal_dependent_views (TimeAxisViewItem&);
                
-       ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir);
-
-       string name() const;
-
-       ARDOUR::RouteGroup* edit_group() const;
-
-       void build_playlist_menu (Gtk::Menu *);
-       ARDOUR::Playlist* playlist() const;
-
-       /* overridden from parent to store display state */
+       /* Overridden from parent to store display state */
        guint32 show_at (double y, int& nth, Gtk::VBox *parent);
        void hide ();
        
-       /* need accessors/mutators */
-
-       StreamView      *view;
-
-       /* editing operations */
-       
-       bool cut_copy_clear (Selection&, Editing::CutCopyOp);
-       bool paste (jack_nframes_t, float times, Selection&, size_t nth);
-
-       list<TimeAxisView*>get_child_list();
-
        void set_state (const XMLNode&);
        XMLNode* get_child_xml_node (const string & childname);
 
-       /* the editor calls these when mapping an operation across multiple tracks */
-
-       void use_new_playlist (bool prompt);
-       void use_copy_playlist (bool prompt);
-       void clear_playlist ();
-
   private:
-       friend class StreamView;
+       friend class AudioStreamView;
        friend class AudioRegionView;
-
-       ArdourCanvas::Canvas& parent_canvas;
-
-       bool         no_redraw;
-  
-       AutomationTimeAxisView *gain_track;
-       AutomationTimeAxisView *pan_track;
-
-       void update_automation_view (ARDOUR::AutomationType);
-       void reset_redirect_automation_curves ();
-
-       Gtk::HBox  other_button_hbox;
-
-       Gtk::Table button_table;
-
-       Gtk::Button       redirect_button;
-       Gtk::Button       edit_group_button;
-       Gtk::Button       playlist_button;
-       Gtk::Button       size_button;
-       Gtk::Button       automation_button;
-       Gtk::Button       hide_button;
-       Gtk::Button       visual_button;
-
-       void route_active_changed ();
-
-       void diskstream_changed (void *src);
-       void update_diskstream_display ();
        
-       gint edit_click  (GdkEventButton *);
-
-       // variables to get the context menu
-       // automation buttons correctly initialized
-       bool show_gain_automation;
-       bool show_pan_automation;
-
-       void build_redirect_window ();
-       void redirect_click ();
-       void redirect_add ();
-       void redirect_remove ();
-       void redirect_edit ();
-       void redirect_relist ();
-       void redirect_row_selected (gint row, gint col, GdkEvent *ev);
-       void add_to_redirect_display (ARDOUR::Redirect *);
-       void redirects_changed (void *);
-
-       sigc::connection modified_connection;
-       sigc::connection state_changed_connection;
-
-       void take_name_changed (void *);
-       void route_name_changed (void *);
-       void name_entry_changed ();
-
-       void on_area_realize ();
-
-       virtual void label_view ();
-
-       Gtk::Menu edit_group_menu;
-
-       void add_edit_group_menu_item (ARDOUR::RouteGroup *, Gtk::RadioMenuItem::Group*);
-       void set_edit_group_from_menu (ARDOUR::RouteGroup *);
-
-       void reset_samples_per_unit ();
+       void route_active_changed ();
 
-       void select_track_color();
+       void build_automation_action_menu ();
+       void append_extra_display_menu_items ();
        
-       virtual void build_display_menu ();
-
-       Gtk::CheckMenuItem* waveform_item;
-       Gtk::RadioMenuItem* traditional_item;
-       Gtk::RadioMenuItem* rectified_item;
-       
-       Gtk::RadioMenuItem* align_existing_item;
-       Gtk::RadioMenuItem* align_capture_item;
-       
-       void align_style_changed ();
-       void set_align_style (ARDOUR::AlignStyle);
-
        void toggle_show_waveforms ();
-
        void set_waveform_shape (WaveformShape);
        void toggle_waveforms ();
 
-       Gtk::Menu *playlist_menu;
-       Gtk::Menu *playlist_action_menu;
-       Gtk::MenuItem *playlist_item;
-       
-       /* playlist */
-
-       void set_playlist (ARDOUR::AudioPlaylist *);
-       void playlist_click ();
-       void show_playlist_selector ();
-
-       void playlist_changed ();
-       void playlist_state_changed (ARDOUR::Change);
-       void playlist_modified ();
-
-       void add_playlist_to_playlist_menu (ARDOUR::Playlist*);
-       void rename_current_playlist ();
-
-       /* automation stuff */
-       
-       Gtk::Menu* automation_action_menu;
-       Gtk::CheckMenuItem* gain_automation_item;
-       Gtk::CheckMenuItem* pan_automation_item;
-
-       void automation_click ();
-       void clear_automation ();
-       void hide_all_automation ();
        void show_all_automation ();
        void show_existing_automation ();
+       void hide_all_automation ();
 
-       struct RedirectAutomationNode {
-           uint32_t     what;
-           Gtk::CheckMenuItem* menu_item;
-           AutomationTimeAxisView* view;
-           AudioTimeAxisView& parent;
-
-           RedirectAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, AudioTimeAxisView& p)
-                   : what (w), menu_item (mitem), view (0), parent (p) {}
-
-           ~RedirectAutomationNode ();
-       };
-
-       struct RedirectAutomationInfo {
-           ARDOUR::Redirect* redirect;
-           bool valid;
-           Gtk::Menu* menu;
-           vector<RedirectAutomationNode*> lines;
-
-           RedirectAutomationInfo (ARDOUR::Redirect* r) 
-                   : redirect (r), valid (true) {}
-
-           ~RedirectAutomationInfo ();
-       };
-
-       list<RedirectAutomationInfo*> redirect_automation;
-       RedirectAutomationNode* find_redirect_automation_node (ARDOUR::Redirect *redirect, uint32_t what);
-       
-       Gtk::Menu subplugin_menu;
-       void add_redirect_to_subplugin_menu (ARDOUR::Redirect *);
-
-       void remove_ran (RedirectAutomationNode* ran);
-
-       void redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutomationInfo*,
-                                        AudioTimeAxisView::RedirectAutomationNode*);
-       void redirect_automation_track_hidden (RedirectAutomationNode*, ARDOUR::Redirect*);
-       
-       vector<RedirectAutomationLine*> redirect_automation_curves;
-       RedirectAutomationLine *find_redirect_automation_curve (ARDOUR::Redirect*,uint32_t);
-       void add_redirect_automation_curve (ARDOUR::Redirect*, uint32_t);
-       void add_existing_redirect_automation_curves (ARDOUR::Redirect*);
-
-       ArdourCanvas::SimpleRect *timestretch_rect;
-
-       void timestretch (jack_nframes_t start, jack_nframes_t end);
-
-       void visual_click ();
-       void hide_click ();
-       gint when_displayed (GdkEventAny*);
-
-       void speed_changed ();
-       
        void add_gain_automation_child ();
        void add_pan_automation_child ();
        void add_parameter_automation_child ();
@@ -309,14 +115,19 @@ class AudioTimeAxisView : public RouteUI, public TimeAxisView
 
        void update_pans ();
 
-       void region_view_added (AudioRegionView*);
-       void add_ghost_to_redirect (AudioRegionView*, AutomationTimeAxisView*);
-
-       void map_frozen ();
+       AutomationTimeAxisView* gain_track;
+       AutomationTimeAxisView* pan_track;
 
-       void color_handler (ColorID, uint32_t);
-       bool select_me (GdkEventButton*);
+       // Set from XML so context menu automation buttons can be correctly initialized
+       bool show_gain_automation;
+       bool show_pan_automation;
+       
+       Gtk::CheckMenuItem* waveform_item;
+       Gtk::RadioMenuItem* traditional_item;
+       Gtk::RadioMenuItem* rectified_item;
+       Gtk::CheckMenuItem* gain_automation_item;
+       Gtk::CheckMenuItem* pan_automation_item;
 };
 
-#endif /* __ardour_trackview_h__ */
+#endif /* __ardour_audio_time_axis_h__ */
 
index 080a440bc9b3a7ccf80c477be7199cc538fd32fa..6e2a93889f46504cb5f4def427dc5603544b3096 100644 (file)
@@ -21,7 +21,7 @@ using namespace PBD;
 using namespace Gtk;
 using namespace Editing;
 
-AutomationTimeAxisView::AutomationTimeAxisView (Session& s, Route& r, PublicEditor& e, TimeAxisView& rent, 
+AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r, PublicEditor& e, TimeAxisView& rent, 
                                                ArdourCanvas::Canvas& canvas, const string & nom, 
                                                const string & state_name, const string & nomparent)
 
@@ -41,6 +41,7 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, Route& r, PublicEdit
        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(),
@@ -73,6 +74,8 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, Route& r, PublicEdit
        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"));
@@ -116,6 +119,7 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, Route& r, PublicEdit
                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);
@@ -139,9 +143,9 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, Route& r, PublicEdit
        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 ();
 
        height_button.signal_clicked().connect (mem_fun(*this, &AutomationTimeAxisView::height_clicked));
@@ -282,11 +286,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;
 
@@ -298,119 +302,91 @@ AutomationTimeAxisView::set_height (TrackHeight ht)
                (*i)->set_height ();
        }
 
-       switch (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 */
+               route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
        }
 }
 
index deb08b41f0a9c6c2d1c798de69e2da1733304e60..0cd9acc034c47a76ad5344a667516c01d8898cb7 100644 (file)
@@ -4,6 +4,9 @@
 #include <vector>
 #include <list>
 #include <string>
+
+#include <boost/shared_ptr.hpp>
+
 #include <ardour/types.h>
 
 #include "canvas.h"
@@ -21,7 +24,7 @@ namespace ARDOUR {
 
 class PublicEditor;
 class TimeSelection;
-class AudioRegionSelection;
+class RegionSelection;
 class PointSelection;
 class AutomationLine;
 class GhostRegion;
@@ -31,7 +34,7 @@ class Selectable;
 class AutomationTimeAxisView : public TimeAxisView {
   public:
        AutomationTimeAxisView (ARDOUR::Session&,
-                               ARDOUR::Route&,
+                               boost::shared_ptr<ARDOUR::Route>,
                                PublicEditor&,
                                TimeAxisView& parent,
                                ArdourCanvas::Canvas& canvas,
@@ -41,14 +44,14 @@ class AutomationTimeAxisView : public TimeAxisView {
 
        ~AutomationTimeAxisView();
        
-       void set_height (TimeAxisView::TrackHeight);
+       virtual void set_height (TimeAxisView::TrackHeight);
        void set_samples_per_unit (double);
        std::string name() const { return _name; }
 
        virtual void add_automation_event (ArdourCanvas::Item *item, GdkEvent *event, jack_nframes_t, double) = 0;
 
-       void clear_lines ();
-       void add_line (AutomationLine&);
+       virtual void clear_lines ();
+       virtual void add_line (AutomationLine&);
 
        vector<AutomationLine*> lines;
 
@@ -75,12 +78,14 @@ class AutomationTimeAxisView : public TimeAxisView {
        XMLNode* get_state_node ();
 
   protected:
-       ARDOUR::Route& route;
+       boost::shared_ptr<ARDOUR::Route> route;
        ArdourCanvas::SimpleRect* base_rect;
        string _name;
        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 97ac91f622b63d0918491f8074f30f86da51fe8f..75281f69ebb5d80752e000361e0e445c29dc388d 100644 (file)
@@ -80,10 +80,10 @@ struct _GnomeCanvasWaveView
     void (*gain_curve_function)(void *arg, double start, double end, float* vector, guint32 veclen);
     void *gain_src;
 
-    /* x-axis: samples per canvas unit. */
+    /** x-axis: samples per canvas unit. */
     double samples_per_unit;
     
-    /* y-axis: amplitude_above_axis.
+    /** y-axis: amplitude_above_axis.
      * 
      * the default is that an (scaled, normalized -1.0 ... +1.0) amplitude of 1.0
      * corresponds to the top of the area assigned to the waveview.
@@ -92,8 +92,8 @@ struct _GnomeCanvasWaveView
      * smaller values will decrease the vertical scale, moving peaks/troughs toward
      * the middle of the area assigned to the waveview.
      */
-
     double amplitude_above_axis;
+
     double x;
     double y;
     double height;
index 5b587594de730f9bfc7b1397907587092e41253f..b2967dc4a9dfc60b453f8cc769ef176c377765f5 100644 (file)
@@ -1077,7 +1077,7 @@ CrossfadeEditor::peaks_ready (AudioRegion* r, WhichFade which)
 void
 CrossfadeEditor::audition_both ()
 {
-       AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
+       AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
        jack_nframes_t preroll;
        jack_nframes_t postroll;
        jack_nframes_t length;
@@ -1140,7 +1140,7 @@ CrossfadeEditor::audition_left_dry ()
 void
 CrossfadeEditor::audition_left ()
 {
-       AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
+       AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
 
        AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left", 
                                             0, Region::DefaultFlags, false);
@@ -1172,7 +1172,7 @@ CrossfadeEditor::audition_right_dry ()
 void
 CrossfadeEditor::audition_right ()
 {
-       AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
+       AudioPlaylist& pl (session.the_auditioner()->prepare_playlist());
 
        AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade out", 
                                             0, Region::DefaultFlags, false);
index 350698ec483b4ef8e16119a6cd743b08aca6ac43..087af25e7317e9a59e172eaabe4eb7c4a8ca819a 100644 (file)
@@ -29,7 +29,7 @@
 #include "rgb_macros.h"
 #include "audio_time_axis.h"
 #include "public_editor.h"
-#include "regionview.h"
+#include "audio_region_view.h"
 #include "utils.h"
 #include "canvas_impl.h"
 
@@ -43,7 +43,7 @@ using namespace Canvas;
 sigc::signal<void,CrossfadeView*> CrossfadeView::GoingAway;
 
 CrossfadeView::CrossfadeView (ArdourCanvas::Group *parent, 
-                             AudioTimeAxisView &tv, 
+                             RouteTimeAxisView &tv, 
                              Crossfade& xf, 
                              double spu,
                              Gdk::Color& basic_color,
@@ -227,7 +227,7 @@ CrossfadeView::set_valid (bool yn)
 AudioRegionView&
 CrossfadeView::upper_regionview () const
 {
-       if (left_view.region.layer() > right_view.region.layer()) {
+       if (left_view.region().layer() > right_view.region().layer()) {
                return left_view;
        } else {
                return right_view;
index 403edfe297d3ca338a76adf0da0cfda8a54ce4b2..adbd74b42027da577d37d5857ace317eac45fbb9 100644 (file)
 
 #include "time_axis_view_item.h"
 
-class AudioTimeAxisView;
+class RouteTimeAxisView;
 class AudioRegionView;
 
 struct CrossfadeView : public TimeAxisViewItem
 {
     CrossfadeView (ArdourCanvas::Group*, 
-                  AudioTimeAxisView&,
+                  RouteTimeAxisView&,
                   ARDOUR::Crossfade&,
                   double initial_samples_per_unit, 
                   Gdk::Color& basic_color,
index cf36550fb41da60b16bb4305a0c15f0557bb7c4c..654ddc8852111eedcb165653d2f4d030aec667b2 100644 (file)
@@ -56,4 +56,5 @@ DISPLAYCONTROL(ShowWaveformsRecording)
 
 IMPORTMODE(ImportAsRegion)
 IMPORTMODE(ImportAsTrack)
+IMPORTMODE(ImportAsTapeTrack)
 IMPORTMODE(ImportToTrack)
index 64729740931babca7709b404ac0399a447faa526..513251085c6d9f8c195bb684e400ae0e9c8762cc 100644 (file)
 #include "keyboard.h"
 #include "marker.h"
 #include "playlist_selector.h"
-#include "regionview.h"
+#include "audio_region_view.h"
 #include "rgb_macros.h"
 #include "selection.h"
-#include "streamview.h"
+#include "audio_streamview.h"
 #include "time_axis_view.h"
 #include "utils.h"
 #include "crossfade_view.h"
@@ -102,8 +102,8 @@ static const int32_t slide_index = 0;
 static const int32_t splice_index = 1;
 
 static const gchar *edit_mode_strings[] = {
-       N_("Slide"),
-       N_("Splice"),
+       N_("Slide Edit"),
+       N_("Splice Edit"),
        0
 };
 
@@ -132,17 +132,17 @@ static const gchar *snap_type_strings[] = {
 };
 
 static const gchar *snap_mode_strings[] = {
-       N_("Normal"),
-       N_("Magnetic"),
+       N_("Normal Snap"),
+       N_("Magnetic Snap"),
        0
 };
 
 static const gchar *zoom_focus_strings[] = {
-       N_("Left"),
-       N_("Right"),
-       N_("Center"),
-       N_("Playhead"),
-       N_("Edit Cursor"),
+       N_("Focus Left"),
+       N_("Focus Right"),
+       N_("Focus Center"),
+       N_("Focus Play"),
+       N_("Focus Edit"),
        0
 };
 
@@ -205,37 +205,20 @@ Editor::Editor (AudioEngine& eng)
 
          /* tool bar related */
 
-         selection_start_clock (X_("SelectionStartClock"), true),
-         selection_end_clock (X_("SelectionEndClock"), true),
          edit_cursor_clock (X_("EditCursorClock"), true),
          zoom_range_clock (X_("ZoomRangeClock"), true, true),
          
          toolbar_selection_clock_table (2,3),
          
-         mouse_mode_button_table (2, 3),
-
-         mouse_select_button (_("range")),
-         mouse_move_button (_("object")),
-         mouse_gain_button (_("gain")),
-         mouse_zoom_button (_("zoom")),
-         mouse_timefx_button (_("timefx")),
-         mouse_audition_button (_("listen")),
-
          automation_mode_button (_("mode")),
          global_automation_button (_("automation")),
 
-         edit_mode_label (_("Edit Mode")),
-         snap_type_label (_("Snap To")),
-         snap_mode_label(_("Snap Mode")),
-         zoom_focus_label (_("Zoom Focus")),
-
          /* <CMT Additions> */
          image_socket_listener(0),
          /* </CMT Additions> */
 
          /* nudge */
 
-         nudge_label (_("Nudge")),
          nudge_clock (X_("NudgeClock"), true, true)
 
 {
@@ -346,6 +329,7 @@ Editor::Editor (AudioEngine& eng)
        reset_hscrollbar_stepping ();
        
        zoom_focus = ZoomFocusLeft;
+       set_zoom_focus (ZoomFocusLeft);
        zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
 
        initialize_rulers ();
@@ -466,36 +450,7 @@ Editor::Editor (AudioEngine& eng)
 
        edit_packer.attach (edit_hscrollbar,         2, 3, 2, 3,    FILL|EXPAND,  FILL, 0, 0);
 
-       zoom_in_button.set_name ("EditorTimeButton");
-       zoom_out_button.set_name ("EditorTimeButton");
-       ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
-       ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
-
-       zoom_out_full_button.set_name ("EditorTimeButton");
-       ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
-
-       zoom_in_button.add (*(manage (new Image (Stock::ZOOM_IN, ICON_SIZE_BUTTON))));
-       zoom_out_button.add (*(manage (new Image (Stock::ZOOM_OUT, ICON_SIZE_BUTTON))));
-       zoom_out_full_button.add (*(manage (new Image (Stock::ZOOM_FIT, ICON_SIZE_BUTTON))));
-       
-       zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
-       zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
-       zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
-       
-       zoom_indicator_box.pack_start (zoom_out_button, false, false);
-       zoom_indicator_box.pack_start (zoom_in_button, false, false);
-       zoom_indicator_box.pack_start (zoom_range_clock, false, false); 
-       zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
-       
-       zoom_indicator_label.set_text (_("Zoom Span"));
-       zoom_indicator_label.set_name ("ToolBarLabel");
-
-       zoom_indicator_vbox.set_spacing (3);
-       zoom_indicator_vbox.set_border_width (3);
-       zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
-       zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
-
-       bottom_hbox.set_border_width (3);
+       bottom_hbox.set_border_width (2);
        bottom_hbox.set_spacing (3);
 
        route_display_model = ListStore::create(route_display_columns);
@@ -718,15 +673,15 @@ Editor::Editor (AudioEngine& eng)
        _playlist_selector = new PlaylistSelector();
        _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
 
-       AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
+       RegionView::RegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_regionview));
 
        /* nudge stuff */
 
        nudge_forward_button.add (*(manage (new Image (get_xpm("right_arrow.xpm")))));
        nudge_backward_button.add (*(manage (new Image (get_xpm("left_arrow.xpm")))));
 
-       ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
-       ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
+       ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge Region/Selection Forwards"));
+       ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge Region/Selection Backwards"));
 
        nudge_forward_button.set_name ("TransportButton");
        nudge_backward_button.set_name ("TransportButton");
@@ -776,7 +731,7 @@ Editor::add_toplevel_controls (Container& cont)
 }
 
 void
-Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
+Editor::catch_vanishing_regionview (RegionView *rv)
 {
        /* note: the selection will take care of the vanishing
           audioregionview by itself.
@@ -792,7 +747,7 @@ Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
 }
 
 void
-Editor::set_entered_regionview (AudioRegionView* rv)
+Editor::set_entered_regionview (RegionView* rv)
 {
        if (rv == entered_regionview) {
                return;
@@ -914,7 +869,7 @@ Editor::set_frames_per_unit (double fpu)
 void
 Editor::instant_save ()
 {
-        if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
+       if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
                return;
        }
 
@@ -1222,7 +1177,7 @@ Editor::connect_to_session (Session *t)
 
        session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
        session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
-       session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
+       session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route)));
        session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::handle_new_audio_region)));
        session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::handle_audio_region_removed)));
        session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::handle_new_duration)));
@@ -1243,8 +1198,6 @@ Editor::connect_to_session (Session *t)
        edit_groups_changed ();
 
        edit_cursor_clock.set_session (session);
-       selection_start_clock.set_session (session);
-       selection_end_clock.set_session (session);
        zoom_range_clock.set_session (session);
        _playlist_selector->set_session (session);
        nudge_clock.set_session (session);
@@ -1377,7 +1330,7 @@ Editor::connect_to_session (Session *t)
                        AudioTimeAxisView *atv;
                        
                        if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
-                               if (atv->route().master()) {
+                               if (atv->route()->master()) {
                                        route_list_display.get_selection()->unselect (i);
                                }
                        }
@@ -1448,7 +1401,7 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
        switch (item_type) {
        case FadeInItem:
        case FadeInHandleItem:
-               if (arv->region.fade_in_active()) {
+               if (arv->audio_region().fade_in_active()) {
                        items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
                } else {
                        items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
@@ -1456,16 +1409,16 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
                
                items.push_back (SeparatorElem());
                
-               items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
-               items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
-               items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
-               items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
-               items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
+               items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
+               items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
+               items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
+               items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
+               items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
                break;
 
        case FadeOutItem:
        case FadeOutHandleItem:
-               if (arv->region.fade_out_active()) {
+               if (arv->audio_region().fade_out_active()) {
                        items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
                } else {
                        items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
@@ -1473,11 +1426,11 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
                
                items.push_back (SeparatorElem());
                
-               items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
-               items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
-               items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
-               items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
-               items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
+               items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
+               items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
+               items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
+               items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
+               items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->audio_region(), &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
 
                break;
        default:
@@ -1499,8 +1452,8 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type,
 
        switch (item_type) {
        case RegionItem:
-       case AudioRegionViewName:
-       case AudioRegionViewNameHighlight:
+       case RegionViewName:
+       case RegionViewNameHighlight:
                if (with_selection) {
                        build_menu_function = &Editor::build_track_selection_context_menu;
                } else {
@@ -1540,25 +1493,26 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type,
 
        switch (item_type) {
        case RegionItem:
-       case AudioRegionViewName:
-       case AudioRegionViewNameHighlight:
+       case RegionViewName:
+       case RegionViewNameHighlight:
                if (!with_selection) {
                        if (region_edit_menu_split_item) {
-                               if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
+                               if (clicked_regionview && clicked_regionview->region().covers (edit_cursor->current_frame)) {
                                        ActionManager::set_sensitive (ActionManager::edit_cursor_in_region_sensitive_actions, true);
                                } else {
                                        ActionManager::set_sensitive (ActionManager::edit_cursor_in_region_sensitive_actions, false);
                                }
                        }
+                       /*
                        if (region_edit_menu_split_multichannel_item) {
-                               if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
+                               if (clicked_regionview && clicked_regionview->region().n_channels() > 1) {
                                        // GTK2FIX find the action, change its sensitivity
                                        // region_edit_menu_split_multichannel_item->set_sensitive (true);
                                } else {
                                        // GTK2FIX see above
                                        // region_edit_menu_split_multichannel_item->set_sensitive (false);
                                }
-                       }
+                       }*/
                }
                break;
 
@@ -1638,13 +1592,13 @@ Editor::build_track_region_context_menu (jack_nframes_t frame)
        AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
 
        if (atv) {
-               AudioDiskstream* ds;
+               Diskstream* ds;
                Playlist* pl;
                
                if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
                        Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
                        for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
-                               add_region_context_items (atv->view, (*i), edit_items);
+                               add_region_context_items (atv->audio_view(), (*i), edit_items);
                        }
                        delete regions;
                }
@@ -1665,7 +1619,7 @@ Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
        AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
 
        if (atv) {
-               AudioDiskstream* ds;
+               Diskstream* ds;
                Playlist* pl;
                AudioPlaylist* apl;
 
@@ -1679,11 +1633,11 @@ Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
                        bool many = xfades.size() > 1;
 
                        for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
-                               add_crossfade_context_items (atv->view, (*i), edit_items, many);
+                               add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many);
                        }
 
                        for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
-                               add_region_context_items (atv->view, (*i), edit_items);
+                               add_region_context_items (atv->audio_view(), (*i), edit_items);
                        }
 
                        delete regions;
@@ -1749,7 +1703,7 @@ Editor::build_track_selection_context_menu (jack_nframes_t ignored)
 }
 
 void
-Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
+Editor::add_crossfade_context_items (AudioStreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
 {
        using namespace Menu_Helpers;
        Menu     *xfade_menu = manage (new Menu);
@@ -1806,7 +1760,7 @@ Editor::xfade_edit_right_region ()
 }
 
 void
-Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
+Editor::add_region_context_items (AudioStreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
 {
        using namespace Menu_Helpers;
        Menu     *region_menu = manage (new Menu);
@@ -2185,7 +2139,6 @@ Editor::set_state (const XMLNode& node)
                yoff = atoi(geometry->property("y_off")->value());
        }
 
-       set_geometry_hints (vpacker, g, Gdk::HINT_BASE_SIZE);
        set_default_size (g.base_width, g.base_height);
        move (x, y);
 
@@ -2297,7 +2250,7 @@ Editor::get_state ()
        char buf[32];
 
        if (is_realized()) {
-               Glib::RefPtr<Gdk::Window> win = get_window();
+               Glib::RefPtr<Gdk::Window> win = get_window();
                
                int x, y, xoff, yoff, width, height;
                win->get_root_origin(x, y);
@@ -2586,30 +2539,56 @@ void
 Editor::setup_toolbar ()
 {
        string pixmap_path;
+
+       const guint32 FUDGE = 18; // Combo's are stupid - they steal space from the entry for the button
+
+
+       /* Mode Buttons (tool selection) */
+
        vector<ToggleButton *> mouse_mode_buttons;
 
+       mouse_move_button.add (*(manage (new Image (get_xpm("tool_object.xpm")))));
+       mouse_move_button.set_relief(Gtk::RELIEF_NONE);
        mouse_mode_buttons.push_back (&mouse_move_button);
+       mouse_select_button.add (*(manage (new Image (get_xpm("tool_range.xpm")))));
+       mouse_select_button.set_relief(Gtk::RELIEF_NONE);
        mouse_mode_buttons.push_back (&mouse_select_button);
+       mouse_gain_button.add (*(manage (new Image (get_xpm("tool_gain.xpm")))));
+       mouse_gain_button.set_relief(Gtk::RELIEF_NONE);
        mouse_mode_buttons.push_back (&mouse_gain_button);
+       mouse_zoom_button.add (*(manage (new Image (get_xpm("tool_zoom.xpm")))));
+       mouse_zoom_button.set_relief(Gtk::RELIEF_NONE);
        mouse_mode_buttons.push_back (&mouse_zoom_button);
+       mouse_timefx_button.add (*(manage (new Image (get_xpm("tool_stretch.xpm")))));
+       mouse_timefx_button.set_relief(Gtk::RELIEF_NONE);
        mouse_mode_buttons.push_back (&mouse_timefx_button);
+       mouse_audition_button.add (*(manage (new Image (get_xpm("tool_audition.xpm")))));
+       mouse_audition_button.set_relief(Gtk::RELIEF_NONE);
        mouse_mode_buttons.push_back (&mouse_audition_button);
+       
        mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
 
-       mouse_mode_button_table.set_homogeneous (true);
-       mouse_mode_button_table.set_col_spacings (2);
-       mouse_mode_button_table.set_row_spacings (2);
-       mouse_mode_button_table.set_border_width (5);
+       HBox* mode_box = manage(new HBox);
+       mode_box->set_border_width (2);
+       mode_box->set_spacing(4);
+       mouse_mode_button_box.set_spacing(1);
+       mouse_mode_button_box.pack_start(mouse_move_button, true, true);
+       mouse_mode_button_box.pack_start(mouse_select_button, true, true);
+       mouse_mode_button_box.pack_start(mouse_zoom_button, true, true);
+       mouse_mode_button_box.pack_start(mouse_gain_button, true, true);
+       mouse_mode_button_box.pack_start(mouse_timefx_button, true, true);
+       mouse_mode_button_box.pack_start(mouse_audition_button, true, true);
+       mouse_mode_button_box.set_homogeneous(true);
 
-       mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
-       mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
-       mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
-       mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
-       mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
-       mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
+       edit_mode_selector.set_name ("EditModeSelector");
+       Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "Splice Edit", 2+FUDGE, 10);
+       set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
+       edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
 
-       mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
+       mode_box->pack_start(edit_mode_selector);
+       mode_box->pack_start(mouse_mode_button_box);
+       
+       mouse_mode_tearoff = manage (new TearOff (*mode_box));
        mouse_mode_tearoff->set_name ("MouseModeBase");
 
        mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
@@ -2628,12 +2607,12 @@ Editor::setup_toolbar ()
        mouse_timefx_button.set_name ("MouseModeButton");
        mouse_audition_button.set_name ("MouseModeButton");
 
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
+       ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("Select/Move Objects"));
+       ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("Select/Move Ranges"));
+       ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("Draw Gain Automation"));
+       ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("Select Zoom Range"));
+       ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("Stretch/Shrink Regions"));
+       ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("Listen to Specific Regions"));
 
        mouse_move_button.unset_flags (CAN_FOCUS);
        mouse_select_button.unset_flags (CAN_FOCUS);
@@ -2652,160 +2631,82 @@ Editor::setup_toolbar ()
        mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
 
        // mouse_move_button.set_active (true);
+       
 
-       /* automation control */
-
-       global_automation_button.set_name ("MouseModeButton");
-       automation_mode_button.set_name ("MouseModeButton");
-
-       automation_box.set_spacing (2);
-       automation_box.set_border_width (2);
-       automation_box.pack_start (global_automation_button, false, false);
-       automation_box.pack_start (automation_mode_button, false, false);
-
-       /* Edit mode */
-
-       edit_mode_label.set_name ("ToolBarLabel");
-
-       edit_mode_selector.set_name ("EditModeSelector");
+       /* Zoom */
+       
+       zoom_box.set_spacing (1);
+       zoom_box.set_border_width (2);
 
-       edit_mode_box.set_spacing (3);
-       edit_mode_box.set_border_width (3);
+       zoom_in_button.set_name ("EditorTimeButton");
+       zoom_in_button.add (*(manage (new Image (get_xpm("zoom_in.xpm")))));
+       zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
+       ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom In"));
+       
+       zoom_out_button.set_name ("EditorTimeButton");
+       zoom_out_button.add (*(manage (new Image (get_xpm("zoom_out.xpm")))));
+       zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
+       ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom Out"));
 
-       /* XXX another disgusting hack because of the way combo boxes size themselves */
+       zoom_out_full_button.set_name ("EditorTimeButton");
+       zoom_out_full_button.add (*(manage (new Image (get_xpm("zoom_full.xpm")))));
+       zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
+       ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to Session"));
+       
+       zoom_box.pack_start (zoom_out_button, false, false);
+       zoom_box.pack_start (zoom_in_button, false, false);
+       zoom_box.pack_start (zoom_range_clock, false, false);   
+       zoom_box.pack_start (zoom_out_full_button, false, false);
+       
+       ARDOUR_UI::instance()->tooltips().set_tip (zoom_range_clock, _("Current Zoom Range\n(Width of visible area)"));
+       
+       zoom_focus_selector.set_name ("ZoomFocusSelector");
+       Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Focus Center", 2+FUDGE, 0);
+       set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
+       zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
 
-       const guint32 FUDGE = 20; // Combo's are stupid - they steal space from the entry for the button
-       Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2+FUDGE, 10);
-       set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
-       edit_mode_box.pack_start (edit_mode_label, false, false);
-       edit_mode_box.pack_start (edit_mode_selector, false, false);
+       zoom_box.pack_start (zoom_focus_selector, false, false);
 
-       edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
 
-       /* Snap Type */
+       /* Edit Cursor / Snap */
 
-       snap_type_label.set_name ("ToolBarLabel");
+       snap_box.set_spacing (1);
+       snap_box.set_border_width (2);
 
        snap_type_selector.set_name ("SnapTypeSelector");
-
-       snap_type_box.set_spacing (3);
-       snap_type_box.set_border_width (3);
-
-       /* XXX another disgusting hack because of the way combo boxes size themselves */
-
        Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "SMPTE Seconds", 2+FUDGE, 10);
        set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
-
-       snap_type_box.pack_start (snap_type_label, false, false);
-       snap_type_box.pack_start (snap_type_selector, false, false);
-
        snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
-
-       /* Snap mode, not snap type */
-
-       snap_mode_label.set_name ("ToolBarLabel");
+       ARDOUR_UI::instance()->tooltips().set_tip (snap_type_selector, _("Unit to snap cursors and ranges to"));
 
        snap_mode_selector.set_name ("SnapModeSelector");
-       
-       snap_mode_box.set_spacing (3);
-       snap_mode_box.set_border_width (3);
-
-       Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2+FUDGE, 10);
+       Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "Magnetic Snap", 2+FUDGE, 10);
        set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
-
-       snap_mode_box.pack_start (snap_mode_label, false, false);
-       snap_mode_box.pack_start (snap_mode_selector, false, false);
-
        snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
 
-       /* Zoom focus mode */
-
-       zoom_focus_label.set_name ("ToolBarLabel");
-
-       zoom_focus_selector.set_name ("ZoomFocusSelector");
-
-       zoom_focus_box.set_spacing (3);
-       zoom_focus_box.set_border_width (3);
-
-       /* XXX another disgusting hack because of the way combo boxes size themselves */
-
-       Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2+FUDGE, 10);
-       set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
-
-       zoom_focus_box.pack_start (zoom_focus_label, false, false);
-       zoom_focus_box.pack_start (zoom_focus_selector, false, false);
-
-       zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
-
-       /* selection/cursor clocks */
-
-       toolbar_selection_cursor_label.set_name ("ToolBarLabel");
-       selection_start_clock_label.set_name ("ToolBarLabel");
-       selection_end_clock_label.set_name ("ToolBarLabel");
-       edit_cursor_clock_label.set_name ("ToolBarLabel");
-
-       selection_start_clock_label.set_text (_("Start:"));
-       selection_end_clock_label.set_text (_("End:"));
-       edit_cursor_clock_label.set_text (_("Edit"));
-
-       /* the zoom in/out buttons are generally taller than the clocks, so
-          put all the toolbar clocks into a size group with one of the 
-          buttons to make them all equal height.
+       snap_box.pack_start (edit_cursor_clock, false, false);
+       snap_box.pack_start (snap_mode_selector, false, false);
+       snap_box.pack_start (snap_type_selector, false, false);
 
-          this also applies to the various toolbar combos
-       */
-
-       RefPtr<SizeGroup> toolbar_clock_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
-       toolbar_clock_size_group->add_widget (zoom_out_button);
-       toolbar_clock_size_group->add_widget (edit_cursor_clock);
-       toolbar_clock_size_group->add_widget (zoom_range_clock);
-       toolbar_clock_size_group->add_widget (nudge_clock);
-       toolbar_clock_size_group->add_widget (edit_mode_selector);
-       toolbar_clock_size_group->add_widget (snap_type_selector);
-       toolbar_clock_size_group->add_widget (snap_mode_selector);
-       toolbar_clock_size_group->add_widget (zoom_focus_selector);
-
-       HBox* edit_clock_hbox = manage (new HBox());
-       VBox* edit_clock_vbox = manage (new VBox());
-
-       edit_clock_hbox->pack_start (edit_cursor_clock, false, false);
-
-       edit_clock_vbox->set_spacing (3);
-       edit_clock_vbox->set_border_width (3);
-       edit_clock_vbox->pack_start (edit_cursor_clock_label, false, false);
-       edit_clock_vbox->pack_start (*edit_clock_hbox, false, false);
-
-       HBox* hbox = new HBox;
 
-       hbox->pack_start (*edit_clock_vbox, false, false);
-       hbox->pack_start (zoom_indicator_vbox, false, false); 
-       hbox->pack_start (zoom_focus_box, false, false);
-       hbox->pack_start (snap_type_box, false, false);
-       hbox->pack_start (snap_mode_box, false, false);
-       hbox->pack_start (edit_mode_box, false, false);
+       /* Nudge */
 
-       VBox *vbox = manage (new VBox);
+       HBox *nudge_box = manage (new HBox);
+       nudge_box->set_spacing(1);
+       nudge_box->set_border_width (2);
 
-       vbox->set_spacing (3);
-       vbox->set_border_width (3);
-
-       HBox *nbox = manage (new HBox);
-       
        nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
        nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
 
-       nbox->pack_start (nudge_backward_button, false, false);
-       nbox->pack_start (nudge_forward_button, false, false);
-       nbox->pack_start (nudge_clock, false, false, 5);
-
-       nudge_label.set_name ("ToolBarLabel");
+       nudge_box->pack_start (nudge_backward_button, false, false);
+       nudge_box->pack_start (nudge_forward_button, false, false);
+       nudge_box->pack_start (nudge_clock, false, false);
 
-       vbox->pack_start (nudge_label, false, false);
-       vbox->pack_start (*nbox, false, false);
 
-       hbox->pack_start (*vbox, false, false);
+       /* Pack everything in... */
 
-       hbox->show_all ();
+       HBox* hbox = new HBox;
+       hbox->set_spacing(10);
 
        tools_tearoff = new TearOff (*hbox);
        tools_tearoff->set_name ("MouseModeBase");
@@ -2819,11 +2720,18 @@ Editor::setup_toolbar ()
        tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
                                              &tools_tearoff->tearoff_window(), 0));
 
-       toolbar_hbox.set_spacing (8);
-       toolbar_hbox.set_border_width (2);
+       toolbar_hbox.set_spacing (10);
+       toolbar_hbox.set_border_width (1);
 
-       toolbar_hbox.pack_start (*tools_tearoff, false, false);
        toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
+       toolbar_hbox.pack_start (*tools_tearoff, false, false);
+
+       
+       hbox->pack_start (snap_box, false, false);
+       hbox->pack_start (zoom_box, false, false); 
+       hbox->pack_start (*nudge_box, false, false);
+
+       hbox->show_all ();
        
        toolbar_base.set_name ("ToolBarBase");
        toolbar_base.add (toolbar_hbox);
@@ -3055,7 +2963,7 @@ Editor::get_relevant_audio_tracks (AudioTimeAxisView& base, set<AudioTimeAxisVie
                        continue;
                }
 
-               RouteGroup* group = atv->route().edit_group();
+               RouteGroup* group = atv->route()->edit_group();
 
                if (group && group->is_active()) {
                        
@@ -3067,7 +2975,7 @@ Editor::get_relevant_audio_tracks (AudioTimeAxisView& base, set<AudioTimeAxisVie
                                
                                if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
                                        
-                                       if (tatv->route().edit_group() == group) {
+                                       if (tatv->route()->edit_group() == group) {
                                                relevant_tracks.insert (tatv);
                                        }
                                }
@@ -3102,31 +3010,31 @@ Editor::mapover_audio_tracks (slot<void,AudioTimeAxisView&,uint32_t> sl)
 }
 
 void
-Editor::mapped_set_selected_regionview_from_click (AudioTimeAxisView& atv, uint32_t ignored, 
-                                                 AudioRegionView* basis, vector<AudioRegionView*>* all_equivs)
+Editor::mapped_set_selected_regionview_from_click (RouteTimeAxisView& tv, uint32_t ignored, 
+                                                 RegionView* basis, vector<RegionView*>* all_equivs)
 {
-       AudioPlaylist* pl;
-       vector<AudioRegion*> results;
-       AudioRegionView* marv;
-       AudioDiskstream* ds;
+       Playlist* pl;
+       vector<Region*> results;
+       RegionView* marv;
+       Diskstream* ds;
 
-       if ((ds = atv.get_diskstream()) == 0) {
+       if ((ds = tv.get_diskstream()) == 0) {
                /* bus */
                return;
        }
 
-       if (&atv == &basis->get_time_axis_view()) {
+       if (&tv == &basis->get_time_axis_view()) {
                /* looking in same track as the original */
                return;
        }
 
        
-       if ((pl = ds->playlist()) != 0) {
-               pl->get_equivalent_regions (basis->region, results);
+       if ((pl = dynamic_cast<Playlist*>(ds->playlist())) != 0) {
+               pl->get_equivalent_regions (basis->region(), results);
        }
        
-       for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
-               if ((marv = atv.view->find_view (**ir)) != 0) {
+       for (vector<Region*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
+               if ((marv = tv.view()->find_view (**ir)) != 0) {
                        all_equivs->push_back (marv);
                }
        }
@@ -3135,7 +3043,7 @@ Editor::mapped_set_selected_regionview_from_click (AudioTimeAxisView& atv, uint3
 bool
 Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool no_track_remove)
 {
-       vector<AudioRegionView*> all_equivalent_regions;
+       vector<RegionView*> all_equivalent_regions;
        bool commit = false;
 
        if (!clicked_regionview || !clicked_audio_trackview) {
@@ -3190,7 +3098,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
                                                commit = true;
                                        }
                                        
-                                       for (vector<AudioRegionView*>::iterator i = all_equivalent_regions.begin(); i != all_equivalent_regions.end(); ++i) {
+                                       for (vector<RegionView*>::iterator i = all_equivalent_regions.begin(); i != all_equivalent_regions.end(); ++i) {
                                                selection->add (*i);
                                        }
                                } 
@@ -3223,58 +3131,58 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
                last_frame = 0;
                first_frame = max_frames;
 
-               for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
+               for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
                        if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
 
-                               if ((*x)->region.last_frame() > last_frame) {
-                                       last_frame = (*x)->region.last_frame();
+                               if ((*x)->region().last_frame() > last_frame) {
+                                       last_frame = (*x)->region().last_frame();
                                }
 
-                               if ((*x)->region.first_frame() < first_frame) {
-                                       first_frame = (*x)->region.first_frame();
+                               if ((*x)->region().first_frame() < first_frame) {
+                                       first_frame = (*x)->region().first_frame();
                                }
                        }
                }
 
                /* 2. figure out the boundaries for our search for new objects */
 
-               switch (clicked_regionview->region.coverage (first_frame, last_frame)) {
+               switch (clicked_regionview->region().coverage (first_frame, last_frame)) {
                case OverlapNone:
                        cerr << "no overlap, first = " << first_frame << " last = " << last_frame << " region = " 
-                            << clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl;
+                            << clicked_regionview->region().first_frame() << " .. " << clicked_regionview->region().last_frame() << endl;
 
-                       if (last_frame < clicked_regionview->region.first_frame()) {
+                       if (last_frame < clicked_regionview->region().first_frame()) {
                                first_frame = last_frame;
-                               last_frame = clicked_regionview->region.last_frame();
+                               last_frame = clicked_regionview->region().last_frame();
                        } else {
                                last_frame = first_frame;
-                               first_frame = clicked_regionview->region.first_frame();
+                               first_frame = clicked_regionview->region().first_frame();
                        }
                        break;
 
                case OverlapExternal:
                        cerr << "external overlap, first = " << first_frame << " last = " << last_frame << " region = " 
-                            << clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl;
+                            << clicked_regionview->region().first_frame() << " .. " << clicked_regionview->region().last_frame() << endl;
 
-                       if (last_frame < clicked_regionview->region.first_frame()) {
+                       if (last_frame < clicked_regionview->region().first_frame()) {
                                first_frame = last_frame;
-                               last_frame = clicked_regionview->region.last_frame();
+                               last_frame = clicked_regionview->region().last_frame();
                        } else {
                                last_frame = first_frame;
-                               first_frame = clicked_regionview->region.first_frame();
+                               first_frame = clicked_regionview->region().first_frame();
                        }
                        break;
 
                case OverlapInternal:
                        cerr << "internal overlap, first = " << first_frame << " last = " << last_frame << " region = " 
-                            << clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl;
+                            << clicked_regionview->region().first_frame() << " .. " << clicked_regionview->region().last_frame() << endl;
 
-                       if (last_frame < clicked_regionview->region.first_frame()) {
+                       if (last_frame < clicked_regionview->region().first_frame()) {
                                first_frame = last_frame;
-                               last_frame = clicked_regionview->region.last_frame();
+                               last_frame = clicked_regionview->region().last_frame();
                        } else {
                                last_frame = first_frame;
-                               first_frame = clicked_regionview->region.first_frame();
+                               first_frame = clicked_regionview->region().first_frame();
                        }
                        break;
 
@@ -3300,18 +3208,18 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
                
                /* 3. convert to a vector of audio regions */
 
-               vector<AudioRegionView*> audio_regions;
+               vector<RegionView*> regions;
                
                for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) {
-                       AudioRegionView* arv;
+                       RegionView* arv;
 
-                       if ((arv = dynamic_cast<AudioRegionView*>(*x)) != 0) {
-                               audio_regions.push_back (arv);
+                       if ((arv = dynamic_cast<RegionView*>(*x)) != 0) {
+                               regions.push_back (arv);
                        }
                }
 
-               if (!audio_regions.empty()) {
-                       selection->add (audio_regions);
+               if (!regions.empty()) {
+                       selection->add (regions);
                        commit = true;
                }
        }
@@ -3321,37 +3229,32 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
 }
 
 void
-Editor::set_selected_regionview_from_region_list (Region& r, Selection::Operation op)
+Editor::set_selected_regionview_from_region_list (Region& region, Selection::Operation op)
 {
-       vector<AudioRegionView*> all_equivalent_regions;
-       AudioRegion* region;
-
-       if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
-               return;
-       }
+       vector<RegionView*> all_equivalent_regions;
 
        for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
                
-               AudioTimeAxisView* tatv;
+               RouteTimeAxisView* tatv;
                
-               if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
+               if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
                        
-                       AudioPlaylist* pl;
-                       vector<AudioRegion*> results;
-                       AudioRegionView* marv;
-                       AudioDiskstream* ds;
+                       Playlist* pl;
+                       vector<Region*> results;
+                       RegionView* marv;
+                       Diskstream* ds;
                        
                        if ((ds = tatv->get_diskstream()) == 0) {
                                /* bus */
                                continue;
                        }
 
-                       if ((pl = ds->playlist()) != 0) {
-                               pl->get_region_list_equivalent_regions (*region, results);
+                       if ((pl = dynamic_cast<Playlist*>(ds->playlist())) != 0) {
+                               pl->get_region_list_equivalent_regions (region, results);
                        }
                        
-                       for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
-                               if ((marv = tatv->view->find_view (**ir)) != 0) {
+                       for (vector<Region*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
+                               if ((marv = tatv->view()->find_view (**ir)) != 0) {
                                        all_equivalent_regions.push_back (marv);
                                }
                        }
@@ -3380,10 +3283,10 @@ Editor::set_selected_regionview_from_region_list (Region& r, Selection::Operatio
 bool
 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
 {
-       AudioRegionView* rv;
-       AudioRegion* ar;
+       RegionView* rv;
+       Region* ar;
 
-       if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
+       if ((ar = dynamic_cast<Region*> (r)) == 0) {
                return TRUE;
        }
 
@@ -3395,7 +3298,7 @@ Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv,
           a single other region.
        */
 
-       if (selection->audio_regions.size() > 1) {
+       if (selection->regions.size() > 1) {
                return TRUE;
        }
        
@@ -3560,7 +3463,7 @@ Editor::duplicate_dialog (bool dup_region)
 
        if (sscanf (text.c_str(), "%f", &times) == 1) {
                if (dup_region) {
-                       AudioRegionSelection regions;
+                       RegionSelection regions;
                        regions.add (clicked_regionview);
                        duplicate_some_regions (regions, times);
                } else {
@@ -3611,9 +3514,9 @@ Editor::edit_mode_selection_done ()
        string choice = edit_mode_selector.get_active_text();
        EditMode mode = Slide;
 
-       if (choice == _("Splice")) {
+       if (choice == _("Splice Edit")) {
                mode = Splice;
-       } else if (choice == _("Slide")) {
+       } else if (choice == _("Slide Edit")) {
                mode = Slide;
        }
 
@@ -3629,18 +3532,18 @@ Editor::snap_type_selection_done ()
 
        string choice = snap_type_selector.get_active_text();
        SnapType snaptype = SnapToFrame;
-       
+
        if (choice == _("Beats/3")) {
-                snaptype = SnapToAThirdBeat;
-        } else if (choice == _("Beats/4")) {
-                snaptype = SnapToAQuarterBeat;
-        } else if (choice == _("Beats/8")) {
-                snaptype = SnapToAEighthBeat;
-        } else if (choice == _("Beats/16")) {
-                snaptype = SnapToASixteenthBeat;
-        } else if (choice == _("Beats/32")) {
-                snaptype = SnapToAThirtysecondBeat;
-        } else if (choice == _("Beats")) {
+               snaptype = SnapToAThirdBeat;
+       } else if (choice == _("Beats/4")) {
+               snaptype = SnapToAQuarterBeat;
+       } else if (choice == _("Beats/8")) {
+               snaptype = SnapToAEighthBeat;
+       } else if (choice == _("Beats/16")) {
+               snaptype = SnapToASixteenthBeat;
+       } else if (choice == _("Beats/32")) {
+               snaptype = SnapToAThirtysecondBeat;
+       } else if (choice == _("Beats")) {
                snaptype = SnapToBeat;
        } else if (choice == _("Bars")) {
                snaptype = SnapToBar;
@@ -3668,10 +3571,10 @@ Editor::snap_type_selection_done ()
                snaptype = SnapToSeconds;
        } else if (choice == _("Minutes")) {
                snaptype = SnapToMinutes;
-        } else if (choice == _("None")) {
+       } else if (choice == _("None")) {
                snaptype = SnapToFrame;
        }
-       
+
        set_snap_to (snaptype);
 }      
 
@@ -3685,9 +3588,9 @@ Editor::snap_mode_selection_done ()
        string choice = snap_mode_selector.get_active_text();
        SnapMode mode = SnapNormal;
 
-       if (choice == _("Normal")) {
+       if (choice == _("Normal Snap")) {
                mode = SnapNormal;
-       } else if (choice == _("Magnetic")) {
+       } else if (choice == _("Magnetic Snap")) {
                mode = SnapMagnetic;
        }
 
@@ -3704,15 +3607,15 @@ Editor::zoom_focus_selection_done ()
        string choice = zoom_focus_selector.get_active_text();
        ZoomFocus focus_type = ZoomFocusLeft;
 
-       if (choice == _("Left")) {
+       if (choice == _("Focus Left")) {
                focus_type = ZoomFocusLeft;
-       } else if (choice == _("Right")) {
+       } else if (choice == _("Focus Right")) {
                focus_type = ZoomFocusRight;
-       } else if (choice == _("Center")) {
+       } else if (choice == _("Focus Center")) {
                focus_type = ZoomFocusCenter;
-        } else if (choice == _("Playhead")) {
+       } else if (choice == _("Focus Playhead")) {
                focus_type = ZoomFocusPlayhead;
-        } else if (choice == _("Edit Cursor")) {
+       } else if (choice == _("Focus Edit Cursor")) {
                focus_type = ZoomFocusEdit;
        } 
 
@@ -3782,7 +3685,7 @@ void
 Editor::region_selection_changed ()
 {
        for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
-               (*i)->set_selected_regionviews (selection->audio_regions);
+               (*i)->set_selected_regionviews (selection->regions);
        }
 }
 
@@ -4052,8 +3955,8 @@ Editor::playlist_deletion_dialog (Playlist* pl)
 bool
 Editor::audio_region_selection_covers (jack_nframes_t where)
 {
-       for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
-               if ((*a)->region.covers (where)) {
+       for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
+               if ((*a)->region().covers (where)) {
                        return true;
                }
        }
@@ -4064,10 +3967,10 @@ Editor::audio_region_selection_covers (jack_nframes_t where)
 void
 Editor::prepare_for_cleanup ()
 {
-       cut_buffer->clear_audio_regions ();
+       cut_buffer->clear_regions ();
        cut_buffer->clear_playlists ();
 
-       selection->clear_audio_regions ();
+       selection->clear_regions ();
        selection->clear_playlists ();
 }
 
index 478a8c96ab17ede9cb2f50ff4fd84f919f2b9c14..c31dfd5ede788d14dd0425bf9db8a3e46d4b78ad 100644 (file)
@@ -40,7 +40,7 @@
 #include <gtkmm2ext/click_box.h>
 #include <gtkmm2ext/dndtreeview.h>
 
-#include <ardour/stateful.h>
+#include <pbd/stateful.h>
 #include <ardour/session.h>
 #include <ardour/tempo.h>
 #include <ardour/location.h>
@@ -69,6 +69,7 @@ namespace ARDOUR {
        class AudioDiskstream;
        class RouteGroup;
        class Playlist;
+       class AudioPlaylist;
        class Region;
        class Location;
        class TempoSection;
@@ -83,6 +84,7 @@ namespace LADSPA {
 }
 
 class TimeAxisView;
+class RouteTimeAxisView;
 class AudioTimeAxisView;
 class AutomationTimeAxisView;
 class AudioRegionView;
@@ -100,6 +102,7 @@ class TrackSelection;
 class AutomationSelection;
 class MixerStrip;
 class StreamView;
+class AudioStreamView;
 class ControlPoint;
 #ifdef FFT_ANALYSIS
 class AnalysisWindow;
@@ -405,8 +408,8 @@ class Editor : public PublicEditor
 
        TimeAxisView*      clicked_trackview;
        AudioTimeAxisView* clicked_audio_trackview;
-       AudioRegionView*   clicked_regionview;
-       AudioRegionView*   latest_regionview;
+       RegionView*        clicked_regionview;
+       RegionView*        latest_regionview;
        uint32_t           clicked_selection;
        CrossfadeView*     clicked_crossfadeview;
        ControlPoint*      clicked_control_point;
@@ -416,7 +419,7 @@ class Editor : public PublicEditor
 
        /* functions to be passed to mapover_audio_tracks(), possibly with sigc::bind()-supplied arguments */
 
-       void mapped_set_selected_regionview_from_click (AudioTimeAxisView&, uint32_t, AudioRegionView*, vector<AudioRegionView*>*);
+       void mapped_set_selected_regionview_from_click (RouteTimeAxisView&, uint32_t, RegionView*, vector<RegionView*>*);
        void mapped_use_new_playlist (AudioTimeAxisView&, uint32_t);
        void mapped_use_copy_playlist (AudioTimeAxisView&, uint32_t);
        void mapped_clear_playlist (AudioTimeAxisView&, uint32_t);
@@ -426,7 +429,7 @@ class Editor : public PublicEditor
        void button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type);
        bool button_release_can_deselect;
 
-       void catch_vanishing_audio_regionview (AudioRegionView *);
+       void catch_vanishing_regionview (RegionView *);
 
        bool set_selected_control_point_from_click (bool press, Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false);
        bool set_selected_track_from_click (bool press, Selection::Operation op = Selection::Set, bool with_undo = true, bool no_remove=false);
@@ -434,7 +437,7 @@ class Editor : public PublicEditor
 
        void set_selected_regionview_from_region_list (ARDOUR::Region& region, Selection::Operation op = Selection::Set);
        bool set_selected_regionview_from_map_event (GdkEventAny*, StreamView*, ARDOUR::Region*);
-       void collect_new_region_view (AudioRegionView *);
+       void collect_new_region_view (RegionView *);
 
        Gtk::Menu track_context_menu;
        Gtk::Menu track_region_context_menu;
@@ -455,12 +458,11 @@ class Editor : public PublicEditor
        Gtk::Menu* build_track_selection_context_menu (jack_nframes_t);
        void add_dstream_context_items (Gtk::Menu_Helpers::MenuList&);
        void add_bus_context_items (Gtk::Menu_Helpers::MenuList&);
-       void add_region_context_items (StreamView*, ARDOUR::Region*, Gtk::Menu_Helpers::MenuList&);
-       void add_crossfade_context_items (StreamView*, ARDOUR::Crossfade*, Gtk::Menu_Helpers::MenuList&, bool many);
+       void add_region_context_items (AudioStreamView*, ARDOUR::Region*, Gtk::Menu_Helpers::MenuList&);
+       void add_crossfade_context_items (AudioStreamView*, ARDOUR::Crossfade*, Gtk::Menu_Helpers::MenuList&, bool many);
        void add_selection_context_items (Gtk::Menu_Helpers::MenuList&);
 
-       void handle_new_route (ARDOUR::Route&);
-       void handle_new_route_p (ARDOUR::Route*);
+       void handle_new_route (boost::shared_ptr<ARDOUR::Route>);
        void remove_route (TimeAxisView *);
        bool route_removal;
 
@@ -854,7 +856,7 @@ class Editor : public PublicEditor
        void lower_region_to_bottom ();
        void split_region ();
        void split_region_at (jack_nframes_t);
-       void split_regions_at (jack_nframes_t, AudioRegionSelection&);
+       void split_regions_at (jack_nframes_t, RegionSelection&);
        void crop_region_to_selection ();
        void set_a_regions_sync_position (ARDOUR::Region&, jack_nframes_t);
        void set_region_sync_from_edit_cursor ();
@@ -867,13 +869,13 @@ class Editor : public PublicEditor
        void remove_clicked_region ();
        void destroy_clicked_region ();
        void edit_region ();
-       void duplicate_some_regions (AudioRegionSelection&, float times);
+       void duplicate_some_regions (RegionSelection&, float times);
        void duplicate_selection (float times);
        void region_fill_selection ();
 
        void region_fill_track ();
-       void audition_playlist_region_standalone (ARDOUR::AudioRegion&);
-       void audition_playlist_region_via_route (ARDOUR::AudioRegion&, ARDOUR::Route&);
+       void audition_playlist_region_standalone (ARDOUR::Region&);
+       void audition_playlist_region_via_route (ARDOUR::Region&, ARDOUR::Route&);
        void split_multichannel_region();
        void reverse_region ();
        void normalize_region ();
@@ -1020,7 +1022,7 @@ class Editor : public PublicEditor
        bool have_pending_keyboard_selection;
        jack_nframes_t pending_keyboard_selection_start;
 
-       ARDOUR::AudioRegion* select_region_for_operation (int dir, TimeAxisView **tv);
+       ARDOUR::Region* select_region_for_operation (int dir, TimeAxisView **tv);
        void extend_selection_to_end_of_region (bool next);
        void extend_selection_to_start_of_region (bool previous);
 
@@ -1094,7 +1096,7 @@ class Editor : public PublicEditor
        void remove_gain_control_point (ArdourCanvas::Item*, GdkEvent*);
        void remove_control_point (ArdourCanvas::Item*, GdkEvent*);
 
-       void mouse_brush_insert_region (AudioRegionView*, jack_nframes_t pos);
+       void mouse_brush_insert_region (RegionView*, jack_nframes_t pos);
        void brush (jack_nframes_t);
 
        void show_verbose_time_cursor (jack_nframes_t frame, double offset = 0, double xpos=-1, double ypos=-1);
@@ -1112,10 +1114,10 @@ class Editor : public PublicEditor
        bool canvas_fade_in_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
        bool canvas_fade_out_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
        bool canvas_fade_out_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
-       bool canvas_region_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
-       bool canvas_region_view_name_highlight_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
-       bool canvas_region_view_name_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*);
-       bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioTimeAxisView*);
+       bool canvas_region_view_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*);
+       bool canvas_region_view_name_highlight_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*);
+       bool canvas_region_view_name_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*);
+       bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, RouteTimeAxisView*);
        bool canvas_marker_event (GdkEvent* event,ArdourCanvas::Item*, Marker*);
        bool canvas_zoom_rect_event (GdkEvent* event,ArdourCanvas::Item*);
        bool canvas_tempo_marker_event (GdkEvent* event,ArdourCanvas::Item*, TempoMarker*);
@@ -1263,12 +1265,7 @@ class Editor : public PublicEditor
 
        void editor_mixer_button_toggled ();
 
-       AudioClock               selection_start_clock;
-       Gtk::Label               selection_start_clock_label;
-       AudioClock               selection_end_clock;
-       Gtk::Label               selection_end_clock_label;
        AudioClock               edit_cursor_clock;
-       Gtk::Label               edit_cursor_clock_label;
        AudioClock               zoom_range_clock;
        Gtk::Button              zoom_in_button;
        Gtk::Button              zoom_out_button;
@@ -1280,8 +1277,8 @@ class Editor : public PublicEditor
        Gtk::Table               toolbar_selection_clock_table;
        Gtk::Label               toolbar_selection_cursor_label;
        
-       Gtk::Table               mouse_mode_button_table;
-       Gtkmm2ext::TearOff*       mouse_mode_tearoff;
+       Gtk::HBox                mouse_mode_button_box;
+       Gtkmm2ext::TearOff*      mouse_mode_tearoff;
        Gtk::ToggleButton        mouse_select_button;
        Gtk::ToggleButton        mouse_move_button;
        Gtk::ToggleButton        mouse_gain_button;
@@ -1299,32 +1296,23 @@ class Editor : public PublicEditor
        Gtk::ToggleButton        global_automation_button;
 
        Gtk::ComboBoxText edit_mode_selector;
-       Gtk::Label               edit_mode_label;
-       Gtk::VBox                edit_mode_box;
+       Gtk::VBox         edit_mode_box;
 
        void edit_mode_selection_done ();
 
        Gtk::ComboBoxText snap_type_selector;
-       Gtk::Label               snap_type_label;
-       Gtk::VBox                snap_type_box;
+       Gtk::ComboBoxText snap_mode_selector;
+       Gtk::HBox         snap_box;
 
        void snap_type_selection_done ();
-
-       Gtk::ComboBoxText               snap_mode_selector;
-       Gtk::Label               snap_mode_label;
-       Gtk::VBox                snap_mode_box;
-
        void snap_mode_selection_done ();
        
        Gtk::ComboBoxText zoom_focus_selector;
-       Gtk::Label               zoom_focus_label;
        Gtk::VBox                zoom_focus_box;
        
        void zoom_focus_selection_done ();
 
-       Gtk::Label          zoom_indicator_label;
-       Gtk::HBox           zoom_indicator_box;
-       Gtk::VBox           zoom_indicator_vbox;
+       Gtk::HBox           zoom_box;
 
        void                update_zoom_indicator ();
        void                zoom_adjustment_changed();
@@ -1533,12 +1521,12 @@ class Editor : public PublicEditor
        void start_trim (ArdourCanvas::Item*, GdkEvent*);
        void point_trim (GdkEvent*);
        void trim_motion_callback (ArdourCanvas::Item*, GdkEvent*);
-       void single_contents_trim (AudioRegionView&, jack_nframes_t, bool, bool, bool);
-       void single_start_trim (AudioRegionView&, jack_nframes_t, bool, bool);
-       void single_end_trim (AudioRegionView&, jack_nframes_t, bool, bool);
+       void single_contents_trim (RegionView&, jack_nframes_t, bool, bool, bool);
+       void single_start_trim (RegionView&, jack_nframes_t, bool, bool);
+       void single_end_trim (RegionView&, jack_nframes_t, bool, bool);
 
        void trim_finished_callback (ArdourCanvas::Item*, GdkEvent*);
-       void thaw_region_after_trim (AudioRegionView& rv);
+       void thaw_region_after_trim (RegionView& rv);
        
        void trim_region_to_edit_cursor ();
        void trim_region_from_edit_cursor ();
@@ -1592,7 +1580,7 @@ class Editor : public PublicEditor
        void export_range (jack_nframes_t start, jack_nframes_t end);
        void export_range_markers ();
 
-       int  write_region_selection(AudioRegionSelection&);
+       int  write_region_selection(RegionSelection&);
        bool write_region (string path, ARDOUR::AudioRegion&);
        void export_region ();
        void bounce_region_selection ();
@@ -1600,7 +1588,7 @@ class Editor : public PublicEditor
        void external_edit_region ();
 
        int write_audio_selection (TimeSelection&);
-       bool write_audio_range (ARDOUR::Playlist&, uint32_t channels, list<ARDOUR::AudioRange>&);
+       bool write_audio_range (ARDOUR::AudioPlaylist&, uint32_t channels, list<ARDOUR::AudioRange>&);
 
        void write_selection ();
 
@@ -1671,7 +1659,7 @@ class Editor : public PublicEditor
        struct TimeStretchDialog : public ArdourDialog {
            ARDOUR::Session::TimeStretchRequest request;
            Editor&               editor;
-           AudioRegionSelection  regions;
+           RegionSelection       regions;
            Gtk::ProgressBar      progress_bar;
            Gtk::ToggleButton     quick_button;
            Gtk::ToggleButton     antialias_button;
@@ -1697,7 +1685,7 @@ class Editor : public PublicEditor
        TimeStretchDialog* current_timestretch;
 
        static void* timestretch_thread (void *arg);
-       int run_timestretch (AudioRegionSelection&, float fraction);
+       int run_timestretch (RegionSelection&, float fraction);
        void do_timestretch (TimeStretchDialog&);
 
        /* editor-mixer strip */
@@ -1776,7 +1764,6 @@ class Editor : public PublicEditor
        Gtk::Button      nudge_backward_button;
        Gtk::HBox        nudge_hbox;
        Gtk::VBox        nudge_vbox;
-       Gtk::Label       nudge_label;
        AudioClock       nudge_clock;
 
        jack_nframes_t get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next);
@@ -1799,11 +1786,11 @@ class Editor : public PublicEditor
        sigc::connection step_timeout;
 
        TimeAxisView* entered_track;
-       AudioRegionView* entered_regionview;
+       RegionView*   entered_regionview;
        bool clear_entered_track;
        gint left_track_canvas (GdkEventCrossing*);
        void set_entered_track (TimeAxisView*);
-       void set_entered_regionview (AudioRegionView*);
+       void set_entered_regionview (RegionView*);
        gint left_automation_track ();
 
        bool _new_regionviews_show_envelope;
index e20e6ee8eb51690e0d70240d787df78948a5f731..65195ca82204295dc10f3d0751e02423525a44f2 100644 (file)
@@ -357,6 +357,8 @@ Editor::register_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, X_("addExternalAudioAsTrack"), _("as Tracks"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsTrack));
        ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, X_("addExternalAudioAsTapeTrack"), _("as Tape Tracks"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsTapeTrack));
+       ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, X_("addExternalAudioToTrack"), _("to Tracks"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack));
        ActionManager::session_sensitive_actions.push_back (act);
 
index 2c64f2cf152668bb2a4f9a20eb166f108c25ee92..7524f9605cab34eb48c87c58b8fd9f9a61389157 100644 (file)
@@ -268,7 +268,7 @@ Editor::embed_sndfile (Glib::ustring path, bool split, bool multiple_files, bool
                idspec += string_compose(":%1", n);
                
                try {
-                       source = AudioFileSource::create (idspec.c_str());
+                       source = AudioFileSource::create (idspec.c_str(), (mode == ImportAsTrack ? AudioFileSource::Destructive : AudioFileSource::Flag (0)));
                        sources.push_back(source);
                } 
                
@@ -306,16 +306,18 @@ Editor::embed_sndfile (Glib::ustring path, bool split, bool multiple_files, bool
 }
 
 int
- Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32_t out_chans, AudioTrack* track, jack_nframes_t& pos, ImportMode mode)
- {
-        switch (mode) {
-        case ImportAsRegion:
-                /* relax, its been done */
-                break;
+Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32_t out_chans, AudioTrack* track, jack_nframes_t& pos, ImportMode mode)
+{
+       AudioRegion* copy;
+
+       switch (mode) {
+       case ImportAsRegion:
+               /* relax, its been done */
+               break;
                
        case ImportToTrack:
                if (track) {
-                       Playlist* playlist  = track->disk_stream().playlist();
+                       Playlist* playlist  = track->diskstream().playlist();
                        
                        AudioRegion* copy = new AudioRegion (region);
                        begin_reversible_command (_("insert sndfile"));
@@ -329,11 +331,21 @@ int
                break;
                
        case ImportAsTrack:
-               AudioTrack* at = session->new_audio_track (in_chans, out_chans);
-               AudioRegion* copy = new AudioRegion (region);
-               at->disk_stream().playlist()->add_region (*copy, pos);
+       { 
+               boost::shared_ptr<AudioTrack> at (session->new_audio_track (in_chans, out_chans, Normal));
+               copy = new AudioRegion (region);
+               at->diskstream().playlist()->add_region (*copy, pos);
+               break;
+       }
+
+       case ImportAsTapeTrack:
+       {
+               boost::shared_ptr<AudioTrack> at (session->new_audio_track (in_chans, out_chans, Destructive));
+               copy = new AudioRegion (region);
+               at->diskstream().playlist()->add_region (*copy, pos);
                break;
        }
+       }
 
        return 0;
 }
index acad3371a0d8cd09cf8feeaf5a127930969085ee..5b575b4814f48ae25a12295822ef04706c14fd76 100644 (file)
@@ -4,7 +4,7 @@
 #include "editor.h"
 #include "editing.h"
 #include "audio_time_axis.h"
-#include "regionview.h"
+#include "region_view.h"
 #include "selection.h"
 
 using namespace ARDOUR;
index 41350a1da421142759d00e033f0ae31ba3176395..e8ba2b8a6032bce19af73d77172725eaa0e8070e 100644 (file)
@@ -128,7 +128,7 @@ Editor::initialize_canvas ()
        
        time_line_group = new ArdourCanvas::Group (*track_canvas.root(), 0.0, 0.0);
        cursor_group = new ArdourCanvas::Group (*track_canvas.root(), 0.0, 0.0);
-       
+
        time_canvas.set_name ("EditorTimeCanvas");
        time_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
        time_canvas.set_flags (CAN_FOCUS);
index 43114534c5a4bf780325b1499f9ee2b7142483f9..8e635bbe13a20bfc7ac49673b017bf00b965dd3e 100644 (file)
@@ -26,8 +26,8 @@
 
 #include "editor.h"
 #include "public_editor.h"
-#include "regionview.h"
-#include "streamview.h"
+#include "audio_region_view.h"
+#include "audio_streamview.h"
 #include "crossfade_view.h"
 #include "audio_time_axis.h"
 #include "region_gain_line.h"
@@ -212,7 +212,7 @@ Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
 }
 
 bool
-Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
+Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView *rv)
 {
        gint ret = FALSE;
 
@@ -251,7 +251,7 @@ Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, Aud
 }
 
 bool
-Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, AudioTimeAxisView *tv)
+Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, RouteTimeAxisView *tv)
 {
        bool ret = FALSE;
        
@@ -262,7 +262,7 @@ Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, Aud
                clicked_regionview = 0;
                clicked_control_point = 0;
                clicked_trackview = tv;
-               clicked_audio_trackview = tv;
+               clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(tv);
                ret = button_press_handler (item, event, StreamItem);
                break;
 
@@ -512,22 +512,25 @@ Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item,
        if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
 
                if (atv->is_audio_track()) {
-                       
-                       AudioPlaylist* pl = atv->get_diskstream()->playlist();
-                       Playlist::RegionList* rl = pl->regions_at (event_frame (event));
 
-                       if (!rl->empty()) {
-                               DescendingRegionLayerSorter cmp;
-                               rl->sort (cmp);
+                       AudioPlaylist* pl;
+                       if ((pl = dynamic_cast<AudioPlaylist*> (atv->get_diskstream()->playlist())) != 0) {
+
+                               Playlist::RegionList* rl = pl->regions_at (event_frame (event));
+
+                               if (!rl->empty()) {
+                                       DescendingRegionLayerSorter cmp;
+                                       rl->sort (cmp);
 
-                               AudioRegionView* arv = atv->view->find_view (*(dynamic_cast<AudioRegion*> (rl->front())));
+                                       RegionView* rv = atv->view()->find_view (*rl->front());
 
-                               /* proxy */
-                               
-                               delete rl;
+                                       /* proxy */
 
-                               return canvas_region_view_event (event, arv->get_canvas_group(), arv);
-                       } 
+                                       delete rl;
+
+                                       return canvas_region_view_event (event, rv->get_canvas_group(), rv);
+                               } 
+                       }
                }
        }
 
@@ -696,7 +699,7 @@ Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* it
 
 
 bool
-Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, AudioRegionView* rv)
+Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, RegionView* rv)
 {
        bool ret = false;
        
@@ -708,20 +711,20 @@ Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::
                clicked_control_point = 0;
                clicked_trackview = &clicked_regionview->get_time_axis_view();
                clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
-               ret = button_press_handler (item, event, AudioRegionViewNameHighlight);
+               ret = button_press_handler (item, event, RegionViewNameHighlight);
                break;
        case GDK_BUTTON_RELEASE:
-               ret = button_release_handler (item, event, AudioRegionViewNameHighlight);
+               ret = button_release_handler (item, event, RegionViewNameHighlight);
                break;
        case GDK_MOTION_NOTIFY:
-               ret = motion_handler (item, event, AudioRegionViewNameHighlight);
+               ret = motion_handler (item, event, RegionViewNameHighlight);
                break;
        case GDK_ENTER_NOTIFY:
-               ret = enter_handler (item, event, AudioRegionViewNameHighlight);
+               ret = enter_handler (item, event, RegionViewNameHighlight);
                break;
 
        case GDK_LEAVE_NOTIFY:
-               ret = leave_handler (item, event, AudioRegionViewNameHighlight);
+               ret = leave_handler (item, event, RegionViewNameHighlight);
                break;
 
        default:
@@ -732,7 +735,7 @@ Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::
 }
 
 bool
-Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView* rv)
+Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, RegionView* rv)
 {
        bool ret = false;
 
@@ -744,20 +747,20 @@ Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item
                clicked_control_point = 0;
                clicked_trackview = &clicked_regionview->get_time_axis_view();
                clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
-               ret = button_press_handler (item, event, AudioRegionViewName);
+               ret = button_press_handler (item, event, RegionViewName);
                break;
        case GDK_BUTTON_RELEASE:
-               ret = button_release_handler (item, event, AudioRegionViewName);
+               ret = button_release_handler (item, event, RegionViewName);
                break;
        case GDK_MOTION_NOTIFY:
-               ret = motion_handler (item, event, AudioRegionViewName);
+               ret = motion_handler (item, event, RegionViewName);
                break;
        case GDK_ENTER_NOTIFY:
-               ret = enter_handler (item, event, AudioRegionViewName);
+               ret = enter_handler (item, event, RegionViewName);
                break;
 
        case GDK_LEAVE_NOTIFY:
-               ret = leave_handler (item, event, AudioRegionViewName);
+               ret = leave_handler (item, event, RegionViewName);
                break;
 
        default:
index 7339536e4255a3fb8979063a47ef53ede7b93163..46a704b435003603f35fde7ff0e72cd32caf89a8 100644 (file)
@@ -31,7 +31,7 @@
 #include "selection.h"
 #include "time_axis_view.h"
 #include "audio_time_axis.h"
-#include "regionview.h"
+#include "audio_region_view.h"
 
 #include <pbd/pthread_utils.h>
 #include <ardour/types.h>
@@ -92,12 +92,12 @@ Editor::export_region ()
                return;
        }
 
-       ExportDialog* dialog = new ExportRegionDialog (*this, &clicked_regionview->region);
+       ExportDialog* dialog = new ExportRegionDialog (*this, &clicked_regionview->region());
                
        dialog->connect_to_session (session);
        dialog->set_range (
-               clicked_regionview->region.first_frame(), 
-               clicked_regionview->region.last_frame());
+               clicked_regionview->region().first_frame(), 
+               clicked_regionview->region().last_frame());
        dialog->start_export();
 }
 
@@ -123,24 +123,26 @@ Editor::export_range_markers ()
 }      
 
 int
-Editor::write_region_selection (AudioRegionSelection& regions)
+Editor::write_region_selection (RegionSelection& regions)
 {
-       for (AudioRegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
-               if (write_region ("", (*i)->region) == false) {
-                       return -1;
-               }
+       for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
+               AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*i);
+               if (arv)
+                       if (write_region ("", arv->audio_region()) == false)
+                               return -1;
        }
+
        return 0;
 }
 
 void
 Editor::bounce_region_selection ()
 {
-       for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
                
-               AudioRegion& region ((*i)->region);
-               AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&(*i)->get_time_axis_view());
-               AudioTrack* track = dynamic_cast<AudioTrack*>(&(atv->route()));
+               Region& region ((*i)->region());
+               RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&(*i)->get_time_axis_view());
+               Track* track = dynamic_cast<Track*>(rtv->route().get());
 
                InterThreadInfo itt;
 
@@ -287,7 +289,7 @@ Editor::write_audio_selection (TimeSelection& ts)
 
                if (atv->is_audio_track()) {
 
-                       Playlist* playlist = atv->get_diskstream()->playlist();
+                       AudioPlaylist* playlist = dynamic_cast<AudioPlaylist*>(atv->get_diskstream()->playlist());
                        
                        if (playlist && write_audio_range (*playlist, atv->get_diskstream()->n_channels(), ts) == 0) {
                                ret = -1;
@@ -300,7 +302,7 @@ Editor::write_audio_selection (TimeSelection& ts)
 }
 
 bool
-Editor::write_audio_range (Playlist& playlist, uint32_t channels, list<AudioRange>& range)
+Editor::write_audio_range (AudioPlaylist& playlist, uint32_t channels, list<AudioRange>& range)
 {
        AudioFileSource* fs;
        const jack_nframes_t chunk_size = 4096;
@@ -435,7 +437,7 @@ Editor::write_selection ()
 {
        if (!selection->time.empty()) {
                write_audio_selection (selection->time);
-       } else if (!selection->audio_regions.empty()) {
-               write_region_selection (selection->audio_regions);
+       } else if (!selection->regions.empty()) {
+               write_region_selection (selection->regions);
        }
 }
index 4f6010ec2c08565971733c5cd71b96f7a0e75aaa..7f3a0d3fccc22c3bbf874e367d9065dc24e9fd8a 100644 (file)
@@ -23,8 +23,8 @@ enum ItemType {
        TempoMarkerItem,
        MeterBarItem,
        TempoBarItem,
-       AudioRegionViewNameHighlight,
-       AudioRegionViewName,
+       RegionViewNameHighlight,
+       RegionViewName,
        StartSelectionTrimItem,
        EndSelectionTrimItem,
        AutomationTrackItem,
index b665f8b0a6a5579510aab1dc0134ffb4adda8f1f..a0368b23b048cec58342feca3ab865d96567011a 100644 (file)
@@ -23,7 +23,7 @@
 #include <pbd/memento_command.h>
 
 #include "editor.h"
-#include "regionview.h"
+#include "region_view.h"
 #include "selection.h"
 
 #include "i18n.h"
@@ -82,10 +82,10 @@ Editor::kbd_do_split (GdkEvent* ev)
        jack_nframes_t where = event_frame (ev);
 
        if (entered_regionview) {
-               if (selection->audio_regions.find (entered_regionview) != selection->audio_regions.end()) {
-                       split_regions_at (where, selection->audio_regions);
+               if (selection->regions.find (entered_regionview) != selection->regions.end()) {
+                       split_regions_at (where, selection->regions);
                } else {
-                       AudioRegionSelection s;
+                       RegionSelection s;
                        s.add (entered_regionview);
                        split_regions_at (where, s);
                }
@@ -103,11 +103,11 @@ Editor::kbd_mute_unmute_region ()
 {
        if (entered_regionview) {
                begin_reversible_command (_("mute region"));
-               XMLNode &before = entered_regionview->region.playlist()->get_state();
+               XMLNode &before = entered_regionview->region().playlist()->get_state();
                
-           entered_regionview->region.set_muted (!entered_regionview->region.muted());
+           entered_regionview->region().set_muted (!entered_regionview->region().muted());
                
-               XMLNode &after = entered_regionview->region.playlist()->get_state();
+               XMLNode &after = entered_regionview->region().playlist()->get_state();
                session->add_command (new MementoCommand<ARDOUR::Playlist>(*(entered_regionview->region.playlist()), before, after));
                commit_reversible_command();
        }
@@ -126,7 +126,7 @@ Editor::kbd_do_set_sync_position (GdkEvent* ev)
        snap_to (where);
 
        if (entered_regionview) {
-         set_a_regions_sync_position (entered_regionview->region, where);
+         set_a_regions_sync_position (entered_regionview->region(), where);
        }
 }
 
index baa158cbf8374c6e73ceda214b1227ccbbcda0db..1bcaafd27957f1a045f801b012698b9498592630 100644 (file)
@@ -30,7 +30,7 @@
 #include "ardour_ui.h"
 #include "editor.h"
 #include "time_axis_view.h"
-#include "regionview.h"
+#include "region_view.h"
 #include "selection.h"
 
 #include "i18n.h"
@@ -66,7 +66,7 @@ Editor::keyboard_selection_begin ()
 void
 Editor::keyboard_duplicate_region ()
 {
-       if (selection->audio_regions.empty()) {
+       if (selection->regions.empty()) {
                return;
        }
 
@@ -74,9 +74,9 @@ Editor::keyboard_duplicate_region ()
        bool was_floating;
 
        if (get_prefix (prefix, was_floating) == 0) {
-               duplicate_some_regions (selection->audio_regions, prefix);
+               duplicate_some_regions (selection->regions, prefix);
        } else {
-               duplicate_some_regions (selection->audio_regions, 1);
+               duplicate_some_regions (selection->regions, 1);
        }
 }
 
index c4d8f3143fedbcca93ac6ebad1d7df1700679905..ccc1415888449f1c92bfac39f810de0106c48f25 100644 (file)
@@ -717,9 +717,9 @@ Editor::marker_menu_set_from_selection ()
                                }
                        }
                        else {
-                               if (!selection->audio_regions.empty()) {
-                                       l->set_start (selection->audio_regions.start());
-                                       l->set_end (selection->audio_regions.end_frame());
+                               if (!selection->regions.empty()) {
+                                       l->set_start (selection->regions.start());
+                                       l->set_end (selection->regions.end_frame());
                                }
                        }
                }
index a55b6f2066c1b4a1887cc8c37c2c9e3cf79ea464..246dbdc6473337501d943c82165bf8c175b27cdd 100644 (file)
@@ -131,7 +131,7 @@ Editor::set_selected_mixer_strip (TimeAxisView& view)
 
                /* might be nothing to do */
 
-               if (&current_mixer_strip->route() == &at->route()) {
+               if (current_mixer_strip->route() == at->route()) {
                        return;
                }
 
@@ -221,7 +221,7 @@ Editor::current_mixer_strip_hidden ()
                AudioTimeAxisView* tmp;
                
                if ((tmp = dynamic_cast<AudioTimeAxisView*>(*i)) != 0) {
-                       if (&(tmp->route()) == &(current_mixer_strip->route())) {
+                       if (tmp->route() == current_mixer_strip->route()) {
                                (*i)->set_selected (false);
                                break;
                        }
@@ -270,8 +270,6 @@ Editor::session_going_away ()
        group_model->clear ();
 
        edit_cursor_clock.set_session (0);
-       selection_start_clock.set_session (0);
-       selection_end_clock.set_session (0);
        zoom_range_clock.set_session (0);
        nudge_clock.set_session (0);
 
index c7199984a811985d0e5ad7e8a252bf45e98bd7bb..f7abe7fdea98eca2aa1142cb5146e27e0084e6ef 100644 (file)
@@ -18,6 +18,7 @@
     $Id$
 */
 
+#include <cassert>
 #include <cstdlib>
 #include <stdint.h>
 #include <cmath>
@@ -33,7 +34,7 @@
 #include "editor.h"
 #include "time_axis_view.h"
 #include "audio_time_axis.h"
-#include "regionview.h"
+#include "audio_region_view.h"
 #include "marker.h"
 #include "streamview.h"
 #include "region_gain_line.h"
@@ -183,7 +184,7 @@ Editor::set_mouse_mode (MouseMode m, bool force)
                   show the object (region) selection.
                */
 
-               for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+               for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
                        (*i)->set_should_show_selection (true);
                }
                for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
@@ -320,8 +321,8 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
                commit = (c1 || c2);
                break;
                
-       case AudioRegionViewNameHighlight:
-       case AudioRegionViewName:
+       case RegionViewNameHighlight:
+       case RegionViewName:
                c1 = set_selected_track_from_click (press, op, true, true);
                c2 = set_selected_regionview_from_click (press, op, true);
                commit = (c1 || c2);
@@ -522,12 +523,12 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
                                        }
                                        break;
                                        
-                               case AudioRegionViewNameHighlight:
+                               case RegionViewNameHighlight:
                                        start_trim (item, event);
                                        return true;
                                        break;
                                        
-                               case AudioRegionViewName:
+                               case RegionViewName:
                                        /* rename happens on edit clicks */
                                                start_trim (clicked_regionview->get_name_highlight(), event);
                                                return true;
@@ -693,12 +694,12 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
                        
                        
                        switch (item_type) {
-                       case AudioRegionViewNameHighlight:
+                       case RegionViewNameHighlight:
                                start_trim (item, event);
                                return true;
                                break;
                                
-                       case AudioRegionViewName:
+                       case RegionViewName:
                                start_trim (clicked_regionview->get_name_highlight(), event);
                                return true;
                                break;
@@ -854,7 +855,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        edit_meter_marker (item);
                        break;
                        
-               case AudioRegionViewName:
+               case RegionViewName:
                        if (clicked_regionview->name_active()) {
                                return mouse_rename_region (item, event);
                        }
@@ -889,8 +890,8 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                                break;
                                
                        case RegionItem:
-                       case AudioRegionViewNameHighlight:
-                       case AudioRegionViewName:
+                       case RegionViewNameHighlight:
+                       case RegionViewName:
                                popup_track_context_menu (1, event->button.time, item_type, false, where);
                                break;
                                
@@ -1048,9 +1049,13 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        break;
 
                case MouseGain:
+                       // Gain only makes sense for audio regions
+                       if ( ! dynamic_cast<AudioRegionView*>(clicked_regionview))
+                               break;
+
                        switch (item_type) {
                        case RegionItem:
-                               clicked_regionview->add_gain_point_event (item, event);
+                               dynamic_cast<AudioRegionView*>(clicked_regionview)->add_gain_point_event (item, event);
                                return true;
                                break;
                                
@@ -1204,7 +1209,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                }
                break;
                
-       case AudioRegionViewNameHighlight:
+       case RegionViewNameHighlight:
                if (is_drawable() && mouse_mode == MouseObject) {
                        track_canvas.get_window()->set_cursor (*trimmer_cursor);
                }
@@ -1231,11 +1236,11 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                }
                break;
 
-       case AudioRegionViewName:
+       case RegionViewName:
                
                /* when the name is not an active item, the entire name highlight is for trimming */
 
-               if (!reinterpret_cast<AudioRegionView *> (item->get_data ("regionview"))->name_active()) {
+               if (!reinterpret_cast<RegionView *> (item->get_data ("regionview"))->name_active()) {
                        if (mouse_mode == MouseObject && is_drawable()) {
                                track_canvas.get_window()->set_cursor (*trimmer_cursor);
                        }
@@ -1340,7 +1345,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
        ControlPoint* cp;
        Marker *marker;
        Location *loc;
-       AudioRegionView* rv;
+       RegionView* rv;
        bool is_start;
 
        switch (item_type) {
@@ -1362,7 +1367,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                hide_verbose_canvas_cursor ();
                break;
                
-       case AudioRegionViewNameHighlight:
+       case RegionViewNameHighlight:
        case StartSelectionTrimItem:
        case EndSelectionTrimItem:
        case EditCursorItem:
@@ -1393,9 +1398,9 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                }
                break;
 
-       case AudioRegionViewName:
+       case RegionViewName:
                /* see enter_handler() for notes */
-               if (!reinterpret_cast<AudioRegionView *> (item->get_data ("regionview"))->name_active()) {
+               if (!reinterpret_cast<RegionView *> (item->get_data ("regionview"))->name_active()) {
                        if (is_drawable() && mouse_mode == MouseObject) {
                                track_canvas.get_window()->set_cursor (*current_canvas_cursor);
                        }
@@ -1430,7 +1435,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
 
        case FadeInHandleItem:
        case FadeOutHandleItem:
-               rv = static_cast<AudioRegionView*>(item->get_data ("regionview"));
+               rv = static_cast<RegionView*>(item->get_data ("regionview"));
                {
                        ArdourCanvas::SimpleRect *rect = dynamic_cast<ArdourCanvas::SimpleRect *> (item);
                        if (rect) {
@@ -1525,7 +1530,7 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item
        case PanAutomationControlPointItem:
        case TempoMarkerItem:
        case MeterMarkerItem:
-       case AudioRegionViewNameHighlight:
+       case RegionViewNameHighlight:
        case StartSelectionTrimItem:
        case EndSelectionTrimItem:
        case SelectionItem:
@@ -1746,7 +1751,7 @@ Editor::start_fade_in_grab (ArdourCanvas::Item* item, GdkEvent* event)
 
        AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
 
-       drag_info.pointer_frame_offset = drag_info.grab_frame - ((jack_nframes_t) arv->region.fade_in().back()->when + arv->region.position()); 
+       drag_info.pointer_frame_offset = drag_info.grab_frame - ((jack_nframes_t) arv->audio_region().fade_in().back()->when + arv->region().position());       
 }
 
 void
@@ -1767,17 +1772,17 @@ Editor::fade_in_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                snap_to (pos);
        }
        
-       if (pos < (arv->region.position() + 64)) {
+       if (pos < (arv->region().position() + 64)) {
                fade_length = 64; // this should be a minimum defined somewhere
-       } else if (pos > arv->region.last_frame()) {
-               fade_length = arv->region.length();
+       } else if (pos > arv->region().last_frame()) {
+               fade_length = arv->region().length();
        } else {
-               fade_length = pos - arv->region.position();
+               fade_length = pos - arv->region().position();
        }
        
        arv->reset_fade_in_shape_width (fade_length);
 
-       show_verbose_duration_cursor (arv->region.position(),  arv->region.position() + fade_length, 10);
+       show_verbose_duration_cursor (arv->region().position(),  arv->region().position() + fade_length, 10);
 
        drag_info.first_move = false;
 }
@@ -1802,23 +1807,23 @@ Editor::fade_in_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* even
                snap_to (pos);
        }
 
-       if (pos < (arv->region.position() + 64)) {
+       if (pos < (arv->region().position() + 64)) {
                fade_length = 64; // this should be a minimum defined somewhere
        }
-       else if (pos > arv->region.last_frame()) {
-               fade_length = arv->region.length();
+       else if (pos > arv->region().last_frame()) {
+               fade_length = arv->region().length();
        }
        else {
-               fade_length = pos - arv->region.position();
+               fade_length = pos - arv->region().position();
        }
 
        begin_reversible_command (_("change fade in length"));
-        XMLNode &before = arv->region.get_state();
+        XMLNode &before = arv->audio_region().get_state();
 
-       arv->region.set_fade_in_length (fade_length);
+       arv->audio_region().set_fade_in_length (fade_length);
 
-        XMLNode &after = arv->region.get_state();
-        session->add_command(new MementoCommand<ARDOUR::AudioRegion>(arv->region,
+        XMLNode &after = arv->audio_region().get_state();
+        session->add_command(new MementoCommand<ARDOUR::AudioRegion>(arv->audio_regio(),
                                                                      before,
                                                                      after));
        commit_reversible_command ();
@@ -1841,7 +1846,7 @@ Editor::start_fade_out_grab (ArdourCanvas::Item* item, GdkEvent* event)
 
        AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
 
-       drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region.length() - (jack_nframes_t) arv->region.fade_out().back()->when + arv->region.position()); 
+       drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region().length() - (jack_nframes_t) arv->audio_region().fade_out().back()->when + arv->region().position());     
 }
 
 void
@@ -1862,19 +1867,19 @@ Editor::fade_out_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event
                snap_to (pos);
        }
 
-       if (pos > (arv->region.last_frame() - 64)) {
+       if (pos > (arv->region().last_frame() - 64)) {
                fade_length = 64; // this should really be a minimum fade defined somewhere
        }
-       else if (pos < arv->region.position()) {
-               fade_length = arv->region.length();
+       else if (pos < arv->region().position()) {
+               fade_length = arv->region().length();
        }
        else {
-               fade_length = arv->region.last_frame() - pos;
+               fade_length = arv->region().last_frame() - pos;
        }
        
        arv->reset_fade_out_shape_width (fade_length);
 
-       show_verbose_duration_cursor (arv->region.last_frame() - fade_length, arv->region.last_frame(), 10);
+       show_verbose_duration_cursor (arv->region().last_frame() - fade_length, arv->region().last_frame(), 10);
 
        drag_info.first_move = false;
 }
@@ -1899,23 +1904,23 @@ Editor::fade_out_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* eve
                snap_to (pos);
        }
 
-       if (pos > (arv->region.last_frame() - 64)) {
+       if (pos > (arv->region().last_frame() - 64)) {
                fade_length = 64; // this should really be a minimum fade defined somewhere
        }
-       else if (pos < arv->region.position()) {
-               fade_length = arv->region.length();
+       else if (pos < arv->region().position()) {
+               fade_length = arv->region().length();
        }
        else {
-               fade_length = arv->region.last_frame() - pos;
+               fade_length = arv->region().last_frame() - pos;
        }
 
        begin_reversible_command (_("change fade out length"));
-        XMLNode &before = arv->region.get_state();
+        XMLNode &before = arv->region().get_state();
 
-       arv->region.set_fade_out_length (fade_length);
+       arv->audio_region().set_fade_out_length (fade_length);
 
-        XMLNode &after = arv->region.get_state();
-        session->add_command(new MementoCommand<ARDOUR::AudioRegion>(arv->region, before, after));
+        XMLNode &after = arv->region().get_state();
+        session->add_command(new MementoCommand<ARDOUR::AudioRegion>(arv->region(), before, after));
        commit_reversible_command ();
 
        fade_out_drag_motion_callback (item, event);
@@ -2038,7 +2043,7 @@ Editor::start_marker_grab (ArdourCanvas::Item* item, GdkEvent* event)
 
        drag_info.copied_location = new Location (*location);
        drag_info.pointer_frame_offset = drag_info.grab_frame - (is_start ? location->start() : location->end());       
-       
+
        update_marker_drag_item (location);
 
        if (location->is_mark()) {
@@ -2097,31 +2102,39 @@ Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                move_both = true;
        }
 
-       if (is_start) { // start marker
+       if (copy_location->is_mark()) {
+               /* just move it */
 
-               if (move_both) {
-                       copy_location->set_start (newframe);
-                       copy_location->set_end (newframe + f_delta);
-               } else  if (newframe < copy_location->end()) {
-                       copy_location->set_start (newframe);
-               } else { 
-                       snap_to (next, 1, true);
-                       copy_location->set_end (next);
-                       copy_location->set_start (newframe);
-               }
+               copy_location->set_start (newframe);
 
-       } else { // end marker
+       } else {
 
-               if (move_both) {
-                       copy_location->set_end (newframe);
-                       copy_location->set_start (newframe - f_delta);
-               } else if (newframe > copy_location->start()) {
-                       copy_location->set_end (newframe);
+               if (is_start) { // start-of-range marker
                        
-               } else if (newframe > 0) {
-                       snap_to (next, -1, true);
-                       copy_location->set_start (next);
-                       copy_location->set_end (newframe);
+                       if (move_both) {
+                               copy_location->set_start (newframe);
+                               copy_location->set_end (newframe + f_delta);
+                       } else  if (newframe < copy_location->end()) {
+                               copy_location->set_start (newframe);
+                       } else { 
+                               snap_to (next, 1, true);
+                               copy_location->set_end (next);
+                               copy_location->set_start (newframe);
+                       }
+                       
+               } else { // end marker
+                       
+                       if (move_both) {
+                               copy_location->set_end (newframe);
+                               copy_location->set_start (newframe - f_delta);
+                       } else if (newframe > copy_location->start()) {
+                               copy_location->set_end (newframe);
+                               
+                       } else if (newframe > 0) {
+                               snap_to (next, -1, true);
+                               copy_location->set_start (next);
+                               copy_location->set_end (newframe);
+                       }
                }
        }
 
@@ -2154,7 +2167,11 @@ Editor::marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
        Location * location = find_location_from_marker (marker, is_start);
        
        if (location) {
-               location->set (drag_info.copied_location->start(), drag_info.copied_location->end());
+               if (location->is_mark()) {
+                       location->set_start (drag_info.copied_location->start());
+               } else {
+                       location->set (drag_info.copied_location->start(), drag_info.copied_location->end());
+               }
        }
 
        XMLNode &after = session->locations()->get_state();
@@ -2553,7 +2570,8 @@ Editor::start_line_grab_from_regionview (ArdourCanvas::Item* item, GdkEvent* eve
 {
        switch (mouse_mode) {
        case MouseGain:
-               start_line_grab (clicked_regionview->get_gain_line(), event);
+               assert(dynamic_cast<AudioRegionView*>(clicked_regionview));
+               start_line_grab (dynamic_cast<AudioRegionView*>(clicked_regionview)->get_gain_line(), event);
                break;
        default:
                break;
@@ -2647,7 +2665,7 @@ Editor::line_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
 void
 Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
 {
-       if (selection->audio_regions.empty() || clicked_regionview == 0) {
+       if (selection->regions.empty() || clicked_regionview == 0) {
                return;
        }
 
@@ -2661,13 +2679,13 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
 
        double speed = 1.0;
        TimeAxisView* tvp = clicked_trackview;
-       AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+       RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
 
        if (tv && tv->is_audio_track()) {
                speed = tv->get_diskstream()->speed();
        }
        
-       drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed);
+       drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region().position() / speed);
        drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
        drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
        // we want a move threshold
@@ -2681,7 +2699,7 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
 void
 Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
 {
-       if (selection->audio_regions.empty() || clicked_regionview == 0) {
+       if (selection->regions.empty() || clicked_regionview == 0) {
                return;
        }
 
@@ -2692,7 +2710,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
        start_grab(event);
 
        TimeAxisView* tv = &clicked_regionview->get_time_axis_view();
-       AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(tv);
+       RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(tv);
        double speed = 1.0;
 
        if (atv && atv->is_audio_track()) {
@@ -2700,7 +2718,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
        }
        
        drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
-       drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed);
+       drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region().position() / speed);
        drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
        // we want a move threshold
        drag_info.want_move_threshold = true;
@@ -2711,7 +2729,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
 void
 Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event)
 {
-       if (selection->audio_regions.empty() || clicked_regionview == 0) {
+       if (selection->regions.empty() || clicked_regionview == 0) {
                return;
        }
 
@@ -2725,13 +2743,13 @@ Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event)
 
        double speed = 1.0;
        TimeAxisView* tvp = clicked_trackview;
-       AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+       RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
 
        if (tv && tv->is_audio_track()) {
                speed = tv->get_diskstream()->speed();
        }
        
-       drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed);
+       drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region().position() / speed);
        drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
        drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
        // we want a move threshold
@@ -2746,7 +2764,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 {
        double x_delta;
        double y_delta = 0;
-       AudioRegionView *rv = reinterpret_cast<AudioRegionView*> (drag_info.data); 
+       RegionView* rv = reinterpret_cast<RegionView*> (drag_info.data); 
        jack_nframes_t pending_region_position = 0;
        int32_t pointer_y_span = 0, canvas_pointer_y_span = 0, original_pointer_order;
        int32_t visible_y_high = 0, visible_y_low = 512;  //high meaning higher numbered.. not the height on the screen
@@ -2766,18 +2784,18 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                
                /* duplicate the region(s) */
                
-               vector<AudioRegionView*> new_regionviews;
+               vector<RegionView*> new_regionviews;
                
                set<Playlist*> affected_playlists;
                pair<set<Playlist*>::iterator,bool> insert_result;
                
-               for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
-                       AudioRegionView* rv;
+               for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
+                       RegionView* rv;
                        
                        rv = (*i);
                        
-                       Playlist* to_playlist = rv->region.playlist();
-                       AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&rv->get_time_axis_view());
+                       Playlist* to_playlist = rv->region().playlist();
+                       RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(&rv->get_time_axis_view());
                        
                        insert_result = affected_playlists.insert (to_playlist);
                        if (insert_result.second) {
@@ -2786,18 +2804,21 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        
                        latest_regionview = 0;
                        
-                       sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
-                       
-                       /* create a new region with the same name.
-                        */
+                       sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
                        
-                       AudioRegion* newregion = new AudioRegion (rv->region);
+                       /* create a new region with the same name. */
                        
+                       // FIXME: ew.  need a (virtual) Region::duplicate() or something?
+                       Region* newregion = NULL;
+                       if (dynamic_cast<AudioRegion*>(&rv->region()))
+                               newregion = new AudioRegion (dynamic_cast<AudioRegion&>(rv->region()));
+                       assert(newregion);
+
                        /* if the original region was locked, we don't care */
                        
                        newregion->set_locked (false);
                        
-                       to_playlist->add_region (*newregion, (jack_nframes_t) (rv->region.position() * atv->get_diskstream()->speed()));
+                       to_playlist->add_region (*newregion, (jack_nframes_t) (rv->region().position() * atv->get_diskstream()->speed()));
                        
                        c.disconnect ();
                        
@@ -2909,16 +2930,15 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        }
                }
 
-               for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
-                       AudioRegionView* rv2;
-                       rv2 = (*i);
+               for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
+                       RegionView* rv2 = (*i);
                        double ix1, ix2, iy1, iy2;
                        int32_t n = 0;
 
                        rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
                        rv2->get_canvas_group()->i2w (ix1, iy1);
                        TimeAxisView* tvp2 = trackview_by_y_position (iy1);
-                       AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2);
+                       RouteTimeAxisView* atv2 = dynamic_cast<RouteTimeAxisView*>(tvp2);
 
                        if (atv2->order != original_pointer_order) {    
                                /* this isn't the pointer track */      
@@ -3013,8 +3033,8 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
            
                        pending_region_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
            
-                       sync_offset = rv->region.sync_offset (sync_dir);
-                       sync_frame = rv->region.adjust_to_sync (pending_region_position);
+                       sync_offset = rv->region().sync_offset (sync_dir);
+                       sync_frame = rv->region().adjust_to_sync (pending_region_position);
 
                        /* we snap if the snap modifier is not enabled.
                         */
@@ -3033,7 +3053,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        pending_region_position = 0;
                }
          
-               if (pending_region_position > max_frames - rv->region.length()) {
+               if (pending_region_position > max_frames - rv->region().length()) {
                        pending_region_position = drag_info.last_frame_position;
                }
          
@@ -3075,14 +3095,11 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
        } 
 
        if (x_delta < 0) {
-               for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
+               for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
 
-                       AudioRegionView* rv2;
-                       rv2 = (*i);
+                       RegionView* rv2 = (*i);
 
-                       /* if any regionview is at zero, we need to know so we can 
-                          stop further leftward motion.
-                       */
+                       // If any regionview is at zero, we need to know so we can stop further leftward motion.
                        
                        double ix1, ix2, iy1, iy2;
                        rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
@@ -3100,12 +3117,11 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
        ************************************************************/
 
        pair<set<Playlist*>::iterator,bool> insert_result;
-       const list<AudioRegionView*>& layered_regions = selection->audio_regions.by_layer();
+       const list<RegionView*>& layered_regions = selection->regions.by_layer();
 
-       for (list<AudioRegionView*>::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) {
+       for (list<RegionView*>::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) {
            
-               AudioRegionView* rv;
-               rv = (*i);
+               RegionView* rv = (*i);
                double ix1, ix2, iy1, iy2;
                int32_t temp_pointer_y_span = pointer_y_span;
 
@@ -3186,8 +3202,8 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        if (-x_delta > ix1) {
                                x_delta = -ix1;
                        }
-               } else if ((x_delta > 0) &&(rv->region.last_frame() > max_frames - x_delta)) {
-                       x_delta = max_frames - rv->region.last_frame();
+               } else if ((x_delta > 0) &&(rv->region().last_frame() > max_frames - x_delta)) {
+                       x_delta = max_frames - rv->region().last_frame();
                }
                        
                if (drag_info.first_move) {
@@ -3212,7 +3228,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 
                        AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&rv->get_time_axis_view());
                        if (atv && atv->is_audio_track()) {
-                               AudioPlaylist* pl = atv->get_diskstream()->playlist();
+                               AudioPlaylist* pl = dynamic_cast<AudioPlaylist*>(atv->get_diskstream()->playlist());
                                if (pl) {
                                        /* only freeze and capture state once */
 
@@ -3248,11 +3264,11 @@ void
 Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
 {
        jack_nframes_t where;
-       AudioRegionView* rv = reinterpret_cast<AudioRegionView *> (drag_info.data);
+       RegionView* rv = reinterpret_cast<RegionView *> (drag_info.data);
        pair<set<Playlist*>::iterator,bool> insert_result;
        bool nocommit = true;
        double speed;
-       AudioTimeAxisView* atv;
+       RouteTimeAxisView* atv;
        bool regionview_y_movement;
        bool regionview_x_movement;
 
@@ -3286,7 +3302,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                speed = atv->get_diskstream()->speed();
        }
        
-       regionview_x_movement = (drag_info.last_frame_position != (jack_nframes_t) (rv->region.position()/speed));
+       regionview_x_movement = (drag_info.last_frame_position != (jack_nframes_t) (rv->region().position()/speed));
        regionview_y_movement = (drag_info.last_trackview != &rv->get_time_axis_view());
 
        //printf ("last_frame: %s position is %lu  %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed); 
@@ -3296,13 +3312,13 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
                /* motion between tracks */
 
-               list<AudioRegionView*> new_selection;
+               list<RegionView*> new_selection;
        
                /* moved to a different audio track. */
 
-               for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ) {
+               for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) {
            
-                       AudioRegionView* rv2 = (*i);                
+                       RegionView* rv2 = (*i);             
            
                        /* the region that used to be in the old playlist is not
                           moved to the new one - we make a copy of it. as a result,
@@ -3319,7 +3335,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
                /* first, freeze the target tracks */
 
-               for (list<AudioRegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) {
+               for (list<RegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) {
 
                        Playlist* from_playlist;
                        Playlist* to_playlist;
@@ -3331,7 +3347,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                        TimeAxisView* tvp2 = trackview_by_y_position (iy1);
                        AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2);
            
-                       from_playlist = (*i)->region.playlist();
+                       from_playlist = (*i)->region().playlist();
                        to_playlist = atv2->playlist();
 
                        /* the from_playlist was frozen in the "first_move" case 
@@ -3354,7 +3370,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
                /* now do it again with the actual operations */
 
-               for (list<AudioRegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) {
+               for (list<RegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) {
 
                        Playlist* from_playlist;
                        Playlist* to_playlist;
@@ -3366,17 +3382,17 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                        TimeAxisView* tvp2 = trackview_by_y_position (iy1);
                        AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2);
            
-                       from_playlist = (*i)->region.playlist();
+                       from_playlist = (*i)->region().playlist();
                        to_playlist = atv2->playlist();
 
                        latest_regionview = 0;
            
                        where = (jack_nframes_t) (unit_to_frame (ix1) * speed);
-                       Region* new_region = createRegion ((*i)->region);
+                       Region* new_region = createRegion ((*i)->region());
 
-                       from_playlist->remove_region (&((*i)->region));
+                       from_playlist->remove_region (&((*i)->region()));
          
-                       sigc::connection c = atv2->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
+                       sigc::connection c = atv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
                        to_playlist->add_region (*new_region, where);
                        c.disconnect ();
                        
@@ -3389,11 +3405,11 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
                /* motion within a single track */
                
-               for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
+               for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
 
                        rv = (*i);
 
-                       if (rv->region.locked()) {
+                       if (rv->region().locked()) {
                                continue;
                        }
                        
@@ -3415,14 +3431,14 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                                
                        } else {
                                
-                               where = rv->region.position();
+                               where = rv->region().position();
                        }
 
                        rv->get_time_axis_view().reveal_dependent_views (*rv);
 
                        /* no need to add an undo here, we did that when we added this playlist to motion_frozen playlists */
                        
-                       rv->region.set_position (where, (void *) this);
+                       rv->region().set_position (where, (void *) this);
                }
        }
 
@@ -3456,15 +3472,15 @@ Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event)
 
                if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
 
-                       align_region (rv.region, SyncPoint, (jack_nframes_t) (edit_cursor->current_frame * speed));
+                       align_region (rv.region(), SyncPoint, (jack_nframes_t) (edit_cursor->current_frame * speed));
 
                } else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
 
-                       align_region (rv.region, End, (jack_nframes_t) (edit_cursor->current_frame * speed));
+                       align_region (rv.region(), End, (jack_nframes_t) (edit_cursor->current_frame * speed));
 
                } else {
 
-                       align_region (rv.region, Start, (jack_nframes_t) (edit_cursor->current_frame * speed));
+                       align_region (rv.region(), Start, (jack_nframes_t) (edit_cursor->current_frame * speed));
                }
        }
 }
@@ -3581,7 +3597,7 @@ Editor::show_verbose_duration_cursor (jack_nframes_t start, jack_nframes_t end,
 }
 
 void
-Editor::collect_new_region_view (AudioRegionView* rv)
+Editor::collect_new_region_view (RegionView* rv)
 {
        latest_regionview = rv;
 }
@@ -3614,7 +3630,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
        */
        
        latest_regionview = 0;
-       sigc::connection c = clicked_audio_trackview->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
+       sigc::connection c = clicked_audio_trackview->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
        
        /* A selection grab currently creates two undo/redo operations, one for 
           creating the new region and another for moving it.
@@ -3650,7 +3666,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
        start_grab (event);
        
        drag_info.last_trackview = clicked_trackview;
-       drag_info.last_frame_position = latest_regionview->region.position();
+       drag_info.last_frame_position = latest_regionview->region().position();
        drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
        
        show_verbose_time_cursor (drag_info.last_frame_position, 10);
@@ -3891,9 +3907,9 @@ Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event)
                speed = tv->get_diskstream()->speed();
        }
        
-       jack_nframes_t region_start = (jack_nframes_t) (clicked_regionview->region.position() / speed);
-       jack_nframes_t region_end = (jack_nframes_t) (clicked_regionview->region.last_frame() / speed);
-       jack_nframes_t region_length = (jack_nframes_t) (clicked_regionview->region.length() / speed);
+       jack_nframes_t region_start = (jack_nframes_t) (clicked_regionview->region().position() / speed);
+       jack_nframes_t region_end = (jack_nframes_t) (clicked_regionview->region().last_frame() / speed);
+       jack_nframes_t region_length = (jack_nframes_t) (clicked_regionview->region().length() / speed);
 
        motion_frozen_playlists.clear();
        
@@ -3933,7 +3949,7 @@ Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event)
 void
 Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 {
-       AudioRegionView* rv = clicked_regionview;
+       RegionView* rv = clicked_regionview;
        jack_nframes_t frame_delta = 0;
        bool left_direction;
        bool obey_snap = !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier());
@@ -3945,7 +3961,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 
        double speed = 1.0;
        TimeAxisView* tvp = clicked_trackview;
-       AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+       RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
        pair<set<Playlist*>::iterator,bool> insert_result;
 
        if (tv && tv->is_audio_track()) {
@@ -3984,11 +4000,14 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 
                begin_reversible_command (trim_type);
 
-               for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
-                       (*i)->region.freeze ();
-                       (*i)->temporarily_hide_envelope ();
+               for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
+                       (*i)->region().freeze ();
+               
+                       AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+                       if (arv)
+                               arv->temporarily_hide_envelope ();
 
-                       Playlist * pl = (*i)->region.playlist();
+                       Playlist * pl = (*i)->region().playlist();
                        insert_result = motion_frozen_playlists.insert (pl);
                        if (insert_result.second) {
                                 session->add_command(new MementoUndoCommand<Playlist>(*pl, pl->get_state()));
@@ -4004,20 +4023,20 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 
        switch (trim_op) {              
        case StartTrim:
-               if ((left_direction == false) && (drag_info.current_pointer_frame <= rv->region.first_frame()/speed)) {
+               if ((left_direction == false) && (drag_info.current_pointer_frame <= rv->region().first_frame()/speed)) {
                        break;
                 } else {
-                       for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
+                       for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
                                single_start_trim (**i, frame_delta, left_direction, obey_snap);
                        }
                        break;
                }
                
        case EndTrim:
-               if ((left_direction == true) && (drag_info.current_pointer_frame > (jack_nframes_t) (rv->region.last_frame()/speed))) {
+               if ((left_direction == true) && (drag_info.current_pointer_frame > (jack_nframes_t) (rv->region().last_frame()/speed))) {
                        break;
                } else {
-                       for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
+                       for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
                                single_end_trim (**i, frame_delta, left_direction, obey_snap);
                        }
                        break;
@@ -4031,8 +4050,8 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                                swap_direction = true;
                        }
                        
-                       for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin();
-                            i != selection->audio_regions.by_layer().end(); ++i)
+                       for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin();
+                            i != selection->regions.by_layer().end(); ++i)
                        {
                                single_contents_trim (**i, frame_delta, left_direction, swap_direction, obey_snap);
                        }
@@ -4042,10 +4061,10 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 
        switch (trim_op) {
        case StartTrim:
-               show_verbose_time_cursor((jack_nframes_t) (rv->region.position()/speed), 10);   
+               show_verbose_time_cursor((jack_nframes_t) (rv->region().position()/speed), 10); 
                break;
        case EndTrim:
-               show_verbose_time_cursor((jack_nframes_t) (rv->region.last_frame()/speed), 10); 
+               show_verbose_time_cursor((jack_nframes_t) (rv->region().last_frame()/speed), 10);       
                break;
        case ContentsTrim:
                show_verbose_time_cursor(drag_info.current_pointer_frame, 10);  
@@ -4057,9 +4076,9 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 }
 
 void
-Editor::single_contents_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap)
+Editor::single_contents_trim (RegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap)
 {
-       Region& region (rv.region);
+       Region& region (rv.region());
 
        if (region.locked()) {
                return;
@@ -4069,7 +4088,7 @@ Editor::single_contents_trim (AudioRegionView& rv, jack_nframes_t frame_delta, b
 
        double speed = 1.0;
        TimeAxisView* tvp = clicked_trackview;
-       AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+       RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
 
        if (tv && tv->is_audio_track()) {
                speed = tv->get_diskstream()->speed();
@@ -4097,9 +4116,9 @@ Editor::single_contents_trim (AudioRegionView& rv, jack_nframes_t frame_delta, b
 }
 
 void
-Editor::single_start_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap)
+Editor::single_start_trim (RegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap)
 {
-       Region& region (rv.region);     
+       Region& region (rv.region());   
 
        if (region.locked()) {
                return;
@@ -4131,9 +4150,9 @@ Editor::single_start_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool
 }
 
 void
-Editor::single_end_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap)
+Editor::single_end_trim (RegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap)
 {
-       Region& region (rv.region);
+       Region& region (rv.region());
 
        if (region.locked()) {
                return;
@@ -4172,8 +4191,8 @@ Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        thaw_region_after_trim (*clicked_regionview);           
                } else {
                        
-                       for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin();
-                            i != selection->audio_regions.by_layer().end(); ++i)
+                       for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin();
+                            i != selection->regions.by_layer().end(); ++i)
                        {
                                thaw_region_after_trim (**i);
                        }
@@ -4196,7 +4215,7 @@ Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
 void
 Editor::point_trim (GdkEvent* event)
 {
-       AudioRegionView* rv = clicked_regionview;
+       RegionView* rv = clicked_regionview;
        jack_nframes_t new_bound = drag_info.current_pointer_frame;
 
        if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
@@ -4211,13 +4230,13 @@ Editor::point_trim (GdkEvent* event)
 
                if (rv->get_selected()) {
 
-                       for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin();
-                            i != selection->audio_regions.by_layer().end(); ++i)
+                       for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin();
+                            i != selection->regions.by_layer().end(); ++i)
                        {
-                               if (!(*i)->region.locked()) {
+                               if (!(*i)->region().locked()) {
                                         Playlist *pl = (*i)->region.playlist();
                                         XMLNode &before = pl->get_state();
-                                       (*i)->region.trim_front (new_bound, this);      
+                                       (*i)->region().trim_front (new_bound, this);    
                                         XMLNode &after = pl->get_state();
                                         session->add_command(new MementoCommand<Playlist>(*pl, before, after));
                                }
@@ -4225,10 +4244,10 @@ Editor::point_trim (GdkEvent* event)
 
                } else {
 
-                       if (!rv->region.locked()) {
-                                Playlist *pl = rv->region.playlist();
+                       if (!rv->region().locked()) {
+                                Playlist *pl = rv->region().playlist();
                                XMLNode &before = pl->get_state();
-                               rv->region.trim_front (new_bound, this);        
+                               rv->region().trim_front (new_bound, this);      
                                 XMLNode &after = pl->get_state();
                                session->add_command(new MementoCommand<Playlist>(*pl, before, after));
                        }
@@ -4243,12 +4262,12 @@ Editor::point_trim (GdkEvent* event)
 
                if (rv->get_selected()) {
                        
-                       for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i)
+                       for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i)
                        {
-                               if (!(*i)->region.locked()) {
-                                        Playlist *pl = (*i)->region.playlist();
+                               if (!(*i)->region().locked()) {
+                                        Playlist *pl = (*i)->region().playlist();
                                        XMLNode &before = pl->get_state();
-                                       (*i)->region.trim_end (new_bound, this);
+                                       (*i)->region().trim_end (new_bound, this);
                                        XMLNode &after = pl->get_state();
                                        session->add_command(new MementoCommand<Playlist>(*pl, before, after));
                                }
@@ -4256,10 +4275,10 @@ Editor::point_trim (GdkEvent* event)
 
                } else {
 
-                       if (!rv->region.locked()) {
-                                Playlist *pl = rv->region.playlist();
+                       if (!rv->region().locked()) {
+                                Playlist *pl = rv->region().playlist();
                                XMLNode &before = pl->get_state();
-                               rv->region.trim_end (new_bound, this);
+                               rv->region().trim_end (new_bound, this);
                                 XMLNode &after = pl->get_state();
                                session->add_command (new MementoCommand<Playlist>(*pl, before, after));
                        }
@@ -4274,9 +4293,9 @@ Editor::point_trim (GdkEvent* event)
 }
 
 void
-Editor::thaw_region_after_trim (AudioRegionView& rv)
+Editor::thaw_region_after_trim (RegionView& rv)
 {
-       Region& region (rv.region);
+       Region& region (rv.region());
 
        if (region.locked()) {
                return;
@@ -4286,7 +4305,9 @@ Editor::thaw_region_after_trim (AudioRegionView& rv)
         XMLNode &after = region.playlist()->get_state();
        session->add_command (new MementoRedoCommand<Playlist>(*(region.playlist()), after));
 
-       rv.unhide_envelope ();
+       AudioRegionView* arv = dynamic_cast<AudioRegionView*>(&rv);
+       if (arv)
+               arv->unhide_envelope ();
 }
 
 void
@@ -4679,7 +4700,7 @@ Editor::end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event)
                }
                
        } else {
-               selection->clear_audio_regions();
+               selection->clear_regions();
                selection->clear_points ();
                selection->clear_lines ();
        }
@@ -4696,7 +4717,7 @@ Editor::mouse_rename_region (ArdourCanvas::Item* item, GdkEvent* event)
        ArdourPrompter prompter (false);
 
        prompter.set_prompt (_("Name for region:"));
-       prompter.set_initial_text (clicked_regionview->region.name());
+       prompter.set_initial_text (clicked_regionview->region().name());
        prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
        prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
        prompter.show_all ();
@@ -4705,7 +4726,7 @@ Editor::mouse_rename_region (ArdourCanvas::Item* item, GdkEvent* event)
         string str;
                prompter.get_result(str);
                if (str.length()) {
-               clicked_regionview->region.set_name (str);
+               clicked_regionview->region().set_name (str);
                }
                break;
        }
@@ -4727,7 +4748,7 @@ Editor::start_time_fx (ArdourCanvas::Item* item, GdkEvent* event)
 void
 Editor::time_fx_motion (ArdourCanvas::Item *item, GdkEvent* event)
 {
-       AudioRegionView* rv = clicked_regionview;
+       RegionView* rv = clicked_regionview;
 
        if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
                snap_to (drag_info.current_pointer_frame);
@@ -4737,8 +4758,8 @@ Editor::time_fx_motion (ArdourCanvas::Item *item, GdkEvent* event)
                return;
        }
 
-       if (drag_info.current_pointer_frame > rv->region.position()) {
-               rv->get_time_axis_view().show_timestretch (rv->region.position(), drag_info.current_pointer_frame);
+       if (drag_info.current_pointer_frame > rv->region().position()) {
+               rv->get_time_axis_view().show_timestretch (rv->region().position(), drag_info.current_pointer_frame);
        }
 
        drag_info.last_pointer_frame = drag_info.current_pointer_frame;
@@ -4756,21 +4777,25 @@ Editor::end_time_fx (ArdourCanvas::Item* item, GdkEvent* event)
                return;
        }
        
-       jack_nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region.position();
-       float percentage = (float) ((double) newlen - (double) clicked_regionview->region.length()) / ((double) newlen) * 100.0f;
+       jack_nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region().position();
+       float percentage = (float) ((double) newlen - (double) clicked_regionview->region().length()) / ((double) newlen) * 100.0f;
        
        begin_reversible_command (_("timestretch"));
 
-       if (run_timestretch (selection->audio_regions, percentage) == 0) {
+       if (run_timestretch (selection->regions, percentage) == 0) {
                session->commit_reversible_command ();
        }
 }
 
 void
-Editor::mouse_brush_insert_region (AudioRegionView* rv, jack_nframes_t pos)
+Editor::mouse_brush_insert_region (RegionView* rv, jack_nframes_t pos)
 {
        /* no brushing without a useful snap setting */
 
+       // FIXME
+       AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
+       assert(arv);
+
        switch (snap_mode) {
        case SnapMagnetic:
                return; /* can't work because it allows region to be placed anywhere */
@@ -4790,11 +4815,11 @@ Editor::mouse_brush_insert_region (AudioRegionView* rv, jack_nframes_t pos)
 
        /* don't brush a copy over the original */
        
-       if (pos == rv->region.position()) {
+       if (pos == rv->region().position()) {
                return;
        }
 
-       AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&rv->get_time_axis_view());
+       RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(&arv->get_time_axis_view());
 
        if (atv == 0 || !atv->is_audio_track()) {
                return;
@@ -4804,7 +4829,7 @@ Editor::mouse_brush_insert_region (AudioRegionView* rv, jack_nframes_t pos)
        double speed = atv->get_diskstream()->speed();
        
         XMLNode &before = playlist->get_state();
-       playlist->add_region (*(new AudioRegion (rv->region)), (jack_nframes_t) (pos * speed));
+       playlist->add_region (*(new AudioRegion (arv->audio_region)), (jack_nframes_t) (pos * speed));
         XMLNode &after = playlist->get_state();
        session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
        
index e9fcc028e63567f9adca52e9fe798c4b9058c5a8..d98be4f0888efdcb77a294f58f7519da4d20c2e9 100644 (file)
@@ -52,7 +52,7 @@
 #include "audio_time_axis.h"
 #include "automation_time_axis.h"
 #include "streamview.h"
-#include "regionview.h"
+#include "audio_region_view.h"
 #include "rgb_macros.h"
 #include "selection_templates.h"
 #include "selection.h"
@@ -187,29 +187,31 @@ Editor::split_region ()
 void
 Editor::split_region_at (jack_nframes_t where)
 {
-       split_regions_at (where, selection->audio_regions);
+       split_regions_at (where, selection->regions);
 }
 
 void
-Editor::split_regions_at (jack_nframes_t where, AudioRegionSelection& regions)
+Editor::split_regions_at (jack_nframes_t where, RegionSelection& regions)
 {
        begin_reversible_command (_("split"));
 
        snap_to (where);
-       for (AudioRegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
+       for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
 
-               AudioRegionSelection::iterator tmp;
+               RegionSelection::iterator tmp;
                
                tmp = a;
                ++tmp;
 
-               Playlist* pl = (*a)->region.playlist();
+               Playlist* pl = (*a)->region().playlist();
 
-               _new_regionviews_show_envelope = (*a)->envelope_visible();
+               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*a);
+               if (arv)
+                       _new_regionviews_show_envelope = arv->envelope_visible();
                
                if (pl) {
                         XMLNode &before = pl->get_state();
-                       pl->split_region ((*a)->region, where);
+                       pl->split_region ((*a)->region(), where);
                         XMLNode &after = pl->get_state();
                         session->add_command(new MementoCommand<Playlist>(*pl, before, after));
                }
@@ -232,7 +234,7 @@ Editor::remove_clicked_region ()
        
        begin_reversible_command (_("remove region"));
         XMLNode &before = playlist->get_state();
-       playlist->remove_region (&clicked_regionview->region);
+       playlist->remove_region (&clicked_regionview->region());
         XMLNode &after = playlist->get_state();
        session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
        commit_reversible_command ();
@@ -241,7 +243,7 @@ Editor::remove_clicked_region ()
 void
 Editor::destroy_clicked_region ()
 {
-       int32_t selected = selection->audio_regions.size();
+       int32_t selected = selection->regions.size();
 
        if (!session || clicked_regionview == 0 && selected == 0) {
                return;
@@ -273,29 +275,29 @@ Do you really want to destroy %1 ?"),
        if (selected > 0) {
                list<Region*> r;
 
-               for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
-                       r.push_back (&(*i)->region);
+               for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+                       r.push_back (&(*i)->region());
                }
 
                session->destroy_regions (r);
 
        } else if (clicked_regionview) {
-               session->destroy_region (&clicked_regionview->region);
+               session->destroy_region (&clicked_regionview->region());
        } 
 }
 
-AudioRegion *
+Region *
 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
 {
-       AudioRegionView* rv;
-       AudioRegion *region;
+       RegionView* rv;
+       Region *region;
        jack_nframes_t start = 0;
 
        if (selection->time.start () == selection->time.end_frame ()) {
                
                /* no current selection-> is there a selected regionview? */
 
-               if (selection->audio_regions.empty()) {
+               if (selection->regions.empty()) {
                        return 0;
                }
 
@@ -303,26 +305,26 @@ Editor::select_region_for_operation (int dir, TimeAxisView **tv)
 
        region = 0;
 
-       if (!selection->audio_regions.empty()) {
+       if (!selection->regions.empty()) {
 
-               rv = *(selection->audio_regions.begin());
+               rv = *(selection->regions.begin());
                (*tv) = &rv->get_time_axis_view();
-               region = &rv->region;
+               region = &rv->region();
 
        } else if (!selection->tracks.empty()) {
 
                (*tv) = selection->tracks.front();
 
-               AudioTimeAxisView* atv;
+               RouteTimeAxisView* rtv;
 
-               if ((atv = dynamic_cast<AudioTimeAxisView*> (*tv)) != 0) {
+               if ((rtv = dynamic_cast<RouteTimeAxisView*> (*tv)) != 0) {
                        Playlist *pl;
                        
-                       if ((pl = atv->playlist()) == 0) {
+                       if ((pl = rtv->playlist()) == 0) {
                                return 0;
                        }
                        
-                       region = dynamic_cast<AudioRegion*> (pl->top_region_at (start));
+                       region = pl->top_region_at (start);
                }
        } 
        
@@ -394,12 +396,12 @@ Editor::nudge_forward (bool next)
 
        if (!session) return;
        
-       if (!selection->audio_regions.empty()) {
+       if (!selection->regions.empty()) {
 
                begin_reversible_command (_("nudge forward"));
 
-               for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
-                       AudioRegion& r ((*i)->region);
+               for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+                       Region& r ((*i)->region());
                        
                        distance = get_nudge_distance (r.position(), next_distance);
 
@@ -429,12 +431,12 @@ Editor::nudge_backward (bool next)
 
        if (!session) return;
        
-       if (!selection->audio_regions.empty()) {
+       if (!selection->regions.empty()) {
 
                begin_reversible_command (_("nudge forward"));
 
-               for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
-                       AudioRegion& r ((*i)->region);
+               for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+                       Region& r ((*i)->region());
 
                        distance = get_nudge_distance (r.position(), next_distance);
                        
@@ -474,14 +476,14 @@ Editor::nudge_forward_capture_offset ()
 
        if (!session) return;
        
-       if (!selection->audio_regions.empty()) {
+       if (!selection->regions.empty()) {
 
                begin_reversible_command (_("nudge forward"));
 
                distance = session->worst_output_latency();
 
-               for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
-                       AudioRegion& r ((*i)->region);
+               for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+                       Region& r ((*i)->region());
                        
                        XMLNode &before = r.playlist()->get_state();
                        r.set_position (r.position() + distance, this);
@@ -501,14 +503,14 @@ Editor::nudge_backward_capture_offset ()
 
        if (!session) return;
        
-       if (!selection->audio_regions.empty()) {
+       if (!selection->regions.empty()) {
 
                begin_reversible_command (_("nudge forward"));
 
                distance = session->worst_output_latency();
 
-               for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
-                       AudioRegion& r ((*i)->region);
+               for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+                       Region& r ((*i)->region());
 
                         XMLNode &before = r.playlist()->get_state();
                        
@@ -789,8 +791,8 @@ Editor::cursor_to_selection_start (Cursor *cursor)
        jack_nframes_t pos = 0;
        switch (mouse_mode) {
        case MouseObject:
-               if (!selection->audio_regions.empty()) {
-                       pos = selection->audio_regions.start();
+               if (!selection->regions.empty()) {
+                       pos = selection->regions.start();
                }
                break;
 
@@ -818,8 +820,8 @@ Editor::cursor_to_selection_end (Cursor *cursor)
 
        switch (mouse_mode) {
        case MouseObject:
-               if (!selection->audio_regions.empty()) {
-                       pos = selection->audio_regions.end_frame();
+               if (!selection->regions.empty()) {
+                       pos = selection->regions.end_frame();
                }
                break;
 
@@ -1319,12 +1321,12 @@ Editor::add_location_from_playhead_cursor ()
 void
 Editor::add_location_from_audio_region ()
 {
-       if (selection->audio_regions.empty()) {
+       if (selection->regions.empty()) {
                return;
        }
 
-       AudioRegionView* rv = *(selection->audio_regions.begin());
-       Region& region = rv->region;
+       RegionView* rv = *(selection->regions.begin());
+       Region& region = rv->region();
        
        Location *location = new Location (region.position(), region.last_frame(), region.name());
        session->begin_reversible_command (_("add marker"));
@@ -1452,12 +1454,12 @@ Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top,
 void
 Editor::set_selection_from_audio_region ()
 {
-       if (selection->audio_regions.empty()) {
+       if (selection->regions.empty()) {
                return;
        }
 
-       AudioRegionView* rv = *(selection->audio_regions.begin());
-       Region& region = rv->region;
+       RegionView* rv = *(selection->regions.begin());
+       Region& region = rv->region();
        
        begin_reversible_command (_("set selection from region"));
        selection->set (0, region.position(), region.last_frame());
@@ -1840,13 +1842,13 @@ Editor::insert_region_list_drag (AudioRegion& region, int x, int y)
 void
 Editor::insert_region_list_selection (float times)
 {
-       AudioTimeAxisView *tv = 0;
+       RouteTimeAxisView *tv = 0;
        Playlist *playlist;
 
        if (clicked_audio_trackview != 0) {
                tv = clicked_audio_trackview;
        } else if (!selection->tracks.empty()) {
-               if ((tv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front())) == 0) {
+               if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
                        return;
                }
        } else {
@@ -1941,23 +1943,23 @@ Editor::play_selection ()
 void
 Editor::play_selected_region ()
 {
-       if (!selection->audio_regions.empty()) {
-               AudioRegionView *rv = *(selection->audio_regions.begin());
+       if (!selection->regions.empty()) {
+               RegionView *rv = *(selection->regions.begin());
 
-               session->request_bounded_roll (rv->region.position(), rv->region.last_frame()); 
+               session->request_bounded_roll (rv->region().position(), rv->region().last_frame());     
        }
 }
 
 void
 Editor::loop_selected_region ()
 {
-       if (!selection->audio_regions.empty()) {
-               AudioRegionView *rv = *(selection->audio_regions.begin());
+       if (!selection->regions.empty()) {
+               RegionView *rv = *(selection->regions.begin());
                Location* tll;
 
                if ((tll = transport_loop_location()) != 0)  {
 
-                       tll->set (rv->region.position(), rv->region.last_frame());
+                       tll->set (rv->region().position(), rv->region().last_frame());
                        
                        // enable looping, reposition and start rolling
 
@@ -2000,10 +2002,10 @@ void
 Editor::toggle_region_mute ()
 {
        if (clicked_regionview) {
-               clicked_regionview->region.set_muted (!clicked_regionview->region.muted());
-       } else if (!selection->audio_regions.empty()) {
-               bool yn = ! (*selection->audio_regions.begin())->region.muted();
-               selection->foreach_audio_region (&AudioRegion::set_muted, yn);
+               clicked_regionview->region().set_muted (!clicked_regionview->region().muted());
+       } else if (!selection->regions.empty()) {
+               bool yn = ! (*selection->regions.begin())->region().muted();
+               selection->foreach_region (&Region::set_muted, yn);
        }
 }
 
@@ -2011,35 +2013,35 @@ void
 Editor::toggle_region_opaque ()
 {
        if (clicked_regionview) {
-               clicked_regionview->region.set_opaque (!clicked_regionview->region.opaque());
-       } else if (!selection->audio_regions.empty()) {
-               bool yn = ! (*selection->audio_regions.begin())->region.opaque();
-               selection->foreach_audio_region (&Region::set_opaque, yn);
+               clicked_regionview->region().set_opaque (!clicked_regionview->region().opaque());
+       } else if (!selection->regions.empty()) {
+               bool yn = ! (*selection->regions.begin())->region().opaque();
+               selection->foreach_region (&Region::set_opaque, yn);
        }
 }
 
 void
 Editor::raise_region ()
 {
-       selection->foreach_audio_region (&Region::raise);
+       selection->foreach_region (&Region::raise);
 }
 
 void
 Editor::raise_region_to_top ()
 {
-       selection->foreach_audio_region (&Region::raise_to_top);
+       selection->foreach_region (&Region::raise_to_top);
 }
 
 void
 Editor::lower_region ()
 {
-       selection->foreach_audio_region (&Region::lower);
+       selection->foreach_region (&Region::lower);
 }
 
 void
 Editor::lower_region_to_bottom ()
 {
-       selection->foreach_audio_region (&Region::lower_to_bottom);
+       selection->foreach_region (&Region::lower_to_bottom);
 }
 
 void
@@ -2060,7 +2062,7 @@ Editor::rename_region ()
        Button ok_button (_("OK"));
        Button cancel_button (_("Cancel"));
 
-       if (selection->audio_regions.empty()) {
+       if (selection->regions.empty()) {
                return;
        }
 
@@ -2091,7 +2093,7 @@ Editor::rename_region ()
        Main::run ();
 
        if (region_renamed) {
-               (*selection->audio_regions.begin())->region.set_name (entry.get_text());
+               (*selection->regions.begin())->region().set_name (entry.get_text());
                redisplay_regions ();
        }
 }
@@ -2105,7 +2107,7 @@ Editor::rename_region_finished (bool status)
 }
 
 void
-Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route)
+Editor::audition_playlist_region_via_route (Region& region, Route& route)
 {
        if (session->is_auditioning()) {
                session->cancel_audition ();
@@ -2126,14 +2128,14 @@ Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route)
 void
 Editor::audition_selected_region ()
 {
-       if (!selection->audio_regions.empty()) {
-               AudioRegionView* rv = *(selection->audio_regions.begin());
-               session->audition_region (rv->region);
+       if (!selection->regions.empty()) {
+               RegionView* rv = *(selection->regions.begin());
+               session->audition_region (rv->region());
        }
 }
 
 void
-Editor::audition_playlist_region_standalone (AudioRegion& region)
+Editor::audition_playlist_region_standalone (Region& region)
 {
        session->audition_region (region);
 }
@@ -2183,7 +2185,6 @@ Editor::region_from_selection ()
        jack_nframes_t selection_cnt = end - start + 1;
        
        for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
-
                AudioRegion *region;
                AudioRegion *current;
                Region* current_r;
@@ -2200,7 +2201,9 @@ Editor::region_from_selection ()
                        continue;
                }
 
-               if ((current = dynamic_cast<AudioRegion*> (current_r)) != 0) {
+               current = dynamic_cast<AudioRegion*> (current_r);
+               // FIXME: audio only
+               if (current != 0) {
                        internal_start = start - current->position();
                        session->region_name (new_name, current->name(), true);
                        region = new AudioRegion (*current, internal_start, selection_cnt, new_name);
@@ -2250,11 +2253,13 @@ Editor::split_multichannel_region ()
 {
        vector<AudioRegion*> v;
 
-       if (!clicked_regionview || clicked_regionview->region.n_channels() < 2) {
+       AudioRegionView* clicked_arv = dynamic_cast<AudioRegionView*>(clicked_regionview);
+       
+       if (!clicked_arv || clicked_arv->audio_region().n_channels() < 2) {
                return;
        }
 
-       clicked_regionview->region.separate_by_channel (*session, v);
+       clicked_arv->audio_region().separate_by_channel (*session, v);
 
        /* nothing else to do, really */
 }
@@ -2440,7 +2445,7 @@ Editor::region_fill_track ()
 {
        jack_nframes_t end;
 
-       if (!session || selection->audio_regions.empty()) {
+       if (!session || selection->regions.empty()) {
                return;
        }
 
@@ -2448,9 +2453,15 @@ Editor::region_fill_track ()
 
        begin_reversible_command (_("region fill"));
 
-       for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+
+               Region& region ((*i)->region());
+               
+               // FIXME
+               AudioRegion* const ar = dynamic_cast<AudioRegion*>(&region);
+               if (!ar)
+                       continue;
 
-               AudioRegion& region ((*i)->region);
                Playlist* pl = region.playlist();
 
                if (end <= region.last_frame()) {
@@ -2464,7 +2475,7 @@ Editor::region_fill_track ()
                }
 
                 XMLNode &before = pl->get_state();
-               pl->add_region (*(new AudioRegion (region)), region.last_frame(), times);
+               pl->add_region (*(new AudioRegion (*ar)), ar->last_frame(), times);
                session->add_command (new MementoCommand<Playlist>(*pl, before, pl->get_state()));
        }
 
@@ -2544,12 +2555,12 @@ Editor::set_region_sync_from_edit_cursor ()
                return;
        }
 
-       if (!clicked_regionview->region.covers (edit_cursor->current_frame)) {
+       if (!clicked_regionview->region().covers (edit_cursor->current_frame)) {
                error << _("Place the edit cursor at the desired sync point") << endmsg;
                return;
        }
 
-       Region& region (clicked_regionview->region);
+       Region& region (clicked_regionview->region());
        begin_reversible_command (_("set sync from edit cursor"));
         XMLNode &before = region.playlist()->get_state();
        region.set_sync_position (edit_cursor->current_frame);
@@ -2562,7 +2573,7 @@ void
 Editor::remove_region_sync ()
 {
        if (clicked_regionview) {
-               Region& region (clicked_regionview->region);
+               Region& region (clicked_regionview->region());
                begin_reversible_command (_("remove sync"));
                 XMLNode &before = region.playlist()->get_state();
                region.clear_sync_position ();
@@ -2575,15 +2586,15 @@ Editor::remove_region_sync ()
 void
 Editor::naturalize ()
 {
-       if (selection->audio_regions.empty()) {
+       if (selection->regions.empty()) {
                return;
        }
        begin_reversible_command (_("naturalize"));
-       for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
-                XMLNode &before = (*i)->region.get_state();
-               (*i)->region.move_to_natural_position (this);
-                XMLNode &after = (*i)->region.get_state();
-               session->add_command (new MementoCommand<AudioRegion>((*i)->region, before, after));
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+                XMLNode &before = (*i)->region().get_state();
+               (*i)->region().move_to_natural_position (this);
+                XMLNode &after = (*i)->region().get_state();
+               session->add_command (new MementoCommand<AudioRegion>((*i)->region(), before, after));
        }
        commit_reversible_command ();
 }
@@ -2602,14 +2613,14 @@ Editor::align_relative (RegionPoint what)
 
 struct RegionSortByTime {
     bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
-           return a->region.position() < b->region.position();
+           return a->region().position() < b->region().position();
     }
 };
 
 void
 Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
 {
-       if (selection->audio_regions.empty()) {
+       if (selection->regions.empty()) {
                return;
        }
 
@@ -2617,9 +2628,9 @@ Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
        jack_nframes_t pos = 0;
        int dir;
 
-       list<AudioRegionView*> sorted;
-       selection->audio_regions.by_position (sorted);
-       Region& r ((*sorted.begin())->region);
+       list<RegionView*> sorted;
+       selection->regions.by_position (sorted);
+       Region& r ((*sorted.begin())->region());
 
        switch (point) {
        case Start:
@@ -2645,9 +2656,9 @@ Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
 
        begin_reversible_command (_("align selection (relative)"));
 
-       for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
 
-               Region& region ((*i)->region);
+               Region& region ((*i)->region());
 
                 XMLNode &before = region.playlist()->get_state();
                
@@ -2668,14 +2679,14 @@ Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
 void
 Editor::align_selection (RegionPoint point, jack_nframes_t position)
 {
-       if (selection->audio_regions.empty()) {
+       if (selection->regions.empty()) {
                return;
        }
 
        begin_reversible_command (_("align selection"));
 
-       for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
-               align_region_internal ((*i)->region, point, position);
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+               align_region_internal ((*i)->region(), point, position);
        }
 
        commit_reversible_command ();
@@ -2721,7 +2732,7 @@ Editor::trim_region_to_edit_cursor ()
                return;
        }
 
-       Region& region (clicked_regionview->region);
+       Region& region (clicked_regionview->region());
 
        float speed = 1.0f;
        AudioTimeAxisView *atav;
@@ -2747,7 +2758,7 @@ Editor::trim_region_from_edit_cursor ()
                return;
        }
 
-       Region& region (clicked_regionview->region);
+       Region& region (clicked_regionview->region());
 
        float speed = 1.0f;
        AudioTimeAxisView *atav;
@@ -2920,16 +2931,16 @@ Editor::cut_copy (CutCopyOp op)
 
        switch (current_mouse_mode()) {
        case MouseObject: 
-               if (!selection->audio_regions.empty() || !selection->points.empty()) {
+               if (!selection->regions.empty() || !selection->points.empty()) {
 
                        begin_reversible_command (opname + _(" objects"));
 
-                       if (!selection->audio_regions.empty()) {
+                       if (!selection->regions.empty()) {
                                
                                cut_copy_regions (op);
                                
                                if (op == Cut) {
-                                       selection->clear_audio_regions ();
+                                       selection->clear_regions ();
                                }
                        }
 
@@ -2986,11 +2997,11 @@ Editor::cut_copy_regions (CutCopyOp op)
        set<Playlist*> freezelist;
        pair<set<Playlist*>::iterator,bool> insert_result;
 
-       for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
-               first_position = min ((*x)->region.position(), first_position);
+       for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
+               first_position = min ((*x)->region().position(), first_position);
 
                if (op == Cut || op == Clear) {
-                       AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
+                       AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region().playlist());
                        if (pl) {
                                insert_result = freezelist.insert (pl);
                                if (insert_result.second) {
@@ -3001,11 +3012,11 @@ Editor::cut_copy_regions (CutCopyOp op)
                }
        }
 
-       for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ) {
+       for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
 
-               AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
+               AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region().playlist());
                AudioPlaylist* npl;
-               AudioRegionSelection::iterator tmp;
+               RegionSelection::iterator tmp;
                
                tmp = x;
                ++tmp;
@@ -3022,18 +3033,24 @@ Editor::cut_copy_regions (CutCopyOp op)
                                npl = pi->second;
                        }
 
+                       // FIXME
+                       AudioRegion* const ar = dynamic_cast<AudioRegion*>(&(*x)->region());
                        switch (op) {
                        case Cut:
-                               npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
-                               pl->remove_region (&((*x)->region));
+                               if (!ar) break;
+
+                               npl->add_region (*(new AudioRegion (*ar)), (*x)->region().position() - first_position);
+                               pl->remove_region (&((*x)->region()));
                                break;
 
                        case Copy:
-                               npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
+                               if (!ar) break;
+
+                               npl->add_region (*(new AudioRegion (*ar)), (*x)->region().position() - first_position);
                                break;
 
                        case Clear:
-                               pl->remove_region (&((*x)->region));
+                               pl->remove_region (&((*x)->region()));
                                break;
                        }
                }
@@ -3179,24 +3196,24 @@ Editor::paste_named_selection (float times)
 }
 
 void
-Editor::duplicate_some_regions (AudioRegionSelection& regions, float times)
+Editor::duplicate_some_regions (RegionSelection& regions, float times)
 {
        Playlist *playlist; 
-       AudioRegionSelection sel = regions; // clear (below) will clear the argument list
+       RegionSelection sel = regions; // clear (below) will clear the argument list
                
        begin_reversible_command (_("duplicate region"));
 
-       selection->clear_audio_regions ();
+       selection->clear_regions ();
 
-       for (AudioRegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
+       for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
 
-               Region& r ((*i)->region);
+               Region& r ((*i)->region());
 
                TimeAxisView& tv = (*i)->get_time_axis_view();
                AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
-               sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
+               sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
                
-               playlist = (*i)->region.playlist();
+               playlist = (*i)->region().playlist();
                 XMLNode &before = playlist->get_state();
                playlist->duplicate (r, r.last_frame(), times);
                session->add_command(new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
@@ -3369,7 +3386,7 @@ Editor::normalize_region ()
                return;
        }
 
-       if (selection->audio_regions.empty()) {
+       if (selection->regions.empty()) {
                return;
        }
 
@@ -3378,11 +3395,13 @@ Editor::normalize_region ()
        track_canvas.get_window()->set_cursor (*wait_cursor);
        gdk_flush ();
 
-       for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
-                XMLNode &before = (*r)->region.get_state();
-               (*r)->region.normalize_to (0.0f);
-                XMLNode &after = (*r)->region.get_state();
-               session->add_command (new MementoCommand<AudioRegion>((*r)->region, before, after));
+       for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
+               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
+               if (!arv)
+                       continue;
+               XMLNode &before = arv->region().get_state();
+               arv->audio_region().normalize_to (0.0f);
+               session->add_command (new MementoCommand<Region>(arv->region, arv->region().get_state());
        }
 
        commit_reversible_command ();
@@ -3397,17 +3416,19 @@ Editor::denormalize_region ()
                return;
        }
 
-       if (selection->audio_regions.empty()) {
+       if (selection->regions.empty()) {
                return;
        }
 
        begin_reversible_command ("denormalize");
 
-       for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
-                XMLNode &before = (*r)->region.get_state();
-               (*r)->region.set_scale_amplitude (1.0f);
-                XMLNode &after = (*r)->region.get_state();
-               session->add_command (new MementoCommand<AudioRegion>((*r)->region, before, after));
+       for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
+               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
+               if (!arv)
+                       continue;
+               XMLNode &before = arv->region().get_state();
+               arv->audio_region().set_scale_amplitude (1.0f);
+               session->add_command (new MementoCommand<Region>(arv->region, before, arv->region().get_state());
        }
 
        commit_reversible_command ();
@@ -3428,7 +3449,7 @@ Editor::reverse_region ()
 void
 Editor::apply_filter (AudioFilter& filter, string command)
 {
-       if (selection->audio_regions.empty()) {
+       if (selection->regions.empty()) {
                return;
        }
 
@@ -3437,20 +3458,22 @@ Editor::apply_filter (AudioFilter& filter, string command)
        track_canvas.get_window()->set_cursor (*wait_cursor);
        gdk_flush ();
 
-       for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ) {
+       for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) {
+               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
+               if (!arv)
+                       continue;
 
-               AudioRegion& region ((*r)->region);
-               Playlist* playlist = region.playlist();
+               Playlist* playlist = arv->region().playlist();
 
-               AudioRegionSelection::iterator tmp;
+               RegionSelection::iterator tmp;
                
                tmp = r;
                ++tmp;
 
-               if (region.apply (filter) == 0) {
+               if (arv->audio_region().apply (filter) == 0) {
 
                         XMLNode &before = playlist->get_state();
-                       playlist->replace_region (region, *(filter.results.front()), region.position());
+                       playlist->replace_region (arv->region(), *(filter.results.front()), arv->region()position());
                         XMLNode &after = playlist->get_state();
                        session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
                } else {
@@ -3461,7 +3484,7 @@ Editor::apply_filter (AudioFilter& filter, string command)
        }
 
        commit_reversible_command ();
-       selection->audio_regions.clear ();
+       selection->regions.clear ();
 
   out:
        track_canvas.get_window()->set_cursor (*current_canvas_cursor);
@@ -3470,8 +3493,8 @@ Editor::apply_filter (AudioFilter& filter, string command)
 void
 Editor::region_selection_op (void (Region::*pmf)(void))
 {
-       for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
-               ((*i)->region.*pmf)();
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+               ((*i)->region().*pmf)();
        }
 }
 
@@ -3479,16 +3502,16 @@ Editor::region_selection_op (void (Region::*pmf)(void))
 void
 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
 {
-       for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
-               ((*i)->region.*pmf)(arg);
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+               ((*i)->region().*pmf)(arg);
        }
 }
 
 void
 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
 {
-       for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
-               ((*i)->region.*pmf)(yn);
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+               ((*i)->region().*pmf)(yn);
        }
 }
 
@@ -3505,20 +3528,20 @@ Editor::external_edit_region ()
 void
 Editor::brush (jack_nframes_t pos)
 {
-       AudioRegionSelection sel;
+       RegionSelection sel;
        snap_to (pos);
 
-       if (selection->audio_regions.empty()) {
+       if (selection->regions.empty()) {
                /* XXX get selection from region list */
        } else { 
-               sel = selection->audio_regions;
+               sel = selection->regions;
        }
 
        if (sel.empty()) {
                return;
        }
 
-       for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
                mouse_brush_insert_region ((*i), pos);
        }
 }
@@ -3526,18 +3549,19 @@ Editor::brush (jack_nframes_t pos)
 void
 Editor::toggle_gain_envelope_visibility ()
 {
-       for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
-               (*i)->set_envelope_visible (!(*i)->envelope_visible());
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+               if (arv)
+                       arv->set_envelope_visible (!arv->envelope_visible());
        }
 }
 
 void
 Editor::toggle_gain_envelope_active ()
 {
-       for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
-               AudioRegion* ar = dynamic_cast<AudioRegion*>(&(*i)->region);
-               if (ar) {
-                       ar->set_envelope_active (true);
-               }
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+               if (arv)
+                       arv->audio_region().set_envelope_active (true);
        }
 }
index 2e036f500189ac98e9a2ec2afd172b2733fb4d9b..c93cf9aba290f64ec80a3cacba65f80d46737574 100644 (file)
@@ -39,21 +39,16 @@ using namespace PBD;
 using namespace Gtk;
 
 void
-Editor::handle_new_route_p (Route* route)
-{
-       ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_new_route_p), route));
-       handle_new_route (*route);
-}
-
-void
-Editor::handle_new_route (Route& route)
+Editor::handle_new_route (boost::shared_ptr<Route> route)
 {
+       ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_new_route), route));
+       
        TimeAxisView *tv;
        AudioTimeAxisView *atv;
        TreeModel::Row parent;
        TreeModel::Row row;
 
-       if (route.hidden()) {
+       if (route->hidden()) {
                return;
        }
        
@@ -75,7 +70,7 @@ Editor::handle_new_route (Route& route)
 
        }
 
-       if (dynamic_cast<AudioTrack*>(&route) != 0) {
+       if (dynamic_cast<AudioTrack*>(route.get()) != 0) {
                TreeModel::iterator iter = route_display_model->get_iter ("1");  // audio tracks 
                parent = *iter;
        } else {
@@ -89,7 +84,7 @@ Editor::handle_new_route (Route& route)
        row = *(route_display_model->append ());
 #endif
 
-       row[route_display_columns.text] = route.name();
+       row[route_display_columns.text] = route->name();
        row[route_display_columns.visible] = tv->marked_for_display();
        row[route_display_columns.tv] = tv;
        
@@ -99,14 +94,14 @@ Editor::handle_new_route (Route& route)
        
        if ((atv = dynamic_cast<AudioTimeAxisView*> (tv)) != 0) {
                /* added a new fresh one at the end */
-               if (atv->route().order_key(N_("editor")) == -1) {
-                       atv->route().set_order_key (N_("editor"), route_display_model->children().size()-1);
+               if (atv->route()->order_key(N_("editor")) == -1) {
+                       atv->route()->set_order_key (N_("editor"), route_display_model->children().size()-1);
                }
        }
 
        ignore_route_list_reorder = false;
        
-       route.gui_changed.connect (mem_fun(*this, &Editor::handle_gui_changes));
+       route->gui_changed.connect (mem_fun(*this, &Editor::handle_gui_changes));
 
        tv->GoingAway.connect (bind (mem_fun(*this, &Editor::remove_route), tv));
        
@@ -188,7 +183,7 @@ Editor::hide_track_in_display (TimeAxisView& tv)
 
        AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
 
-       if (atv && current_mixer_strip && &(atv->route()) == &(current_mixer_strip->route())) {
+       if (atv && current_mixer_strip && (atv->route() == current_mixer_strip->route())) {
                // this will hide the mixer strip
                set_selected_mixer_strip (tv);
        }
@@ -244,7 +239,7 @@ Editor::redisplay_route_list ()
                        */
                        
                        if ((at = dynamic_cast<AudioTimeAxisView*> (tv)) != 0) {
-                               at->route().set_order_key (N_("editor"), order);
+                               at->route()->set_order_key (N_("editor"), order);
                                ++order;
                        }
                }
@@ -263,6 +258,10 @@ Editor::redisplay_route_list ()
                
        }
 
+       /* make sure the cursors stay on top of every newly added track */
+
+       cursor_group->raise_to_top ();
+
        reset_scrolling_region ();
 }
 
@@ -473,7 +472,7 @@ Editor::route_list_selection_filter (const Glib::RefPtr<TreeModel>& model, const
 }
 
 struct EditorOrderRouteSorter {
-    bool operator() (Route* a, Route* b) {
+    bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
            /* use of ">" forces the correct sort order */
            return a->order_key ("editor") < b->order_key ("editor");
     }
@@ -482,17 +481,18 @@ struct EditorOrderRouteSorter {
 void
 Editor::initial_route_list_display ()
 {
-       Session::RouteList routes = session->get_routes();
+       boost::shared_ptr<Session::RouteList> routes = session->get_routes();
+       Session::RouteList r (*routes);
        EditorOrderRouteSorter sorter;
 
-       routes.sort (sorter);
+       r.sort (sorter);
        
        no_route_list_redisplay = true;
 
        route_display_model->clear ();
 
-       for (Session::RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
-               handle_new_route (**i);
+       for (Session::RouteList::iterator i = r.begin(); i != r.end(); ++i) {
+               handle_new_route (*i);
        }
 
        no_route_list_redisplay = false;
index 27fa6c9651bd9cd193ffc7e3e39c9697e0d284ee..3fe0023d07701cc326c5d769f1ef5757674ae275 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "editor.h"
 #include "audio_time_axis.h"
-#include "regionview.h"
+#include "audio_region_view.h"
 #include "region_selection.h"
 
 #include <ardour/session.h>
@@ -101,7 +101,7 @@ Editor::TimeStretchDialog::delete_timestretch_in_progress (GdkEventAny* ev)
 }
 
 int
-Editor::run_timestretch (AudioRegionSelection& regions, float fraction)
+Editor::run_timestretch (RegionSelection& regions, float fraction)
 {
        pthread_t thread;
 
@@ -158,39 +158,42 @@ Editor::run_timestretch (AudioRegionSelection& regions, float fraction)
 void
 Editor::do_timestretch (TimeStretchDialog& dialog)
 {
-       AudioTrack* at;
+       Track*    t;
        Playlist* playlist;
-       AudioRegion* new_region;
+       Region*   new_region;
 
 
-       for (AudioRegionSelection::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ) {
+       for (RegionSelection::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ) {
+               AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*i);
+               if (!arv)
+                       continue;
 
-               AudioRegion& aregion ((*i)->region);
-               TimeAxisView* tv = &(*i)->get_time_axis_view();
-               AudioTimeAxisView* atv;
-               AudioRegionSelection::iterator tmp;
+               AudioRegion& region (arv->audio_region());
+               TimeAxisView* tv = &(arv->get_time_axis_view());
+               RouteTimeAxisView* rtv;
+               RegionSelection::iterator tmp;
                
-               cerr << "stretch " << aregion.name() << endl;
+               cerr << "stretch " << region.name() << endl;
 
                tmp = i;
                ++tmp;
 
-               if ((atv = dynamic_cast<AudioTimeAxisView*> (tv)) == 0) {
+               if ((rtv = dynamic_cast<RouteTimeAxisView*> (tv)) == 0) {
                        i = tmp;
                        continue;
                }
 
-               if ((at = dynamic_cast<AudioTrack*> (&atv->route())) == 0) {
+               if ((t = dynamic_cast<Track*> (rtv->route().get())) == 0) {
                        i = tmp;
                        continue;
                }
        
-               if ((playlist = at->disk_stream().playlist()) == 0) {
+               if ((playlist = t->diskstream().playlist()) == 0) {
                        i = tmp;
                        continue;
                }
 
-               dialog.request.region = &aregion;
+               dialog.request.region = &region;
 
                if (!dialog.request.running) {
                        /* we were cancelled */
@@ -205,7 +208,7 @@ Editor::do_timestretch (TimeStretchDialog& dialog)
                }
 
                XMLNode &before = playlist->get_state();
-               playlist->replace_region (aregion, *new_region, aregion.position());
+               playlist->replace_region (region, *new_region, region.position());
                XMLNode &after = playlist->get_state();
                session->add_command (new MementoCommand<Playlist>(*playlist, before, after));
 
index bcf8cd85adebc19111a410e9d664b1b9262df5e6..b5a47570905830cff140c5a630d652c2be131e12 100644 (file)
@@ -1082,11 +1082,11 @@ ExportDialog::fill_lists ()
        track_list->clear();
        master_list->clear();
        
-       Session::RouteList routes = session->get_routes ();
+       boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
 
-       for (Session::RouteList::iterator ri = routes.begin(); ri != routes.end(); ++ri) {
-
-               Route* route = (*ri);
+       for (Session::RouteList::iterator ri = routes->begin(); ri != routes->end(); ++ri) {
+               
+               boost::shared_ptr<Route> route = (*ri);
                
                if (route->hidden()) {
                        continue;
index 97bf7c22b1ec4190be28c06dcb6e62903a67ea1e..1964fabbfe61ce979143ed3455f7dc8d969ccd65 100644 (file)
@@ -18,6 +18,8 @@
 
 */
 
+#include <cassert>
+
 #include <pbd/pthread_utils.h>
 #include <ardour/audioregion.h>
 
 #include "i18n.h"
 
 
-ExportRegionDialog::ExportRegionDialog (PublicEditor& editor, ARDOUR::AudioRegion* region) 
+ExportRegionDialog::ExportRegionDialog (PublicEditor& editor, ARDOUR::Region* region) 
        : ExportDialog(editor)
 {
-       audio_region = region;
-       
+       // FIXME
+       ARDOUR::AudioRegion* audio_region = dynamic_cast<ARDOUR::AudioRegion*>(region);
+       assert(audio_region);
+
        do_not_allow_track_and_master_selection();
        do_not_allow_channel_count_selection();
 }
index 00464eb5b39f86ac6aabed5d8808295d887cb268..e8afe97d6b188416ffb86f98e635f93b669843b0 100644 (file)
@@ -27,7 +27,7 @@
 class ExportRegionDialog : public ExportDialog
 {
   public:
-       ExportRegionDialog (PublicEditor&, ARDOUR::AudioRegion*);
+       ExportRegionDialog (PublicEditor&, ARDOUR::Region*);
  
        static void* _export_region_thread (void *);
        void export_region ();
index c2d81abf3ce1ab4ad045873d69d936e020667ee4..367dc54b7c11acb55234194dbd4140fdb64c6a23 100644 (file)
@@ -234,11 +234,11 @@ FFTGraph::draw_scales(Glib::RefPtr<Gdk::Window> window)
                while (_logScale[logscale_pos] < position_on_scale)
                        logscale_pos++;
                
-               int coord = v_margin + 1.0 + position_on_scale;
+               int coord = (int)(v_margin + 1.0 + position_on_scale);
                
                int SR = 44100;
 
-               int rate_at_pos = (double)(SR/2) * (double)logscale_pos / (double)_dataSize;
+               int rate_at_pos = (int)((double)(SR/2) * (double)logscale_pos / (double)_dataSize);
                
                char buf[32];
                snprintf(buf,32,"%dhz",rate_at_pos);
@@ -384,7 +384,7 @@ FFTGraph::on_size_request(Gtk::Requisition* requisition)
 }
 
 void
-FFTGraph::on_size_allocate(Gtk::Allocation alloc)
+FFTGraph::on_size_allocate(Gtk::Allocation alloc)
 {
        width = alloc.get_width();
        height = alloc.get_height();
index 80c78180a6c8a934709a2af0ff5bc0a7bd5e0509..73636b989d802d36007a36e3e522cbfdf270b04d 100644 (file)
@@ -51,7 +51,7 @@ class FFTGraph : public Gtk::DrawingArea
                bool on_expose_event (GdkEventExpose* event);
                
                void on_size_request(Gtk::Requisition* requisition);
-               void on_size_allocate(Gtk::Allocation alloc);
+               void on_size_allocate(Gtk::Allocation alloc);
                FFTResult *prepareResult(Gdk::Color color, std::string trackname);
                
        private:
index 9a55b59cb5125880aded7ff65e41db60b5cf1393..f5acef92ed64b6a8ac905d72109549e7bbb0fddf 100644 (file)
@@ -20,9 +20,9 @@
 
 #include <fft_result.h>
 #include <fft_graph.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
+#include <cstdlib>
+#include <string>
+#include <cmath>
 
 #include <iostream>
 
index 3e3d02bfc428259c3addc5da3a7f49a3c5e48bdb..c86c1390f33dd96ac7c44d86ac0c41b0b0d62c62 100644 (file)
@@ -32,7 +32,9 @@ using namespace ARDOUR;
 using namespace PBD;
 using namespace Gtk;
 
-GainAutomationTimeAxisView::GainAutomationTimeAxisView (Session& s, Route& r, PublicEditor& e, TimeAxisView& parent, ArdourCanvas::Canvas& canvas, const string & n, ARDOUR::Curve& c)
+GainAutomationTimeAxisView::GainAutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r, 
+                                                       PublicEditor& e, TimeAxisView& parent, 
+                                                       ArdourCanvas::Canvas& canvas, const string & n, ARDOUR::Curve& c)
 
        : AxisView (s),
          AutomationTimeAxisView (s, r, e, parent, canvas, n, X_("gain"), ""),
@@ -74,6 +76,6 @@ void
 GainAutomationTimeAxisView::set_automation_state (AutoState state)
 {
        if (!ignore_state_request) {
-               route.set_gain_automation_state (state);
+               route->set_gain_automation_state (state);
        }
 }
index 50f1cba3f918fb1af3afedce5a89d66fa866cc3e..dc6d5bd28ea0136df8baea7c21a01f66a38167d5 100644 (file)
@@ -13,7 +13,7 @@ class GainAutomationTimeAxisView : public AutomationTimeAxisView
 {
   public:
        GainAutomationTimeAxisView (ARDOUR::Session&,
-                                   ARDOUR::Route&,
+                                   boost::shared_ptr<ARDOUR::Route>,
                                    PublicEditor&,
                                    TimeAxisView& parent_axis,
                                    ArdourCanvas::Canvas& canvas,
index b7746c4b19773f416e7f6e6ca65eaec0311ac12a..5fa8c462bc3f08ccdd68cfe99413f97022858745 100644 (file)
@@ -79,7 +79,7 @@ GainMeter::setup_slider_pix ()
        return 0;
 }
 
-GainMeter::GainMeter (IO& io, Session& s)
+GainMeter::GainMeter (boost::shared_ptr<IO> io, Session& s)
        : _io (io),
          _session (s),
          gain_slider (0),
@@ -99,18 +99,13 @@ GainMeter::GainMeter (IO& io, Session& s)
        
        gain_slider = manage (new VSliderController (slider, rail,
                                                     &gain_adjustment,
-                                                    & _io.midi_gain_control(),
+                                                    _io->gain_control(),
                                                     false));
 
        gain_slider->signal_button_press_event().connect (mem_fun(*this, &GainMeter::start_gain_touch));
        gain_slider->signal_button_release_event().connect (mem_fun(*this, &GainMeter::end_gain_touch));
        gain_slider->set_name ("MixerGainMeter");
 
-       if (_session.midi_port()) {
-               _io.set_midi_to_gain_function (slider_position_to_gain);
-               _io.set_gain_to_midi_function (gain_to_slider_position);
-       }
-
        gain_display.set_print_func (_gain_printer, this);
 
        gain_display_box.set_spacing (2);
@@ -157,7 +152,7 @@ GainMeter::GainMeter (IO& io, Session& s)
 
        Route* r;
 
-       if ((r = dynamic_cast<Route*> (&_io)) != 0) {
+       if ((r = dynamic_cast<Route*> (_io.get())) != 0) {
                /* 
                   if we don't have a route (if we're the click), 
                   pack some route-dependent stuff.
@@ -170,13 +165,13 @@ GainMeter::GainMeter (IO& io, Session& s)
                using namespace Menu_Helpers;
        
                gain_astate_menu.items().push_back (MenuElem (_("Off"), 
-                                                     bind (mem_fun (&_io, &IO::set_gain_automation_state), (AutoState) Off)));
+                                                     bind (mem_fun (*_io, &IO::set_gain_automation_state), (AutoState) Off)));
                gain_astate_menu.items().push_back (MenuElem (_("Play"),
-                                                     bind (mem_fun (&_io, &IO::set_gain_automation_state), (AutoState) Play)));
+                                                     bind (mem_fun (*_io, &IO::set_gain_automation_state), (AutoState) Play)));
                gain_astate_menu.items().push_back (MenuElem (_("Write"),
-                                                     bind (mem_fun (&_io, &IO::set_gain_automation_state), (AutoState) Write)));
+                                                     bind (mem_fun (*_io, &IO::set_gain_automation_state), (AutoState) Write)));
                gain_astate_menu.items().push_back (MenuElem (_("Touch"),
-                                                     bind (mem_fun (&_io, &IO::set_gain_automation_state), (AutoState) Touch)));
+                                                     bind (mem_fun (*_io, &IO::set_gain_automation_state), (AutoState) Touch)));
        
                gain_astyle_menu.items().push_back (MenuElem (_("Trim")));
                gain_astyle_menu.items().push_back (MenuElem (_("Abs")));
@@ -200,7 +195,7 @@ GainMeter::GainMeter (IO& io, Session& s)
        pack_start (gain_display_box,  Gtk::PACK_SHRINK);
        pack_start (hbox,  Gtk::PACK_SHRINK);
 
-       _io.gain_changed.connect (mem_fun(*this, &GainMeter::gain_changed));
+       _io->gain_changed.connect (mem_fun(*this, &GainMeter::gain_changed));
 
        meter_metric_area.signal_expose_event().connect (mem_fun(*this, &GainMeter::meter_metrics_expose));
        gain_adjustment.signal_value_changed().connect (mem_fun(*this, &GainMeter::gain_adjusted));
@@ -328,7 +323,7 @@ GainMeter::update_meters ()
        
        for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
                if ((*i).packed) {
-                       peak = _io.peak_input_power (n);
+                       peak = _io->peak_input_power (n);
 
                        (*i).meter->set (log_meter (peak), peak);
                                                
@@ -387,14 +382,14 @@ GainMeter::hide_all_meters ()
 void
 GainMeter::setup_meters ()
 {
-       uint32_t nmeters = _io.n_outputs();
+       uint32_t nmeters = _io->n_outputs();
        guint16 width;
 
        hide_all_meters ();
 
        Route* r;
 
-       if ((r = dynamic_cast<Route*> (&_io)) != 0) {
+       if ((r = dynamic_cast<Route*> (_io.get())) != 0) {
 
                switch (r->meter_point()) {
                case MeterPreFader:
@@ -408,7 +403,7 @@ GainMeter::setup_meters ()
 
        } else {
 
-               nmeters = _io.n_outputs();
+               nmeters = _io->n_outputs();
 
        }
 
@@ -456,7 +451,7 @@ GainMeter::peak_button_release (GdkEventButton* ev)
                ResetAllPeakDisplays ();
        } else if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
                Route* r;
-               if ((r = dynamic_cast<Route*> (&_io)) != 0) {
+               if ((r = dynamic_cast<Route*> (_io.get())) != 0) {
                        ResetGroupPeakDisplays (r->mix_group());
                }
        } else {
@@ -477,7 +472,7 @@ void
 GainMeter::reset_group_peak_display (RouteGroup* group)
 {
        Route* r;
-       if ((r = dynamic_cast<Route*> (&_io)) != 0) {
+       if ((r = dynamic_cast<Route*> (_io.get())) != 0) {
                if (group == r->mix_group()) {
                        reset_peak_display ();
                }
@@ -546,14 +541,14 @@ void
 GainMeter::gain_adjusted ()
 {
        if (!ignore_toggle) {
-               _io.set_gain (slider_position_to_gain (gain_adjustment.get_value()), this);
+               _io->set_gain (slider_position_to_gain (gain_adjustment.get_value()), this);
        }
 }
 
 void
 GainMeter::effective_gain_display ()
 {
-       gfloat value = gain_to_slider_position (_io.effective_gain());
+       gfloat value = gain_to_slider_position (_io->effective_gain());
        
        if (gain_adjustment.get_value() != value) {
                ignore_toggle = true;
@@ -583,7 +578,7 @@ GainMeter::set_fader_name (const char * name)
 void
 GainMeter::update_gain_sensitive ()
 {
-       static_cast<Gtkmm2ext::SliderController*>(gain_slider)->set_sensitive (!(_io.gain_automation_state() & Play));
+       static_cast<Gtkmm2ext::SliderController*>(gain_slider)->set_sensitive (!(_io->gain_automation_state() & Play));
 }
 
 
@@ -614,7 +609,7 @@ GainMeter::meter_press(GdkEventButton* ev)
 
        wait_for_release = false;
 
-       if ((_route = dynamic_cast<Route*>(&_io)) == 0) {
+       if ((_route = dynamic_cast<Route*>(_io.get())) == 0) {
                return FALSE;
        }
 
@@ -676,7 +671,7 @@ GainMeter::meter_release(GdkEventButton* ev)
        if(!ignore_toggle){
                if (wait_for_release){
                        wait_for_release = false;
-                       set_meter_point (*(dynamic_cast<Route*>(&_io)), old_meter_point);
+                       set_meter_point (*(dynamic_cast<Route*>(_io.get())), old_meter_point);
                }
        }
        return true;
@@ -705,7 +700,7 @@ GainMeter::meter_point_clicked ()
 {
        Route* r;
 
-       if ((r = dynamic_cast<Route*> (&_io)) != 0) {
+       if ((r = dynamic_cast<Route*> (_io.get())) != 0) {
 
        }
 }
@@ -713,14 +708,14 @@ GainMeter::meter_point_clicked ()
 gint
 GainMeter::start_gain_touch (GdkEventButton* ev)
 {
-       _io.start_gain_touch ();
+       _io->start_gain_touch ();
        return FALSE;
 }
 
 gint
 GainMeter::end_gain_touch (GdkEventButton* ev)
 {
-       _io.end_gain_touch ();
+       _io->end_gain_touch ();
        return FALSE;
 }
 
@@ -824,10 +819,10 @@ GainMeter::gain_automation_style_changed ()
   // Route* _route = dynamic_cast<Route*>(&_io);
        switch (_width) {
        case Wide:
-               gain_automation_style_button.set_label (astyle_string(_io.gain_automation_curve().automation_style()));
+               gain_automation_style_button.set_label (astyle_string(_io->gain_automation_curve().automation_style()));
                break;
        case Narrow:
-               gain_automation_style_button.set_label  (short_astyle_string(_io.gain_automation_curve().automation_style()));
+               gain_automation_style_button.set_label  (short_astyle_string(_io->gain_automation_curve().automation_style()));
                break;
        }
 }
@@ -842,14 +837,14 @@ GainMeter::gain_automation_state_changed ()
 
        switch (_width) {
        case Wide:
-               gain_automation_state_button.set_label (astate_string(_io.gain_automation_curve().automation_state()));
+               gain_automation_state_button.set_label (astate_string(_io->gain_automation_curve().automation_state()));
                break;
        case Narrow:
-               gain_automation_state_button.set_label (short_astate_string(_io.gain_automation_curve().automation_state()));
+               gain_automation_state_button.set_label (short_astate_string(_io->gain_automation_curve().automation_state()));
                break;
        }
 
-       x = (_io.gain_automation_state() != Off);
+       x = (_io->gain_automation_state() != Off);
        
        if (gain_automation_state_button.get_active() != x) {
                ignore_toggle = true;
index ddf93b579f03ad512aa3db69dda746738ed65fb8..1dfc088248b200448687e7e0e907e9854b10e913 100644 (file)
@@ -34,8 +34,8 @@
 
 #include <ardour/types.h>
 
-#include <gtkmm2ext/slider_controller.h>
 #include <gtkmm2ext/click_box.h>
+#include <gtkmm2ext/slider_controller.h>
 
 #include "enums.h"
 
@@ -56,7 +56,7 @@ namespace Gtk {
 class GainMeter : public Gtk::VBox
 {
   public:
-       GainMeter (ARDOUR::IO&, ARDOUR::Session&);
+       GainMeter (boost::shared_ptr<ARDOUR::IO>, ARDOUR::Session&);
        ~GainMeter ();
 
        void update_gain_sensitive ();
@@ -75,7 +75,7 @@ class GainMeter : public Gtk::VBox
   private:
 
        friend class MixerStrip;
-       ARDOUR::IO& _io;
+       boost::shared_ptr<ARDOUR::IO> _io;
        ARDOUR::Session& _session;
 
        bool ignore_toggle;
index b0ecd05077994be991656b4713afc658cecbcb34..f754435112a090cd80fc1cfd7783ebad2f309b63 100644 (file)
@@ -52,7 +52,7 @@ using namespace ARDOUR;
 using namespace PBD;
 using namespace Gtkmm2ext;
 
-IOSelectorWindow::IOSelectorWindow (Session& sess, IO& ior, bool input, bool can_cancel)
+IOSelectorWindow::IOSelectorWindow (Session& sess, boost::shared_ptr<IO> ior, bool input, bool can_cancel)
        : ArdourDialog ("i/o selector"),
          _selector (sess, ior, input),
          ok_button (can_cancel ? _("OK"): _("Close")),
@@ -65,9 +65,9 @@ IOSelectorWindow::IOSelectorWindow (Session& sess, IO& ior, bool input, bool can
 
        string title;
        if (input) {
-               title = string_compose(_("%1 input"), ior.name());
+               title = string_compose(_("%1 input"), ior->name());
        } else {
-               title = string_compose(_("%1 output"), ior.name());
+               title = string_compose(_("%1 output"), ior->name());
        }
 
        ok_button.set_name ("IOSelectorButton");
@@ -135,7 +135,7 @@ IOSelectorWindow::on_map ()
   The IO Selector "widget"
  *************************/  
 
-IOSelector::IOSelector (Session& sess, IO& ior, bool input)
+IOSelector::IOSelector (Session& sess, boost::shared_ptr<IO> ior, bool input)
        : session (sess),
          io (ior),
          for_input (input),
@@ -184,14 +184,14 @@ IOSelector::IOSelector (Session& sess, IO& ior, bool input)
        port_button_box.pack_start (add_port_button, false, false);
 
        if (for_input) {
-               if (io.input_maximum() < 0 || io.input_maximum() > (int) io.n_inputs()) {
+               if (io->input_maximum() < 0 || io->input_maximum() > (int) io->n_inputs()) {
                        add_port_button.set_sensitive (true);
                } else {
                        add_port_button.set_sensitive (false);
                }
 
        } else {
-               if (io.output_maximum() < 0 || io.output_maximum() > (int) io.n_outputs()) {
+               if (io->output_maximum() < 0 || io->output_maximum() > (int) io->n_outputs()) {
                        add_port_button.set_sensitive (true);
                } else {
                        add_port_button.set_sensitive (false);
@@ -202,14 +202,14 @@ IOSelector::IOSelector (Session& sess, IO& ior, bool input)
        port_button_box.pack_start (remove_port_button, false, false);
 
        if (for_input) {
-               if (io.input_minimum() < 0 || io.input_minimum() < (int) io.n_inputs()) {
+               if (io->input_minimum() < 0 || io->input_minimum() < (int) io->n_inputs()) {
                        remove_port_button.set_sensitive (true);
                } else {
                        remove_port_button.set_sensitive (false);
                }
                        
        } else {
-               if (io.output_minimum() < 0 || io.output_minimum() < (int) io.n_outputs()) {
+               if (io->output_minimum() < 0 || io->output_minimum() < (int) io->n_outputs()) {
                        remove_port_button.set_sensitive (true);
                } else {
                        remove_port_button.set_sensitive (false);
@@ -241,12 +241,12 @@ IOSelector::IOSelector (Session& sess, IO& ior, bool input)
        remove_port_button.signal_clicked().connect (mem_fun(*this, &IOSelector::remove_port));
 
        if (for_input) {
-               io.input_changed.connect (mem_fun(*this, &IOSelector::ports_changed));
+               io->input_changed.connect (mem_fun(*this, &IOSelector::ports_changed));
        } else {
-               io.output_changed.connect (mem_fun(*this, &IOSelector::ports_changed));
+               io->output_changed.connect (mem_fun(*this, &IOSelector::ports_changed));
        }
 
-       io.name_changed.connect (mem_fun(*this, &IOSelector::name_changed));
+       io->name_changed.connect (mem_fun(*this, &IOSelector::name_changed));
 }
 
 IOSelector::~IOSelector ()
@@ -265,9 +265,9 @@ void
 IOSelector::clear_connections ()
 {
        if (for_input) {
-               io.disconnect_inputs (this);
+               io->disconnect_inputs (this);
        } else {
-               io.disconnect_outputs (this);
+               io->disconnect_outputs (this);
        }
 }
 
@@ -374,9 +374,9 @@ IOSelector::display_ports ()
                uint32_t limit;
 
                if (for_input) {
-                       limit = io.n_inputs();
+                       limit = io->n_inputs();
                } else {
-                       limit = io.n_outputs();
+                       limit = io->n_outputs();
                }
 
                for (slist<TreeView *>::iterator i = port_displays.begin(); i != port_displays.end(); ) {
@@ -401,9 +401,9 @@ IOSelector::display_ports ()
                        string really_short_name;
                        
                        if (for_input) {
-                               port = io.input (n);
+                               port = io->input (n);
                        } else {
-                               port = io.output (n);
+                               port = io->output (n);
                        }
                        
                        /* we know there is '/' because we put it there */
@@ -443,7 +443,7 @@ IOSelector::display_ports ()
                        
                        if (for_input) {
                                
-                               if (io.input_maximum() == 1) {
+                               if (io->input_maximum() == 1) {
                                        selected_port = port;
                                        selected_port_tview = tview;
                                } else {
@@ -454,7 +454,7 @@ IOSelector::display_ports ()
                        
                        } else {
 
-                               if (io.output_maximum() == 1) {
+                               if (io->output_maximum() == 1) {
                                        selected_port = port;
                                        selected_port_tview = tview;
                                } else {
@@ -516,12 +516,12 @@ IOSelector::port_selection_changed (GdkEventButton *ev, TreeView* treeview)
        ustring other_port_name = (*i)[port_display_columns.full_name];
        
        if (for_input) {
-               if ((status = io.connect_input (selected_port, other_port_name, this)) == 0) {
+               if ((status = io->connect_input (selected_port, other_port_name, this)) == 0) {
                        Port *p = session.engine().get_port_by_name (other_port_name);
                        p->enable_metering();
                }
        } else {
-               status = io.connect_output (selected_port, other_port_name, this);
+               status = io->connect_output (selected_port, other_port_name, this);
        }
 
        if (status == 0) {
@@ -548,7 +548,7 @@ IOSelector::add_port ()
        if (for_input) {
 
                try {
-                       io.add_input_port ("", this);
+                       io->add_input_port ("", this);
                }
 
                catch (AudioEngine::PortRegistrationFailure& err) {
@@ -556,18 +556,18 @@ IOSelector::add_port ()
                        msg.run ();
                }
 
-               if (io.input_maximum() >= 0 && io.input_maximum() <= (int) io.n_inputs()) {
+               if (io->input_maximum() >= 0 && io->input_maximum() <= (int) io->n_inputs()) {
                        add_port_button.set_sensitive (false);
                }
                
-               if (io.input_minimum() < (int) io.n_inputs()) {
+               if (io->input_minimum() < (int) io->n_inputs()) {
                        remove_port_button.set_sensitive (true);
                }
 
        } else {
 
                try {
-                       io.add_output_port ("", this);
+                       io->add_output_port ("", this);
                }
 
                catch (AudioEngine::PortRegistrationFailure& err) {
@@ -575,7 +575,7 @@ IOSelector::add_port ()
                        msg.run ();
                }
 
-               if (io.output_maximum() >= 0 && io.output_maximum() <= (int) io.n_outputs()) {
+               if (io->output_maximum() >= 0 && io->output_maximum() <= (int) io->n_outputs()) {
                        add_port_button.set_sensitive (false);
                }
        }
@@ -589,15 +589,15 @@ IOSelector::remove_port ()
        // always remove last port
        
        if (for_input) {
-               if ((nports = io.n_inputs()) > 0) {
-                       io.remove_input_port (io.input(nports-1), this);
+               if ((nports = io->n_inputs()) > 0) {
+                       io->remove_input_port (io->input(nports-1), this);
                }
-               if (io.input_minimum() == (int) io.n_inputs()) {
+               if (io->input_minimum() == (int) io->n_inputs()) {
                        remove_port_button.set_sensitive (false);
                }
        } else {
-               if ((nports = io.n_outputs()) > 0) {
-                       io.remove_output_port (io.output(nports-1), this);
+               if ((nports = io->n_outputs()) > 0) {
+                       io->remove_output_port (io->output(nports-1), this);
                }
        }
 }
@@ -606,9 +606,9 @@ gint
 IOSelector::remove_port_when_idle (Port *port)
 {
        if (for_input) {
-               io.remove_input_port (port, this);
+               io->remove_input_port (port, this);
        } else {
-               io.remove_output_port (port, this);
+               io->remove_output_port (port, this);
        }
 
        return FALSE;
@@ -651,9 +651,9 @@ IOSelector::connection_button_release (GdkEventButton *ev, TreeView *treeview)
                if (for_input) {
                        Port *p = session.engine().get_port_by_name (connected_port_name);
                        p->disable_metering();
-                       io.disconnect_input (port, connected_port_name, this);
+                       io->disconnect_input (port, connected_port_name, this);
                } else {
-                       io.disconnect_output (port, connected_port_name, this);
+                       io->disconnect_output (port, connected_port_name, this);
                }
        }
 
@@ -749,17 +749,17 @@ IOSelector::redisplay ()
        display_ports ();
 
        if (for_input) {
-               if (io.input_maximum() != 0) {
+               if (io->input_maximum() != 0) {
                        rescan ();
                }
        } else {
-               if (io.output_maximum() != 0) {
+               if (io->output_maximum() != 0) {
                        rescan();
                }
        }
 }
 
-PortInsertUI::PortInsertUI (Session& sess, PortInsert& pi)
+PortInsertUI::PortInsertUI (Session& sess, boost::shared_ptr<PortInsert> pi)
        : input_selector (sess, pi, true),
          output_selector (sess, pi, false)
 {
@@ -786,9 +786,9 @@ PortInsertUI::finished(IOSelector::Result r)
 }
 
 
-PortInsertWindow::PortInsertWindow (Session& sess, PortInsert& pi, bool can_cancel)
+PortInsertWindow::PortInsertWindow (Session& sess, boost::shared_ptr<PortInsert> pi, bool can_cancel)
        : ArdourDialog ("port insert dialog"),
-         _portinsertui(sess, pi),
+         _portinsertui (sess, pi),
          ok_button (can_cancel ? _("OK"): _("Close")),
          cancel_button (_("Cancel")),
          rescan_button (_("Rescan"))
@@ -796,7 +796,7 @@ PortInsertWindow::PortInsertWindow (Session& sess, PortInsert& pi, bool can_canc
 
        set_name ("IOSelectorWindow");
        string title = _("ardour: ");
-       title += pi.name();
+       title += pi->name();
        set_title (title);
        
        ok_button.set_name ("IOSelectorButton");
@@ -823,7 +823,7 @@ PortInsertWindow::PortInsertWindow (Session& sess, PortInsert& pi, bool can_canc
        rescan_button.signal_clicked().connect (mem_fun(*this, &PortInsertWindow::rescan));
 
        signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), reinterpret_cast<Window *> (this))); 
-       pi.GoingAway.connect (mem_fun(*this, &PortInsertWindow::plugin_going_away));
+       pi->GoingAway.connect (mem_fun(*this, &PortInsertWindow::plugin_going_away));
 }
 
 void
index 44518e67599651c7b119bb557283955076247d49..993d4aa1ad0da73f3e9df1638a2af6cb1ea2995b 100644 (file)
@@ -53,7 +53,7 @@ namespace ARDOUR {
 
 class IOSelector : public Gtk::VBox {
   public:
-       IOSelector (ARDOUR::Session&, ARDOUR::IO&, bool for_input);
+       IOSelector (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>, bool for_input);
        ~IOSelector ();
 
        void redisplay ();
@@ -67,9 +67,9 @@ class IOSelector : public Gtk::VBox {
 
   protected:
        ARDOUR::Session& session;
-
+       
   private:
-       ARDOUR::IO& io;
+       boost::shared_ptr<ARDOUR::IO> io;
        bool for_input;
        ARDOUR::Port *selected_port;
 
@@ -135,7 +135,7 @@ class IOSelector : public Gtk::VBox {
 class IOSelectorWindow : public ArdourDialog
 {
   public:
-       IOSelectorWindow (ARDOUR::Session&, ARDOUR::IO&, bool for_input, bool can_cancel=false);
+       IOSelectorWindow (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>, bool for_input, bool can_cancel=false);
        ~IOSelectorWindow ();
 
        IOSelector& selector() { return _selector; }
@@ -162,7 +162,7 @@ class IOSelectorWindow : public ArdourDialog
 class PortInsertUI : public Gtk::VBox
 {
   public: 
-       PortInsertUI (ARDOUR::Session&, ARDOUR::PortInsert&);
+       PortInsertUI (ARDOUR::Session&, boost::shared_ptr<ARDOUR::PortInsert>);
        
        void redisplay ();
        void finished (IOSelector::Result);
@@ -178,7 +178,7 @@ class PortInsertUI : public Gtk::VBox
 class PortInsertWindow : public ArdourDialog
 {
   public: 
-       PortInsertWindow (ARDOUR::Session&, ARDOUR::PortInsert&, bool can_cancel=false);
+       PortInsertWindow (ARDOUR::Session&, boost::shared_ptr<ARDOUR::PortInsert>, bool can_cancel=false);
        
   protected:
        void on_map ();
index 06ed4c800d055a92bbfe9031b3e971e8072f79ee..c13b06afe50f6dad2ff204fda0926303b713e297 100644 (file)
@@ -28,7 +28,7 @@
 #include <gtk/gtk.h>
 
 #include <ardour/types.h>
-#include <ardour/stateful.h>
+#include <pbd/stateful.h>
 
 #include "selection.h"
 
index 778355c858414b1793c509ef36df39cbbd84b7e0..047bb130a4b218771cdb0ed9522b5c21a573b8a0 100644 (file)
@@ -446,7 +446,7 @@ int main (int argc, char *argv[])
        
        try { 
                engine = new ARDOUR::AudioEngine (jack_client_name);
-               ARDOUR::init (*engine, use_vst, try_hw_optimization);
+               ARDOUR::init (use_vst, try_hw_optimization);
                ui->set_engine (*engine);
        } catch (AudioEngine::NoBackendAvailable& err) {
                gui_jack_error ();
index 47d884be5e49d6a2bc72f75197fc24fee87e8e9d..4f3dc720d917aac8074ca5bc8cbbbd4a901b392a 100644 (file)
 #include <gtkmm2ext/gtk_ui.h>
 #include <gtkmm2ext/utils.h>
 #include <gtkmm2ext/choice.h>
-#include <gtkmm2ext/slider_controller.h>
 #include <gtkmm2ext/stop_signal.h>
-#include <gtkmm2ext/bindable_button.h>
 #include <gtkmm2ext/doi.h>
+#include <gtkmm2ext/slider_controller.h>
+#include <gtkmm2ext/bindable_button.h>
 
 #include <ardour/ardour.h>
 #include <ardour/session.h>
@@ -52,7 +52,6 @@
 #include "keyboard.h"
 #include "plugin_selector.h"
 #include "public_editor.h"
-
 #include "plugin_ui.h"
 #include "send_ui.h"
 #include "io_selector.h"
@@ -81,7 +80,7 @@ speed_printer (char buf[32], Gtk::Adjustment& adj, void* arg)
 }
 #endif 
 
-MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, Route& rt, bool in_mixer)
+MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt, bool in_mixer)
        : AxisView(sess),
          RouteUI (rt, sess, _("Mute"), _("Solo"), _("Record")),
          _mixer(mx),
@@ -126,12 +125,12 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, Route& rt, bool in_mixer)
        output_button.set_name ("MixerIOButton");
        output_label.set_name ("MixerIOButtonLabel");
 
-       _route.meter_change.connect (mem_fun(*this, &MixerStrip::meter_changed));
+       _route->meter_change.connect (mem_fun(*this, &MixerStrip::meter_changed));
                meter_point_button.add (meter_point_label);
                meter_point_button.set_name ("MixerStripMeterPreButton");
                meter_point_label.set_name ("MixerStripMeterPreButton");
                
-               switch (_route.meter_point()) {
+               switch (_route->meter_point()) {
                case MeterInput:
                        meter_point_label.set_text (_("input"));
                        break;
@@ -159,9 +158,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, Route& rt, bool in_mixer)
        /* XXX what is this meant to do? */
        //meter_point_button.signal_button_release_event().connect (mem_fun (gpm, &GainMeter::meter_release), false);
 
-       rec_enable_button->set_name ("MixerRecordEnableButton");
-       rec_enable_button->unset_flags (Gtk::CAN_FOCUS);
-
        solo_button->set_name ("MixerSoloButton");
        mute_button->set_name ("MixerMuteButton");
 
@@ -191,7 +187,11 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, Route& rt, bool in_mixer)
 
        if (is_audio_track()) {
                
-               AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
+               rec_enable_button->set_name ("MixerRecordEnableButton");
+               rec_enable_button->unset_flags (Gtk::CAN_FOCUS);
+               rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press));
+
+               AudioTrack* at = audio_track();
 
                at->FreezeChange.connect (mem_fun(*this, &MixerStrip::map_frozen));
 
@@ -217,10 +217,10 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, Route& rt, bool in_mixer)
        Gtkmm2ext::set_size_request_to_display_given_text (name_button, "longest label", 2, 2);
 
        name_label.set_name ("MixerNameButtonLabel");
-       if (_route.phase_invert()) {
+       if (_route->phase_invert()) {
                name_label.set_text (X_("Ø ") + name_label.get_text());
        } else {
-               name_label.set_text (_route.name());
+               name_label.set_text (_route->name());
        }
 
        group_button.add (group_label);
@@ -229,9 +229,9 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, Route& rt, bool in_mixer)
 
        comment_button.set_name ("MixerCommentButton");
 
-       ARDOUR_UI::instance()->tooltips().set_tip (comment_button, _route.comment()=="" ?
+       ARDOUR_UI::instance()->tooltips().set_tip (comment_button, _route->comment()==""        ?
                                                        _("Click to Add/Edit Comments"):
-                                                       _route.comment());
+                                                       _route->comment());
 
        comment_button.signal_clicked().connect (mem_fun(*this, &MixerStrip::comment_button_clicked));
        
@@ -281,27 +281,26 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, Route& rt, bool in_mixer)
 
        _session.engine().Stopped.connect (mem_fun(*this, &MixerStrip::engine_stopped));
        _session.engine().Running.connect (mem_fun(*this, &MixerStrip::engine_running));
-       _route.input_changed.connect (mem_fun(*this, &MixerStrip::input_changed));
-       _route.output_changed.connect (mem_fun(*this, &MixerStrip::output_changed));
-       _route.mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
-       _route.solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
-       _route.solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
-       _route.mix_group_changed.connect (mem_fun(*this, &MixerStrip::mix_group_changed));
-       _route.panner().Changed.connect (mem_fun(*this, &MixerStrip::connect_to_pan));
+       _route->input_changed.connect (mem_fun(*this, &MixerStrip::input_changed));
+       _route->output_changed.connect (mem_fun(*this, &MixerStrip::output_changed));
+       _route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
+       _route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
+       _route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
+       _route->mix_group_changed.connect (mem_fun(*this, &MixerStrip::mix_group_changed));
+       _route->panner().Changed.connect (mem_fun(*this, &MixerStrip::connect_to_pan));
 
        if (is_audio_track()) {
-               audio_track()->diskstream_changed.connect (mem_fun(*this, &MixerStrip::diskstream_changed));
-               get_diskstream()->speed_changed.connect (mem_fun(*this, &MixerStrip::speed_changed));
+               audio_track()->DiskstreamChanged.connect (mem_fun(*this, &MixerStrip::diskstream_changed));
+               get_diskstream()->SpeedChanged.connect (mem_fun(*this, &MixerStrip::speed_changed));
        }
 
-       _route.name_changed.connect (mem_fun(*this, &RouteUI::name_changed));
-       _route.comment_changed.connect (mem_fun(*this, &MixerStrip::comment_changed));
-       _route.gui_changed.connect (mem_fun(*this, &MixerStrip::route_gui_changed));
+       _route->name_changed.connect (mem_fun(*this, &RouteUI::name_changed));
+       _route->comment_changed.connect (mem_fun(*this, &MixerStrip::comment_changed));
+       _route->gui_changed.connect (mem_fun(*this, &MixerStrip::route_gui_changed));
 
        input_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::input_press), false);
        output_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::output_press), false);
 
-       rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press));
        solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press), false);
        solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release), false);
        mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false);
@@ -414,20 +413,22 @@ MixerStrip::set_width (Width w)
                set_size_request (-1, -1);
                xml_node->add_property ("strip_width", "wide");
 
-               rec_enable_button->set_label (_("record"));
+               if (rec_enable_button) {
+                       rec_enable_button->set_label (_("record"));
+               }
                mute_button->set_label  (_("mute"));
                solo_button->set_label (_("solo"));
 
-               if (_route.comment() == "") {
+               if (_route->comment() == "") {
                       comment_button.set_label (_("comments"));
                } else {
                       comment_button.set_label (_("*comments*"));
                }
 
-               gpm.gain_automation_style_button.set_label (gpm.astyle_string(_route.gain_automation_curve().automation_style()));
-               gpm.gain_automation_state_button.set_label (gpm.astate_string(_route.gain_automation_curve().automation_state()));
-               panners.pan_automation_style_button.set_label (panners.astyle_string(_route.panner().automation_style()));
-               panners.pan_automation_state_button.set_label (panners.astate_string(_route.panner().automation_state()));
+               gpm.gain_automation_style_button.set_label (gpm.astyle_string(_route->gain_automation_curve().automation_style()));
+               gpm.gain_automation_state_button.set_label (gpm.astate_string(_route->gain_automation_curve().automation_state()));
+               panners.pan_automation_style_button.set_label (panners.astyle_string(_route->panner().automation_style()));
+               panners.pan_automation_state_button.set_label (panners.astate_string(_route->panner().automation_state()));
                Gtkmm2ext::set_size_request_to_display_given_text (name_button, "long", 2, 2);
                break;
 
@@ -435,20 +436,22 @@ MixerStrip::set_width (Width w)
                set_size_request (50, -1);
                xml_node->add_property ("strip_width", "narrow");
 
-               rec_enable_button->set_label (_("Rec"));
+               if (rec_enable_button) {
+                       rec_enable_button->set_label (_("Rec"));
+               }
                mute_button->set_label (_("M"));
                solo_button->set_label (_("S"));
 
-               if (_route.comment() == "") {
+               if (_route->comment() == "") {
                       comment_button.set_label (_("Cmt"));
                } else {
                       comment_button.set_label (_("*Cmt*"));
                }
 
-               gpm.gain_automation_style_button.set_label (gpm.short_astyle_string(_route.gain_automation_curve().automation_style()));
-               gpm.gain_automation_state_button.set_label (gpm.short_astate_string(_route.gain_automation_curve().automation_state()));
-               panners.pan_automation_style_button.set_label (panners.short_astyle_string(_route.panner().automation_style()));
-               panners.pan_automation_state_button.set_label (panners.short_astate_string(_route.panner().automation_state()));
+               gpm.gain_automation_style_button.set_label (gpm.short_astyle_string(_route->gain_automation_curve().automation_style()));
+               gpm.gain_automation_state_button.set_label (gpm.short_astate_string(_route->gain_automation_curve().automation_state()));
+               panners.pan_automation_style_button.set_label (panners.short_astyle_string(_route->panner().automation_style()));
+               panners.pan_automation_state_button.set_label (panners.short_astate_string(_route->panner().automation_state()));
                Gtkmm2ext::set_size_request_to_display_given_text (name_button, "longest label", 2, 2);
                break;
        }
@@ -555,11 +558,6 @@ MixerStrip::input_press (GdkEventButton *ev)
 
        case 1:
 
-#if ADVANCED_ROUTE_DISKSTREAM_CONNECTIVITY
-               if (is_audio_track()) {
-                       citems.push_back (MenuElem (_("Track"), mem_fun(*this, &MixerStrip::select_stream_input)));
-               }
-#endif
                citems.push_back (MenuElem (_("Edit"), mem_fun(*this, &MixerStrip::edit_input_configuration)));
                citems.push_back (SeparatorElem());
                citems.push_back (MenuElem (_("Disconnect"), mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::disconnect_input)));
@@ -581,7 +579,7 @@ MixerStrip::connection_input_chosen (ARDOUR::Connection *c)
        if (!ignore_toggle) {
 
                try { 
-                       _route.use_input_connection (*c, this);
+                       _route->use_input_connection (*c, this);
                }
 
                catch (AudioEngine::PortRegistrationFailure& err) {
@@ -597,7 +595,7 @@ MixerStrip::connection_output_chosen (ARDOUR::Connection *c)
        if (!ignore_toggle) {
 
                try { 
-                       _route.use_output_connection (*c, this);
+                       _route->use_output_connection (*c, this);
                }
 
                catch (AudioEngine::PortRegistrationFailure& err) {
@@ -618,11 +616,11 @@ MixerStrip::add_connection_to_input_menu (ARDOUR::Connection* c)
 
        MenuList& citems = input_menu.items();
        
-       if (c->nports() == _route.n_inputs()) {
+       if (c->nports() == _route->n_inputs()) {
 
                citems.push_back (CheckMenuElem (c->name(), bind (mem_fun(*this, &MixerStrip::connection_input_chosen), c)));
                
-               ARDOUR::Connection *current = _route.input_connection();
+               ARDOUR::Connection *current = _route->input_connection();
                
                if (current == c) {
                        ignore_toggle = true;
@@ -641,12 +639,12 @@ MixerStrip::add_connection_to_output_menu (ARDOUR::Connection* c)
                return;
        }
 
-       if (c->nports() == _route.n_outputs()) {
+       if (c->nports() == _route->n_outputs()) {
 
                MenuList& citems = output_menu.items();
                citems.push_back (CheckMenuElem (c->name(), bind (mem_fun(*this, &MixerStrip::connection_output_chosen), c)));
                
-               ARDOUR::Connection *current = _route.output_connection();
+               ARDOUR::Connection *current = _route->output_connection();
                
                if (current == c) {
                        ignore_toggle = true;
@@ -656,42 +654,6 @@ MixerStrip::add_connection_to_output_menu (ARDOUR::Connection* c)
        }
 }
 
-void
-MixerStrip::select_stream_input ()
-{
-       using namespace Menu_Helpers;
-
-       Menu *stream_menu = manage (new Menu);
-       MenuList& items = stream_menu->items();
-       stream_menu->set_name ("ArdourContextMenu");
-       
-       Session::AudioDiskstreamList streams = _session.audio_disk_streams();
-
-       for (Session::AudioDiskstreamList::iterator i = streams.begin(); i != streams.end(); ++i) {
-
-               if (!(*i)->hidden()) {
-
-                       items.push_back (CheckMenuElem ((*i)->name(), bind (mem_fun(*this, &MixerStrip::stream_input_chosen), *i)));
-                       
-                       if (get_diskstream() == *i) {
-                               ignore_toggle = true;
-                               static_cast<CheckMenuItem *> (&items.back())->set_active (true);
-                               ignore_toggle = false;
-                       } 
-               }
-       }
-       
-       stream_menu->popup (1, 0);
-}
-
-void
-MixerStrip::stream_input_chosen (AudioDiskstream *stream)
-{
-       if (is_audio_track()) {
-               audio_track()->set_diskstream (*stream, this);
-       }
-}
-
 void
 MixerStrip::update_diskstream_display ()
 {
@@ -724,8 +686,8 @@ MixerStrip::connect_to_pan ()
        panstate_connection.disconnect ();
        panstyle_connection.disconnect ();
 
-       if (!_route.panner().empty()) {
-               StreamPanner* sp = _route.panner().front();
+       if (!_route->panner().empty()) {
+               StreamPanner* sp = _route->panner().front();
 
                panstate_connection = sp->automation().automation_state_changed.connect (mem_fun(panners, &PannerUI::pan_automation_state_changed));
                panstyle_connection = sp->automation().automation_style_changed.connect (mem_fun(panners, &PannerUI::pan_automation_style_changed));
@@ -739,7 +701,7 @@ MixerStrip::update_input_display ()
 {
        ARDOUR::Connection *c;
 
-       if ((c = _route.input_connection()) != 0) {
+       if ((c = _route->input_connection()) != 0) {
                input_label.set_text (c->name());
        } else {
                switch (_width) {
@@ -759,7 +721,7 @@ MixerStrip::update_output_display ()
 {
        ARDOUR::Connection *c;
 
-       if ((c = _route.output_connection()) != 0) {
+       if ((c = _route->output_connection()) != 0) {
                output_label.set_text (c->name());
        } else {
                switch (_width) {
@@ -782,7 +744,7 @@ MixerStrip::fast_update ()
 }
 
 void
-MixerStrip::diskstream_changed (void *src)
+MixerStrip::diskstream_changed ()
 {
        Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_diskstream_display));
 }      
@@ -810,8 +772,8 @@ MixerStrip::comment_button_clicked ()
 
        if (comment_window->is_visible()) {
               string str =  comment_area->get_buffer()->get_text();
-              if (_route.comment() != str) {
-                _route.set_comment (str, this);
+              if (_route->comment() != str) {
+                _route->set_comment (str, this);
 
                 switch (_width) {
                   
@@ -855,7 +817,7 @@ void
 MixerStrip::setup_comment_editor ()
 {
        string title;
-       title = _route.name();
+       title = _route->name();
        title += _(": comment editor");
 
        comment_window = new ArdourDialog (title, false);
@@ -867,7 +829,7 @@ MixerStrip::setup_comment_editor ()
        comment_area->set_size_request (110, 178);
        comment_area->set_wrap_mode (WRAP_WORD);
        comment_area->set_editable (true);
-       comment_area->get_buffer()->set_text (_route.comment());
+       comment_area->get_buffer()->set_text (_route->comment());
        comment_area->show ();
 
        comment_window->get_vbox()->pack_start (*comment_area);
@@ -882,7 +844,7 @@ MixerStrip::comment_changed (void *src)
        if (src != this) {
                ignore_comment_edit = true;
                if (comment_area) {
-                       comment_area->get_buffer()->set_text (_route.comment());
+                       comment_area->get_buffer()->set_text (_route->comment());
                }
                ignore_comment_edit = false;
        }
@@ -891,7 +853,7 @@ MixerStrip::comment_changed (void *src)
 void
 MixerStrip::set_mix_group (RouteGroup *rg)
 {
-       _route.set_mix_group (rg, this);
+       _route->set_mix_group (rg, this);
 }
 
 void
@@ -903,7 +865,7 @@ MixerStrip::add_mix_group_to_menu (RouteGroup *rg, RadioMenuItem::Group* group)
 
        items.push_back (RadioMenuElem (*group, rg->name(), bind (mem_fun(*this, &MixerStrip::set_mix_group), rg)));
 
-       if (_route.mix_group() == rg) {
+       if (_route->mix_group() == rg) {
                static_cast<RadioMenuItem*>(&items.back())->set_active ();
        }
 }
@@ -943,7 +905,7 @@ MixerStrip::mix_group_changed (void *ignored)
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &MixerStrip::mix_group_changed), ignored));
        
-       RouteGroup *rg = _route.mix_group();
+       RouteGroup *rg = _route->mix_group();
        
        if (rg) {
                group_label.set_text (rg->name());
@@ -999,11 +961,11 @@ MixerStrip::build_route_ops_menu ()
        items.push_back (SeparatorElem());
        items.push_back (CheckMenuElem (_("Active"), mem_fun (*this, &RouteUI::toggle_route_active)));
        route_active_menu_item = dynamic_cast<CheckMenuItem *> (&items.back());
-       route_active_menu_item->set_active (_route.active());
+       route_active_menu_item->set_active (_route->active());
        items.push_back (SeparatorElem());
        items.push_back (CheckMenuElem (_("Invert Polarity"), mem_fun (*this, &RouteUI::toggle_polarity)));
        polarity_menu_item = dynamic_cast<CheckMenuItem *> (&items.back());
-       polarity_menu_item->set_active (_route.phase_invert());
+       polarity_menu_item->set_active (_route->phase_invert());
 
        build_remote_control_menu ();
        
@@ -1093,10 +1055,10 @@ MixerStrip::name_changed (void *src)
                RouteUI::name_changed (src);
                break;
        case Narrow:
-               name_label.set_text (PBD::short_version (_route.name(), 5));
+               name_label.set_text (PBD::short_version (_route->name(), 5));
                break;
        }
-       if (_route.phase_invert()) {
+       if (_route->phase_invert()) {
                name_label.set_text (X_("Ø ") + name_label.get_text());
        }
 }
@@ -1135,7 +1097,7 @@ MixerStrip::map_frozen ()
 {
        ENSURE_GUI_THREAD (mem_fun(*this, &MixerStrip::map_frozen));
 
-       AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
+       AudioTrack* at = audio_track();
 
        if (at) {
                switch (at->freeze_state()) {
@@ -1151,11 +1113,11 @@ MixerStrip::map_frozen ()
                        break;
                }
        }
-       _route.foreach_redirect (this, &MixerStrip::hide_redirect_editor);
+       _route->foreach_redirect (this, &MixerStrip::hide_redirect_editor);
 }
 
 void
-MixerStrip::hide_redirect_editor (Redirect* redirect)
+MixerStrip::hide_redirect_editor (boost::shared_ptr<Redirect> redirect)
 {
        void* gui = redirect->get_gui ();
        
@@ -1170,7 +1132,7 @@ MixerStrip::route_active_changed ()
        RouteUI::route_active_changed ();
 
        if (is_audio_track()) {
-               if (_route.active()) {
+               if (_route->active()) {
                        set_name ("AudioTrackStripBase");
                        gpm.set_meter_strip_name ("AudioTrackStripBase");
                } else {
@@ -1178,8 +1140,8 @@ MixerStrip::route_active_changed ()
                        gpm.set_meter_strip_name ("AudioTrackStripBaseInactive");
                }
                gpm.set_fader_name ("AudioTrackFader");
-       } else {
-               if (_route.active()) {
+       } else { // FIXME: assumed audio bus
+               if (_route->active()) {
                        set_name ("AudioBusStripBase");
                        gpm.set_meter_strip_name ("AudioBusStripBase");
                } else {
@@ -1193,14 +1155,16 @@ MixerStrip::route_active_changed ()
 RouteGroup*
 MixerStrip::mix_group() const
 {
-       return _route.mix_group();
+       return _route->mix_group();
 }
 
 void
 MixerStrip::engine_stopped ()
 {
         input_button.set_sensitive (false);
-       rec_enable_button->set_sensitive (false);
+       if (rec_enable_button) {
+               rec_enable_button->set_sensitive (false);
+       }
        output_button.set_sensitive (false);
 }
 
@@ -1208,7 +1172,9 @@ void
 MixerStrip::engine_running ()
 {
         input_button.set_sensitive (true);
-       rec_enable_button->set_sensitive (true);
+       if (rec_enable_button) {
+               rec_enable_button->set_sensitive (true);
+       }
        output_button.set_sensitive (true);
 }
 
@@ -1218,7 +1184,7 @@ MixerStrip::meter_changed (void *src)
 
        ENSURE_GUI_THREAD (bind (mem_fun(*this, &MixerStrip::meter_changed), src));
 
-               switch (_route.meter_point()) {
+               switch (_route->meter_point()) {
                case MeterInput:
                        meter_point_label.set_text (_("input"));
                        break;
index 0cc8fed8e3bcdacc4ec61ec1afe642565be74fb2..21db0d14ca83b4a17dd6b8234b5046e2c674bb80 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
@@ -14,8 +14,6 @@
     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$
 */
 
 #ifndef __ardour_mixer_strip__
 #include <gtkmm/adjustment.h>
 
 #include <gtkmm2ext/auto_spin.h>
-#include <gtkmm2ext/slider_controller.h>
 #include <gtkmm2ext/click_box.h>
+#include <gtkmm2ext/slider_controller.h>
+
+#include <pbd/stateful.h>
 
 #include <ardour/types.h>
 #include <ardour/ardour.h>
 #include <ardour/io.h>
 #include <ardour/insert.h>
-#include <ardour/stateful.h>
 #include <ardour/redirect.h>
 
 #include <pbd/fastlog.h>
@@ -83,7 +82,7 @@ class Mixer_UI;
 class MixerStrip : public RouteUI, public Gtk::EventBox
 {
   public:
-       MixerStrip (Mixer_UI&, ARDOUR::Session&, ARDOUR::Route &, bool in_mixer = true);
+       MixerStrip (Mixer_UI&, ARDOUR::Session&, boost::shared_ptr<ARDOUR::Route>, bool in_mixer = true);
        ~MixerStrip ();
 
        void set_width (Width);
@@ -170,15 +169,13 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
        Gtk::Menu output_menu;
        void add_connection_to_output_menu (ARDOUR::Connection *);
        
-       void stream_input_chosen (ARDOUR::AudioDiskstream*);
-       void select_stream_input ();
        void connection_input_chosen (ARDOUR::Connection *);
        void connection_output_chosen (ARDOUR::Connection *);
 
        void edit_input_configuration ();
        void edit_output_configuration ();
 
-       void diskstream_changed (void *src);
+       void diskstream_changed ();
 
        Gtk::Menu *send_action_menu;
        void build_send_action_menu ();
@@ -238,7 +235,7 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
        void name_changed (void *src);
        void update_speed_display ();
        void map_frozen ();
-       void hide_redirect_editor (ARDOUR::Redirect* redirect);
+       void hide_redirect_editor (boost::shared_ptr<ARDOUR::Redirect> redirect);
 
        bool ignore_speed_adjustment;
 
index 983903d6dd04da5e56ad802564ce46a122f13c32..c2eb588b2f2744865d085574155f36aff585e3cf 100644 (file)
@@ -251,7 +251,7 @@ Mixer_UI::show_window ()
 }
 
 void
-Mixer_UI::add_strip (Route* route)
+Mixer_UI::add_strip (boost::shared_ptr<Route> route)
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &Mixer_UI::add_strip), route));
        
@@ -261,7 +261,7 @@ Mixer_UI::add_strip (Route* route)
                return;
        }
 
-       strip = new MixerStrip (*this, *session, *route);
+       strip = new MixerStrip (*this, *session, route);
        strips.push_back (strip);
 
        strip->set_width (_strip_width);
@@ -310,7 +310,7 @@ void
 Mixer_UI::follow_strip_selection ()
 {
        for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
-               (*i)->set_selected (_selection.selected (&(*i)->route()));
+               (*i)->set_selected (_selection.selected ((*i)->route()));
        }
 }
 
@@ -324,13 +324,13 @@ Mixer_UI::strip_button_release_event (GdkEventButton *ev, MixerStrip *strip)
                   at the same time.
                */
                
-               if (_selection.selected (&strip->route())) {
-                       _selection.remove (&strip->route());
+               if (_selection.selected (strip->route())) {
+                       _selection.remove (strip->route());
                } else {
                        if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
-                               _selection.add (&strip->route());
+                               _selection.add (strip->route());
                        } else {
-                               _selection.set (&strip->route());
+                               _selection.set (strip->route());
                        }
                }
        }
@@ -444,7 +444,7 @@ Mixer_UI::set_all_strips_visibility (bool yn)
                        continue;
                }
                
-               if (strip->route().master() || strip->route().control()) {
+               if (strip->route()->master() || strip->route()->control()) {
                        continue;
                }
 
@@ -472,11 +472,11 @@ Mixer_UI::set_all_audio_visibility (int tracks, bool yn)
                        continue;
                }
 
-               if (strip->route().master() || strip->route().control()) {
+               if (strip->route()->master() || strip->route()->control()) {
                        continue;
                }
 
-               AudioTrack* at = dynamic_cast<AudioTrack*> (&strip->route());
+               AudioTrack* at = strip->audio_track();
 
                switch (tracks) {
                case 0:
@@ -570,11 +570,11 @@ Mixer_UI::redisplay_track_list ()
 
                if (visible) {
                        strip->set_marked_for_display (true);
-                       strip->route().set_order_key (N_("signal"), order);
+                       strip->route()->set_order_key (N_("signal"), order);
 
                        if (strip->packed()) {
 
-                               if (strip->route().master() || strip->route().control()) {
+                               if (strip->route()->master() || strip->route()->control()) {
                                        out_packer.reorder_child (*strip, -1);
                                } else {
                                        strip_packer.reorder_child (*strip, -1); /* put at end */
@@ -582,7 +582,7 @@ Mixer_UI::redisplay_track_list ()
 
                        } else {
 
-                               if (strip->route().master() || strip->route().control()) {
+                               if (strip->route()->master() || strip->route()->control()) {
                                        out_packer.pack_start (*strip, false, false);
                                } else {
                                        strip_packer.pack_start (*strip, false, false);
@@ -593,7 +593,7 @@ Mixer_UI::redisplay_track_list ()
 
                } else {
 
-                       if (strip->route().master() || strip->route().control()) {
+                       if (strip->route()->master() || strip->route()->control()) {
                                /* do nothing, these cannot be hidden */
                        } else {
                                strip_packer.remove (*strip);
@@ -604,7 +604,7 @@ Mixer_UI::redisplay_track_list ()
 }
 
 struct SignalOrderRouteSorter {
-    bool operator() (Route* a, Route* b) {
+    bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
            /* use of ">" forces the correct sort order */
            return a->order_key ("signal") < b->order_key ("signal");
     }
@@ -613,16 +613,17 @@ struct SignalOrderRouteSorter {
 void
 Mixer_UI::initial_track_display ()
 {
-       Session::RouteList routes = session->get_routes();
+       boost::shared_ptr<Session::RouteList> routes = session->get_routes();
+       Session::RouteList copy (*routes);
        SignalOrderRouteSorter sorter;
 
-       routes.sort (sorter);
+       copy.sort (sorter);
        
        no_track_list_redisplay = true;
 
        track_model->clear ();
 
-       for (Session::RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (Session::RouteList::iterator i = copy.begin(); i != copy.end(); ++i) {
                add_strip (*i);
        }
 
@@ -670,7 +671,7 @@ Mixer_UI::track_display_button_press (GdkEventButton* ev)
                        MixerStrip* strip = (*iter)[track_columns.strip];
                        if (strip) {
 
-                               if (!strip->route().master() && !strip->route().control()) {
+                               if (!strip->route()->master() && !strip->route()->control()) {
                                        bool visible = (*iter)[track_columns.visible];
                                        (*iter)[track_columns.visible] = !visible;
                                }
@@ -715,7 +716,7 @@ Mixer_UI::strip_name_changed (void* src, MixerStrip* mx)
        
        for (i = rows.begin(); i != rows.end(); ++i) {
                if ((*i)[track_columns.strip] == mx) {
-                       (*i)[track_columns.text] = mx->route().name();
+                       (*i)[track_columns.text] = mx->route()->name();
                        return;
                }
        } 
index 5108df60142677a433dbf75fdd17cd9e27244d4e..6fe41204279cc840ce0a12007cec0c729d3d1418 100644 (file)
@@ -33,8 +33,9 @@
 #include <gtkmm/menu.h>
 #include <gtkmm/treeview.h>
 
+#include <pbd/stateful.h>
+
 #include <ardour/ardour.h>
-#include <ardour/stateful.h>
 #include <ardour/io.h>
 
 #include "keyboard_target.h"
@@ -110,7 +111,7 @@ class Mixer_UI : public Gtk::Window
 
        bool strip_scroller_button_release (GdkEventButton*);
 
-       void add_strip (ARDOUR::Route*);
+       void add_strip (boost::shared_ptr<ARDOUR::Route>);
        void remove_strip (MixerStrip *);
 
        void hide_all_strips (bool with_select);
@@ -193,7 +194,7 @@ class Mixer_UI : public Gtk::Window
            }
            Gtk::TreeModelColumn<bool>           visible;
            Gtk::TreeModelColumn<Glib::ustring>  text;
-           Gtk::TreeModelColumn<ARDOUR::Route*> route;
+           Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Route> > route;
            Gtk::TreeModelColumn<MixerStrip*>    strip;
        };
 
index d4c27157421e8e09af02a5516944bcddbecd1bc1..b7fc7e746e539fc097f795d9d7175892c5560d4f 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2001 Paul Davis 
+    Copyright (C) 2001-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
@@ -20,6 +20,7 @@
 
 #include <pbd/whitespace.h>
 
+#include <ardour/audio_library.h>
 #include <ardour/session.h>
 #include <ardour/audioengine.h>
 #include <ardour/configuration.h>
@@ -59,9 +60,7 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
 
          /* Paths */
          path_table (11, 2),
-         sfdb_path_columns(),
-         sfdb_paths(ListStore::create(sfdb_path_columns)),
-         sfdb_path_view(sfdb_paths),
+         sfdb_path_view(),
 
          /* Fades */
 
@@ -163,7 +162,6 @@ OptionEditor::set_session (Session *s)
                return;
        }
 
-
        click_path_entry.set_sensitive (true);
        click_emphasis_path_entry.set_sensitive (true);
        session_raid_entry.set_sensitive (true);
@@ -251,12 +249,18 @@ OptionEditor::setup_path_options()
        path_table.attach(*label, 0, 1, 2, 3, FILL|EXPAND, FILL);
        path_table.attach(sfdb_path_view, 1, 3, 2, 3, Gtk::FILL|Gtk::EXPAND, FILL);
 
-       sfdb_path_view.append_column(_("Paths"), sfdb_path_columns.paths);
-       sfdb_path_view.set_size_request(-1, 100);
+       sfdb_path_view.set_paths(Library->get_paths());
+       sfdb_path_view.PathsUpdated.connect (mem_fun(*this, &OptionEditor::sfdb_paths_changed));
 
        path_table.show_all();
 }
 
+void
+OptionEditor::sfdb_paths_changed ()
+{
+       Library->set_paths (sfdb_path_view.get_paths());
+}
+
 void
 OptionEditor::add_session_paths ()
 {
index b9690b02e2d07572fd862df7c84ecda4b5036c37..1331d3126efee35f14fff43c51973988cfb0fdfd 100644 (file)
@@ -33,6 +33,8 @@
 #include <gtkmm/radiobutton.h>
 #include <gtkmm/comboboxtext.h>
 
+#include <gtkmm2ext/pathlist.h>
+
 #include <ardour/session.h>
 
 #include "ardour_dialog.h"
@@ -70,24 +72,16 @@ class OptionEditor : public Gtk::Dialog
 
        /* paths */
 
-       Gtk::Table              path_table;
-       Gtk::Entry              session_raid_entry;
-
-       struct SoundFilePathColumns : public Gtk::TreeModel::ColumnRecord {
-           public:
-                 SoundFilePathColumns() { add (paths); }
-                 Gtk::TreeModelColumn<std::string> paths;
-                           
-       };
+       Gtk::Table      path_table;
+       Gtk::Entry      session_raid_entry;
 
-       SoundFilePathColumns sfdb_path_columns;
-       Glib::RefPtr<Gtk::ListStore> sfdb_paths;
-       Gtk::TreeView sfdb_path_view;
+       Gtkmm2ext::PathList sfdb_path_view;
 
        void setup_path_options();
        void add_session_paths ();
        void remove_session_paths ();
        void raid_path_changed ();
+       void sfdb_paths_changed ();
 
        /* fades */
 
index 73d0f7f1aa0c0cc0d784da7f45ec3b948edaed6e..3169f65059521e99faacf58c05c98f7b52347643 100644 (file)
@@ -28,6 +28,7 @@
 #include "pan_automation_time_axis.h"
 #include "automation_line.h"
 #include "canvas_impl.h"
+#include "route_ui.h"
 
 #include "i18n.h"
 
@@ -35,11 +36,15 @@ using namespace ARDOUR;
 using namespace PBD;
 using namespace Gtk;
 
-PanAutomationTimeAxisView::PanAutomationTimeAxisView (Session& s, Route& r, PublicEditor& e, TimeAxisView& parent, Canvas& canvas, std::string n)
+PanAutomationTimeAxisView::PanAutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r, PublicEditor& e, 
+                                                     TimeAxisView& parent, Canvas& canvas, std::string n)
 
        : AxisView (s),
          AutomationTimeAxisView (s, r, e, parent, canvas, n, X_("pan"), "")
 {
+       multiline_selector.set_name ("PanAutomationLineSelector");
+       
+       controls_table.attach (multiline_selector, 1, 5, 1, 2, Gtk::EXPAND, Gtk::EXPAND);
 }
 
 PanAutomationTimeAxisView::~PanAutomationTimeAxisView ()
@@ -54,14 +59,19 @@ PanAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEv
                return;
        }
 
+       int line_index = 0;
+
        if (lines.size() > 1) {
+               line_index = multiline_selector.get_active_row_number();
 
-               Gtkmm2ext::PopUp* msg = new Gtkmm2ext::PopUp (Gtk::WIN_POS_MOUSE, 5000, true);
-               
-               msg->set_text (_("You can't graphically edit panning of more than stream"));
-               msg->touch ();
+               if (line_index < 0 || line_index >= (int)lines.size()) {
+                       Gtkmm2ext::PopUp* msg = new Gtkmm2ext::PopUp (Gtk::WIN_POS_MOUSE, 5000, true);
                
-               return;
+                       msg->set_text (_("You need to select which line to edit"));
+                       msg->touch ();
+
+                       return;
+               }
        }
 
        double x = 0;
@@ -76,7 +86,7 @@ PanAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEv
 
        lines.front()->view_to_model_y (y);
 
-       AutomationList& alist (lines.front()->the_list());
+       AutomationList& alist (lines[line_index]->the_list());
 
        _session.begin_reversible_command (_("add pan automation event"));
        XMLNode &before = alist.get_state();
@@ -87,10 +97,57 @@ PanAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEv
        _session.set_dirty ();
 }
 
+void
+PanAutomationTimeAxisView::clear_lines ()
+{
+       AutomationTimeAxisView::clear_lines();
+       multiline_selector.clear();
+}
+
+void
+PanAutomationTimeAxisView::add_line (AutomationLine& line)
+{
+       char buf[32];
+       snprintf(buf,32,"Line %u",lines.size()+1);
+       multiline_selector.append_text(buf);
+
+       if (lines.empty()) {
+               multiline_selector.set_active(0);
+       }
+
+       if (lines.size() + 1 > 1 && (height_style != Small && height_style != Smaller)) {
+               multiline_selector.show();
+       } else {
+               multiline_selector.hide();
+
+       }
+
+       AutomationTimeAxisView::add_line(line);
+}
+
+void
+PanAutomationTimeAxisView::set_height (TimeAxisView::TrackHeight th)
+{
+       AutomationTimeAxisView::set_height(th);
+
+       switch (th) {
+               case Largest:
+               case Large:
+               case Larger:
+               case Normal:
+                       if (lines.size() > 1) {
+                               multiline_selector.show();
+                               break;
+                       } 
+               default:
+                       multiline_selector.hide();
+       }
+}
+
 void
 PanAutomationTimeAxisView::set_automation_state (AutoState state)
 {
        if (!ignore_state_request) {
-               route.panner().set_automation_state (state);
+               route->panner().set_automation_state (state);
        }
 }
index b35ee67735bc4a29065341701fb8568385d6ad56..ca4a4db8e7825f9c0375fde9a159cd88b6ec98c2 100644 (file)
@@ -4,27 +4,36 @@
 #include "canvas.h"
 #include "automation_time_axis.h"
 
+#include <gtkmm/comboboxtext.h>
+
 namespace ARDOUR {
        class Redirect;
 }
 
 class PanAutomationTimeAxisView : public AutomationTimeAxisView
 {
-  public:
-       PanAutomationTimeAxisView (ARDOUR::Session&,
-                                  ARDOUR::Route&,
-                                  PublicEditor&,
-                                  TimeAxisView& parent_axis,
-                                  ArdourCanvas::Canvas& canvas,
-                                  std::string name);
-
-       ~PanAutomationTimeAxisView();
-
-       void add_automation_event (ArdourCanvas::Item *item, GdkEvent *event, jack_nframes_t, double);
-       
-   private:
-        void automation_changed ();
-       void set_automation_state (ARDOUR::AutoState);
+       public:
+               PanAutomationTimeAxisView (ARDOUR::Session&,
+                                          boost::shared_ptr<ARDOUR::Route>,
+                                          PublicEditor&,
+                                          TimeAxisView& parent_axis,
+                                          ArdourCanvas::Canvas& canvas,
+                                          std::string name);
+
+               ~PanAutomationTimeAxisView();
+
+               void add_automation_event (ArdourCanvas::Item *item, GdkEvent *event, jack_nframes_t, double);
+
+               void clear_lines ();
+               void add_line (AutomationLine&);
+               void set_height (TimeAxisView::TrackHeight);
+
+       protected:
+               Gtk::ComboBoxText       multiline_selector;
+
+       private:
+               void automation_changed ();
+               void set_automation_state (ARDOUR::AutoState);
 };
 
 #endif /* __ardour_gtk_pan_automation_time_axis_h__ */
index 63a19867a86e1d60e44478d7b6fc16e2cff86499..ccce2ec9f16ff1092ba66b4569ebb430abbbe280 100644 (file)
@@ -14,8 +14,6 @@
   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$
 */
 
 #include <limits.h>
@@ -47,7 +45,7 @@ using namespace Gtk;
 using namespace sigc;
 
 
-PannerUI::PannerUI (IO& io, Session& s)
+PannerUI::PannerUI (boost::shared_ptr<IO> io, Session& s)
        : _io (io),
          _session (s),
          hAdjustment(0.0, 0.0, 0.0),
@@ -87,13 +85,13 @@ PannerUI::PannerUI (IO& io, Session& s)
 
        using namespace Menu_Helpers;
        pan_astate_menu.items().push_back (MenuElem (_("Off"), 
-                                                    bind (mem_fun (_io.panner(), &Panner::set_automation_state), (AutoState) Off)));
+                                                    bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Off)));
        pan_astate_menu.items().push_back (MenuElem (_("Play"),
-                                                    bind (mem_fun (_io.panner(), &Panner::set_automation_state), (AutoState) Play)));
+                                                    bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Play)));
        pan_astate_menu.items().push_back (MenuElem (_("Write"),
-                                                    bind (mem_fun (_io.panner(), &Panner::set_automation_state), (AutoState) Write)));
+                                                    bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Write)));
        pan_astate_menu.items().push_back (MenuElem (_("Touch"),
-                                                    bind (mem_fun (_io.panner(), &Panner::set_automation_state), (AutoState) Touch)));
+                                                    bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Touch)));
 
        pan_astyle_menu.items().push_back (MenuElem (_("Trim")));
        pan_astyle_menu.items().push_back (MenuElem (_("Abs")));
@@ -143,9 +141,9 @@ PannerUI::PannerUI (IO& io, Session& s)
 
        set_width(Narrow);
 
-       _io.panner().Changed.connect (mem_fun(*this, &PannerUI::panner_changed));
-       _io.panner().LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage));
-       _io.panner().StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state));
+       _io->panner().Changed.connect (mem_fun(*this, &PannerUI::panner_changed));
+       _io->panner().LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage));
+       _io->panner().StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state));
 
        pan_changed (0);
        update_pan_sensitive ();
@@ -165,7 +163,7 @@ PannerUI::panning_link_button_release (GdkEventButton* ev)
 {
        cerr << "link release\n";
        if (!ignore_toggle) {
-               _io.panner().set_linked (!_io.panner().linked());
+               _io->panner().set_linked (!_io->panner().linked());
        }
        return true;
 }
@@ -173,12 +171,12 @@ PannerUI::panning_link_button_release (GdkEventButton* ev)
 void
 PannerUI::panning_link_direction_clicked()
 {
-       switch (_io.panner().link_direction()) {
+       switch (_io->panner().link_direction()) {
        case Panner::SameDirection:
-               _io.panner().set_link_direction (Panner::OppositeDirection);
+               _io->panner().set_link_direction (Panner::OppositeDirection);
                break;
        default:
-               _io.panner().set_link_direction (Panner::SameDirection);
+               _io->panner().set_link_direction (Panner::SameDirection);
                break;
        }
 }
@@ -188,7 +186,7 @@ PannerUI::update_pan_linkage ()
 {
        ENSURE_GUI_THREAD(mem_fun(*this, &PannerUI::update_pan_linkage));
        
-       bool x = _io.panner().linked();
+       bool x = _io->panner().linked();
        bool bx = panning_link_button.get_active();
        
        if (x != bx) {
@@ -200,7 +198,7 @@ PannerUI::update_pan_linkage ()
 
        panning_link_direction_button.set_sensitive (x);
 
-       switch (_io.panner().link_direction()) {
+       switch (_io->panner().link_direction()) {
        case Panner::SameDirection:
                panning_link_direction_button.set_image (*(manage (new Image (get_xpm ("forwardblarrow.xpm")))));
                break;
@@ -278,7 +276,7 @@ PannerUI::update_pan_state ()
 void
 PannerUI::setup_pan ()
 {
-       uint32_t nouts = _io.n_outputs ();
+       uint32_t nouts = _io->n_outputs ();
 
        if (nouts == 0 || nouts == 1) {
 
@@ -292,7 +290,7 @@ PannerUI::setup_pan ()
        } else if (nouts == 2) {
 
                vector<Adjustment*>::size_type asz;
-               uint32_t npans = _io.panner().size();
+               uint32_t npans = _io->panner().size();
 
                while (!pan_adjustments.empty()) {
                        delete pan_bars.back();
@@ -308,34 +306,26 @@ PannerUI::setup_pan ()
 
                        /* initialize adjustment with current value of panner */
 
-                       _io.panner()[asz]->get_position (x);
+                       _io->panner()[asz]->get_position (x);
 
                        pan_adjustments.push_back (new Adjustment (x, 0, 1.0, 0.05, 0.1));
                        pan_adjustments.back()->signal_value_changed().connect (bind (mem_fun(*this, &PannerUI::pan_adjustment_changed), (uint32_t) asz));
 
-                       _io.panner()[asz]->Changed.connect (bind (mem_fun(*this, &PannerUI::pan_value_changed), (uint32_t) asz));
+                       _io->panner()[asz]->Changed.connect (bind (mem_fun(*this, &PannerUI::pan_value_changed), (uint32_t) asz));
 
                        bc = new BarController (*pan_adjustments[asz], 
-                                               &_io.panner()[asz]->midi_control(),
+                                               _io->panner()[asz]->control(),
                                                bind (mem_fun(*this, &PannerUI::pan_printer), pan_adjustments[asz]));
                        
-                       if (_session.midi_port()) {
-                               _io.panner()[asz]->reset_midi_control (_session.midi_port(), true);
-                       }
-                       
                        bc->set_name ("PanSlider");
                        bc->set_shadow_type (Gtk::SHADOW_NONE);
                        bc->set_style (BarController::Line);
 
-                       bc->StartGesture.connect (bind (mem_fun (_io, &IO::start_pan_touch), (uint32_t) asz));
-                       bc->StopGesture.connect (bind (mem_fun (_io, &IO::end_pan_touch), (uint32_t) asz));
+                       bc->StartGesture.connect (bind (mem_fun (*_io, &IO::start_pan_touch), (uint32_t) asz));
+                       bc->StopGesture.connect (bind (mem_fun (*_io, &IO::end_pan_touch), (uint32_t) asz));
 
                        char buf[64];
-#ifdef __APPLE__
-                       snprintf (buf, sizeof (buf), _("panner for channel %lu"), asz + 1);
-#else
-                       snprintf (buf, sizeof (buf), _("panner for channel %u"), asz + 1);
-#endif
+                       snprintf (buf, sizeof (buf), _("panner for channel %zu"), asz + 1);
                        ARDOUR_UI::instance()->tooltips().set_tip (bc->event_widget(), buf);
 
                        bc->event_widget().signal_button_release_event().connect
@@ -379,13 +369,13 @@ PannerUI::setup_pan ()
                }
 
                if (panner == 0) {
-                       panner = new Panner2d (_io.panner(), w, 61);
+                       panner = new Panner2d (_io->panner(), w, 61);
                        panner->set_name ("MixerPanZone");
                        panner->show ();
                }
                
                update_pan_sensitive ();
-               panner->reset (_io.n_inputs());
+               panner->reset (_io->n_inputs());
                panner->set_size_request (w, 61);
 
                /* and finally, add it to the panner frame */
@@ -428,7 +418,7 @@ PannerUI::build_pan_menu (uint32_t which)
        
        /* set state first, connect second */
 
-       (dynamic_cast<CheckMenuItem*> (&items.back()))->set_active (_io.panner()[which]->muted());
+       (dynamic_cast<CheckMenuItem*> (&items.back()))->set_active (_io->panner()[which]->muted());
        (dynamic_cast<CheckMenuItem*> (&items.back()))->signal_toggled().connect
                (bind (mem_fun(*this, &PannerUI::pan_mute), which));
 
@@ -437,7 +427,7 @@ PannerUI::build_pan_menu (uint32_t which)
 
        /* set state first, connect second */
 
-       bypass_menu_item->set_active (_io.panner().bypassed());
+       bypass_menu_item->set_active (_io->panner().bypassed());
        bypass_menu_item->signal_toggled().connect (mem_fun(*this, &PannerUI::pan_bypass_toggle));
 
        items.push_back (MenuElem (_("Reset"), mem_fun(*this, &PannerUI::pan_reset)));
@@ -448,15 +438,15 @@ PannerUI::build_pan_menu (uint32_t which)
 void
 PannerUI::pan_mute (uint32_t which)
 {
-       StreamPanner* sp = _io.panner()[which];
+       StreamPanner* sp = _io->panner()[which];
        sp->set_muted (!sp->muted());
 }
 
 void
 PannerUI::pan_bypass_toggle ()
 {
-       if (bypass_menu_item && (_io.panner().bypassed() != bypass_menu_item->get_active())) {
-               _io.panner().set_bypassed (!_io.panner().bypassed());
+       if (bypass_menu_item && (_io->panner().bypassed() != bypass_menu_item->get_active())) {
+               _io->panner().set_bypassed (!_io->panner().bypassed());
        }
 }
 
@@ -468,11 +458,11 @@ PannerUI::pan_reset ()
 void
 PannerUI::effective_pan_display ()
 {
-       if (_io.panner().empty()) {
+       if (_io->panner().empty()) {
                return;
        }
 
-       switch (_io.n_outputs()) {
+       switch (_io->n_outputs()) {
        case 0: 
        case 1:
                /* relax */
@@ -495,7 +485,7 @@ PannerUI::pan_changed (void *src)
                return;
        }
 
-       switch (_io.panner().size()) {
+       switch (_io->panner().size()) {
        case 0:
                panning_link_direction_button.set_sensitive (false);
                panning_link_button.set_sensitive (false);
@@ -509,7 +499,7 @@ PannerUI::pan_changed (void *src)
                panning_link_button.set_sensitive (true);
        }
 
-       uint32_t nouts = _io.n_outputs();
+       uint32_t nouts = _io->n_outputs();
 
        switch (nouts) {
        case 0:
@@ -530,11 +520,11 @@ PannerUI::pan_changed (void *src)
 void
 PannerUI::pan_adjustment_changed (uint32_t which)
 {
-       if (!in_pan_update && which < _io.panner().size()) {
+       if (!in_pan_update && which < _io->panner().size()) {
 
                float xpos;
                float val = pan_adjustments[which]->get_value ();
-               _io.panner()[which]->get_position (xpos);
+               _io->panner()[which]->get_position (xpos);
 
                /* add a kinda-sorta detent for the middle */
                
@@ -551,7 +541,7 @@ PannerUI::pan_adjustment_changed (uint32_t which)
                
                if (!Panner::equivalent (val, xpos)) {
 
-                       _io.panner()[which]->set_position (val);
+                       _io->panner()[which]->set_position (val);
                        /* XXX 
                           the panner objects have no access to the session,
                           so do this here. ick.
@@ -566,11 +556,11 @@ PannerUI::pan_value_changed (uint32_t which)
 {
        ENSURE_GUI_THREAD (bind (mem_fun(*this, &PannerUI::pan_value_changed), which));
                                                           
-       if (_io.n_outputs() > 1 && which < _io.panner().size()) {
+       if (_io->n_outputs() > 1 && which < _io->panner().size()) {
                float xpos;
                float val = pan_adjustments[which]->get_value ();
 
-               _io.panner()[which]->get_position (xpos);
+               _io->panner()[which]->get_position (xpos);
 
                if (!Panner::equivalent (val, xpos)) {
                        in_pan_update = true;
@@ -596,14 +586,14 @@ PannerUI::update_pan_bars (bool only_if_aplay)
                float xpos, val;
 
                if (only_if_aplay) {
-                       AutomationList& alist (_io.panner()[n]->automation());
+                       AutomationList& alist (_io->panner()[n]->automation());
                        
                        if (!alist.automation_playback()) {
                                continue;
                        }
                }
 
-               _io.panner()[n]->get_effective_position (xpos);
+               _io->panner()[n]->get_effective_position (xpos);
                val = (*i)->get_value ();
                
                if (!Panner::equivalent (val, xpos)) {
@@ -634,9 +624,9 @@ PannerUI::pan_printer (char *buf, uint32_t len, Adjustment* adj)
 void
 PannerUI::update_pan_sensitive ()
 {
-       bool sensitive = !(_io.panner().automation_state() & Play);
+       bool sensitive = !(_io->panner().automation_state() & Play);
 
-       switch (_io.n_outputs()) {
+       switch (_io->n_outputs()) {
        case 0:
        case 1:
                break;
@@ -697,10 +687,10 @@ PannerUI::pan_automation_style_changed ()
        
        switch (_width) {
        case Wide:
-               pan_automation_style_button.set_label (astyle_string(_io.panner().automation_style()));
+               pan_automation_style_button.set_label (astyle_string(_io->panner().automation_style()));
                break;
        case Narrow:
-               pan_automation_style_button.set_label (short_astyle_string(_io.panner().automation_style()));
+               pan_automation_style_button.set_label (short_astyle_string(_io->panner().automation_style()));
                break;
        }
 }
@@ -714,10 +704,10 @@ PannerUI::pan_automation_state_changed ()
 
        switch (_width) {
        case Wide:
-         pan_automation_state_button.set_label (astate_string(_io.panner().automation_state()));
+         pan_automation_state_button.set_label (astate_string(_io->panner().automation_state()));
                break;
        case Narrow:
-         pan_automation_state_button.set_label (short_astate_string(_io.panner().automation_state()));
+         pan_automation_state_button.set_label (short_astate_string(_io->panner().automation_state()));
                break;
        }
 
@@ -726,11 +716,11 @@ PannerUI::pan_automation_state_changed ()
           here.
        */
 
-       if (_io.panner().empty()) {
+       if (_io->panner().empty()) {
                return;
        }
 
-       x = (_io.panner().front()->automation().automation_state() != Off);
+       x = (_io->panner().front()->automation().automation_state() != Off);
 
        if (pan_automation_state_button.get_active() != x) {
        ignore_toggle = true;
index 80b14465cf0386b70043532347d4c6b6673c0c95..76589782331ea7e4f53ff063291ae765e2117f93 100644 (file)
@@ -31,8 +31,8 @@
 #include <gtkmm/togglebutton.h>
 #include <gtkmm/button.h>
 
-#include <gtkmm2ext/slider_controller.h>
 #include <gtkmm2ext/click_box.h>
+#include <gtkmm2ext/slider_controller.h>
 
 #include "enums.h"
 
@@ -55,7 +55,7 @@ namespace Gtk {
 class PannerUI : public Gtk::HBox
 {
   public:
-       PannerUI (ARDOUR::IO&, ARDOUR::Session&);
+       PannerUI (boost::shared_ptr<ARDOUR::IO>, ARDOUR::Session&);
        ~PannerUI ();
 
        void pan_changed (void *);
@@ -72,7 +72,7 @@ class PannerUI : public Gtk::HBox
 
   private:
        friend class MixerStrip;
-       ARDOUR::IO& _io;
+       boost::shared_ptr<ARDOUR::IO> _io;
        ARDOUR::Session& _session;
 
        bool ignore_toggle;
diff --git a/gtk2_ardour/pixmaps/tool_audition.xpm b/gtk2_ardour/pixmaps/tool_audition.xpm
new file mode 100644 (file)
index 0000000..d6f2ccd
--- /dev/null
@@ -0,0 +1,19 @@
+/* XPM */
+static char * tool_audition_xpm[] = {
+"16 12 4 1",
+"      c None",
+".     c #000000",
+"+     c #ECECEC",
+"@     c #FFFFFF",
+"      ..        ",
+"     .+.    .   ",
+"    .++.   .@.  ",
+"....+@+...  .@. ",
+".+++@@+..@.  .@.",
+".+@@@@+. .@. .@.",
+".+@@@@+. .@. .@.",
+".+++@@+..@.  .@.",
+"....+@+...  .@. ",
+"    .++.   .@.  ",
+"     .+.    .   ",
+"      ..        "};
diff --git a/gtk2_ardour/pixmaps/tool_gain.xpm b/gtk2_ardour/pixmaps/tool_gain.xpm
new file mode 100644 (file)
index 0000000..480426f
--- /dev/null
@@ -0,0 +1,18 @@
+/* XPM */
+static char * tool_gain_xpm[] = {
+"16 12 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFFFFF",
+"...             ",
+".++..           ",
+"...++.          ",
+"   ..+.         ",
+"     .+.        ",
+"     .+.        ",
+"      .+.       ",
+"      .+.       ",
+"       .+..     ",
+"        .++.....",
+"         ..++++.",
+"           ....."};
diff --git a/gtk2_ardour/pixmaps/tool_object.xpm b/gtk2_ardour/pixmaps/tool_object.xpm
new file mode 100644 (file)
index 0000000..3d18ab8
--- /dev/null
@@ -0,0 +1,18 @@
+/* XPM */
+static char * tool_object_xpm[] = {
+"16 12 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFFFFF",
+"     ...        ",
+"     .+.        ",
+"     .+.        ",
+"     .+.        ",
+"     .+.....    ",
+"     .+.+.+...  ",
+"   ...+.+.+.+.  ",
+"   .+.+++++++.  ",
+"   .+++++++++.  ",
+"   ..+++++++..  ",
+"    ...+++++.   ",
+"      .+++++.   "};
diff --git a/gtk2_ardour/pixmaps/tool_range.xpm b/gtk2_ardour/pixmaps/tool_range.xpm
new file mode 100644 (file)
index 0000000..75ee865
--- /dev/null
@@ -0,0 +1,18 @@
+/* XPM */
+static char * tool_range_xpm[] = {
+"16 12 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFFFFF",
+"...          ...",
+".+.  ..  ..  .+.",
+".+. .+.  .+. .+.",
+".+..+.    .+..+.",
+".+.++......++.+.",
+".++++++++++++++.",
+".+.++......++.+.",
+".+..+.    .+..+.",
+".+. .+.  .+. .+.",
+".+.  ..  ..  .+.",
+".+.          .+.",
+"...          ..."};
diff --git a/gtk2_ardour/pixmaps/tool_stretch.xpm b/gtk2_ardour/pixmaps/tool_stretch.xpm
new file mode 100644 (file)
index 0000000..77943cd
--- /dev/null
@@ -0,0 +1,18 @@
+/* XPM */
+static char * tool_stretch_xpm[] = {
+"16 12 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFFFFF",
+"  ..        ..  ",
+" .+.        .+. ",
+".++..........++.",
+"++++++++++++++++",
+".++..........++.",
+" .+.        .+. ",
+"  ..        ..  ",
+" +  +   +    +  ",
+" ++ +++ + + +++ ",
+"++++++++++++++++",
+"  ++  +  ++ + + ",
+"  +   +   +   + "};
diff --git a/gtk2_ardour/pixmaps/tool_zoom.xpm b/gtk2_ardour/pixmaps/tool_zoom.xpm
new file mode 100644 (file)
index 0000000..581363f
--- /dev/null
@@ -0,0 +1,29 @@
+/* XPM */
+static char * tool_zoom_xpm[] = {
+"16 12 14 1",
+"      c None",
+".     c #000000",
+"+     c #474747",
+"@     c #E7E7E7",
+"#     c #F6F6F6",
+"$     c #DCDCDC",
+"%     c #FFFFFF",
+"&     c #DFDFDF",
+"*     c #D7D7D7",
+"=     c #D6D6D6",
+"-     c #040404",
+";     c #070707",
+">     c #060606",
+",     c #050505",
+"     ...        ",
+"   +.@#$.+      ",
+"   .%%%%%.      ",
+"  .&%%%%%*.     ",
+"  .#%%%%%#.     ",
+"  .$%%%%%&.     ",
+"   .%%%%%.+     ",
+"   +.*#=...     ",
+"     ...+...    ",
+"          -.;   ",
+"           >.-  ",
+"            ,.  "};
diff --git a/gtk2_ardour/pixmaps/zoom_full.xpm b/gtk2_ardour/pixmaps/zoom_full.xpm
new file mode 100644 (file)
index 0000000..5564074
--- /dev/null
@@ -0,0 +1,30 @@
+/* XPM */
+static char * zoom_full_xpm[] = {
+"12 12 15 1",
+"      c None",
+".     c #000000",
+"+     c #474747",
+"@     c #E7E7E7",
+"#     c #F6F6F6",
+"$     c #DCDCDC",
+"%     c #ACACAC",
+"&     c #FFFFFF",
+"*     c #DFDFDF",
+"=     c #D7D7D7",
+"-     c #D6D6D6",
+";     c #040404",
+">     c #070707",
+",     c #060606",
+"'     c #050505",
+"   ...      ",
+" +.@#$.+    ",
+" .%&&&%.    ",
+".*..&..=.   ",
+".#.&&&.#.   ",
+".$..&..*.   ",
+" .%&&&%.+   ",
+" +.=#-...   ",
+"   ...+...  ",
+"        ;.> ",
+"         ,.;",
+"          '."};
diff --git a/gtk2_ardour/pixmaps/zoom_in.xpm b/gtk2_ardour/pixmaps/zoom_in.xpm
new file mode 100644 (file)
index 0000000..1f8d4e8
--- /dev/null
@@ -0,0 +1,29 @@
+/* XPM */
+static char * zoom_in_xpm[] = {
+"12 12 14 1",
+"      c None",
+".     c #000000",
+"+     c #474747",
+"@     c #E7E7E7",
+"#     c #F6F6F6",
+"$     c #DCDCDC",
+"%     c #FFFFFF",
+"&     c #DFDFDF",
+"*     c #D7D7D7",
+"=     c #D6D6D6",
+"-     c #040404",
+";     c #070707",
+">     c #060606",
+",     c #050505",
+"   ...      ",
+" +.@#$.+    ",
+" .%%.%%.    ",
+".&%%.%%*.   ",
+".#.....#.   ",
+".$%%.%%&.   ",
+" .%%.%%.+   ",
+" +.*#=...   ",
+"   ...+...  ",
+"        -.; ",
+"         >.-",
+"          ,."};
diff --git a/gtk2_ardour/pixmaps/zoom_out.xpm b/gtk2_ardour/pixmaps/zoom_out.xpm
new file mode 100644 (file)
index 0000000..ea50d14
--- /dev/null
@@ -0,0 +1,29 @@
+/* XPM */
+static char * zoom_out_xpm[] = {
+"12 12 14 1",
+"      c None",
+".     c #000000",
+"+     c #474747",
+"@     c #E7E7E7",
+"#     c #F6F6F6",
+"$     c #DCDCDC",
+"%     c #FFFFFF",
+"&     c #DFDFDF",
+"*     c #D7D7D7",
+"=     c #D6D6D6",
+"-     c #040404",
+";     c #070707",
+">     c #060606",
+",     c #050505",
+"   ...      ",
+" +.@#$.+    ",
+" .%%%%%.    ",
+".&%%%%%*.   ",
+".#.....#.   ",
+".$%%%%%&.   ",
+" .%%%%%.+   ",
+" +.*#=...   ",
+"   ...+...  ",
+"        -.; ",
+"         >.-",
+"          ,."};
index f1a975d5dcf05897850565d0f8bf67860ea03617..8eaac7cb9d3e74814db7bab3523fc1dd3075d03b 100644 (file)
@@ -90,13 +90,13 @@ void
 PlaylistSelector::show_for (RouteUI* ruix)
 {
        vector<const char*> item;
-       AudioDiskstream* this_ds;
+       Diskstream* this_ds;
        string str;
 
        rui = ruix;
 
        str = _("ardour: playlist for ");
-       str += rui->route().name();
+       str += rui->route()->name();
 
        set_title (str);
 
@@ -116,7 +116,7 @@ PlaylistSelector::show_for (RouteUI* ruix)
        
        for (DSPL_Map::iterator x = dspl_map.begin(); x != dspl_map.end(); ++x) {
 
-               AudioDiskstream* ds = session->diskstream_by_id (x->first);
+               Diskstream* ds = session->diskstream_by_id (x->first);
 
                if (ds == 0) {
                        continue;
@@ -189,7 +189,7 @@ PlaylistSelector::add_playlist_to_map (Playlist *pl)
 
        if ((x = dspl_map.find (apl->get_orig_diskstream_id())) == dspl_map.end()) {
 
-               pair<ARDOUR::id_t,list<Playlist*>*> newp (apl->get_orig_diskstream_id(), new list<Playlist*>);
+               pair<PBD::ID,list<Playlist*>*> newp (apl->get_orig_diskstream_id(), new list<Playlist*>);
                
                x = dspl_map.insert (dspl_map.end(), newp);
        }
@@ -223,7 +223,7 @@ PlaylistSelector::selection_changed ()
 
        TreeModel::iterator iter = tree.get_selection()->get_selected();
 
-       if (!iter) {
+       if (!iter || rui == 0) {
                /* nothing selected */
                return;
        }
@@ -233,7 +233,7 @@ PlaylistSelector::selection_changed ()
                AudioTrack* at;
                AudioPlaylist* apl;
                
-               if ((at = dynamic_cast<AudioTrack*> (&rui->route())) == 0) {
+               if ((at = rui->audio_track()) == 0) {
                        /* eh? */
                        return;
                }
@@ -243,7 +243,7 @@ PlaylistSelector::selection_changed ()
                        return;
                }
                
-               at->disk_stream().use_playlist (apl);
+               at->diskstream().use_playlist (apl);
 
                hide ();
        }
index 863d6cc7f31e4a821f7f0b8830880deff47e2514..2829ba54bbc921550de08796cf67ad40e67e7e11 100644 (file)
@@ -46,7 +46,7 @@ class PlaylistSelector : public ArdourDialog
        void show_for (RouteUI*);
 
   private:
-       typedef std::map<ARDOUR::id_t,std::list<ARDOUR::Playlist*>*> DSPL_Map;
+       typedef std::map<PBD::ID,std::list<ARDOUR::Playlist*>*> DSPL_Map;
 
        ARDOUR::Session* session;
        Gtk::ScrolledWindow scroller;
index 16796df160df608cc7b77c59a99acacdac82c293..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,8 @@ PluginSelector::PluginSelector (PluginManager *mgr)
 
        manager = mgr;
        session = 0;
-       o_selected_plug = -1;
-       i_selected_plug = 0;
+       
+       current_selection = PluginInfo::LADSPA;
 
        lmodel = Gtk::ListStore::create(lcols);
        ladspa_display.set_model (lmodel);
@@ -91,6 +91,25 @@ PluginSelector::PluginSelector (PluginManager *mgr)
                column->set_sort_column(i);
        }
 #endif
+
+#ifdef HAVE_COREAUDIO
+       aumodel = ListStore::create(aucols);
+       au_display.set_model (aumodel);
+       au_display.append_column (_("Available plugins"), aucols.name);
+       au_display.append_column (_("# Inputs"), aucols.ins);
+       au_display.append_column (_("# Outputs"), aucols.outs);
+       au_display.set_headers_visible (true);
+       au_display.set_reorderable (false);
+       auscroller.set_border_width(10);
+       auscroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+       auscroller.add(au_display);
+
+       for (int i = 0; i <=2; i++) {
+               Gtk::TreeView::Column* column = au_display.get_column(i);
+               column->set_sort_column(i);
+       }
+#endif
+
        ascroller.set_border_width(10);
        ascroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
        ascroller.add(added_list);
@@ -124,35 +143,51 @@ PluginSelector::PluginSelector (PluginManager *mgr)
 
        using namespace Gtk::Notebook_Helpers;
        notebook.pages().push_back (TabElem (lscroller, _("LADSPA")));
+
 #ifdef VST_SUPPORT
        if (Config->get_use_vst()) {
                notebook.pages().push_back (TabElem (vscroller, _("VST")));
        }
 #endif
 
+#ifdef HAVE_COREAUDIO
+       notebook.pages().push_back (TabElem (auscroller, _("AudioUnit")));
+#endif
+
        table->set_name("PluginSelectorTable");
        ladspa_display.set_name("PluginSelectorDisplay");
        //ladspa_display.set_name("PluginSelectorList");
        added_list.set_name("PluginSelectorList");
 
        ladspa_display.signal_button_press_event().connect_notify (mem_fun(*this, &PluginSelector::row_clicked));
+       ladspa_display.get_selection()->signal_changed().connect (mem_fun(*this, &PluginSelector::ladspa_display_selection_changed));
+       
 #ifdef VST_SUPPORT
        if (Config->get_use_vst()) {
                vst_display.signal_button_press_event().connect_notify (mem_fun(*this, &PluginSelector::row_clicked));
                vst_display.get_selection()->signal_changed().connect (mem_fun(*this, &PluginSelector::vst_display_selection_changed));
        }
 #endif
-       
+
+#ifdef HAVE_COREAUDIO
+       au_display.signal_button_press_event().connect_notify (mem_fun(*this, &PluginSelector::row_clicked));
+       au_display.get_selection()->signal_changed().connect (mem_fun(*this, &PluginSelector::au_display_selection_changed));
+#endif
+
        btn_update->signal_clicked().connect (mem_fun(*this, &PluginSelector::btn_update_clicked));
        btn_add->signal_clicked().connect(mem_fun(*this, &PluginSelector::btn_add_clicked));
        btn_remove->signal_clicked().connect(mem_fun(*this, &PluginSelector::btn_remove_clicked));
-       ladspa_display.get_selection()->signal_changed().connect (mem_fun(*this, &PluginSelector::ladspa_display_selection_changed));
        added_list.get_selection()->signal_changed().connect (mem_fun(*this, &PluginSelector::added_list_selection_changed));
 
        input_refiller ();
+       
 #ifdef VST_SUPPORT
        vst_refiller ();
 #endif
+
+#ifdef HAVE_COREAUDIO
+       au_refiller ();
+#endif
 }
 
 void
@@ -189,13 +224,11 @@ void
 PluginSelector::input_refiller ()
 {
        guint row;
-       list<PluginInfo *> &plugs = manager->ladspa_plugin_info ();
-       list<PluginInfo *>::iterator i;
+       PluginInfoList &plugs = manager->ladspa_plugin_info ();
+       PluginInfoList::iterator i;
        char ibuf[16], obuf[16];
        lmodel->clear();
-#ifdef VST_SUPPORT
-       vmodel->clear();
-#endif
+
        // Insert into GTK list
        for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) {
                snprintf (ibuf, sizeof(ibuf)-1, "%d", (*i)->n_inputs);
@@ -224,9 +257,10 @@ void
 PluginSelector::vst_refiller ()
 {
        guint row;
-       list<PluginInfo *> &plugs = manager->vst_plugin_info ();
-       list<PluginInfo *>::iterator i;
+       PluginInfoList &plugs = manager->vst_plugin_info ();
+       PluginInfoList::iterator i;
        char ibuf[16], obuf[16];
+       vmodel->clear();
        
        // Insert into GTK list
        for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) {
@@ -242,18 +276,75 @@ PluginSelector::vst_refiller ()
        }
        vmodel->set_sort_column (0, Gtk::SORT_ASCENDING);
 }
-#endif
 
 void
-PluginSelector::use_plugin (PluginInfo* pi)
+PluginSelector::vst_display_selection_changed()
 {
-       list<PluginInfo *>::iterator i;
+       if (vst_display.get_selection()->count_selected_rows() != 0) {
+               btn_add->set_sensitive (true);
+       } else {
+               btn_add->set_sensitive (false);
+       }
+
+       current_selection = PluginInfo::VST;
+}
+
+#endif //VST_SUPPORT
 
-       if (pi == 0 || session == 0) {
+#ifdef HAVE_COREAUDIO
+
+void
+PluginSelector::_au_refiller (void *arg)
+{
+       ((PluginSelector *) arg)->au_refiller ();
+}
+
+void
+PluginSelector::au_refiller ()
+{
+       guint row;
+       PluginInfoList plugs (AUPluginInfo::discover ());
+       PluginInfoList::iterator i;
+       char ibuf[16], obuf[16];
+       aumodel->clear();
+       
+       // Insert into GTK list
+       for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) {
+
+               snprintf (ibuf, sizeof(ibuf)-1, "%d", (*i)->n_inputs);
+               snprintf (obuf, sizeof(obuf)-1, "%d", (*i)->n_outputs);         
+               
+               Gtk::TreeModel::Row newrow = *(aumodel->append());
+               newrow[aucols.name] = (*i)->name.c_str();
+               newrow[aucols.ins] = ibuf;
+               newrow[aucols.outs] = obuf;
+               newrow[aucols.plugin] = *i;
+       }
+       aumodel->set_sort_column (0, Gtk::SORT_ASCENDING);
+}
+
+void
+PluginSelector::au_display_selection_changed()
+{
+       if (au_display.get_selection()->count_selected_rows() != 0) {
+               btn_add->set_sensitive (true);
+       } else {
+               btn_add->set_sensitive (false);
+       }
+       
+       current_selection = PluginInfo::AudioUnit;
+}
+
+#endif //HAVE_COREAUDIO
+
+void
+PluginSelector::use_plugin (PluginInfoPtr pi)
+{
+       if (session == 0) {
                return;
        }
 
-       Plugin *plugin = manager->load (*session, pi);
+       PluginPtr plugin = pi->load (*session);
 
        if (plugin) {
                PluginCreated (plugin);
@@ -263,46 +354,54 @@ PluginSelector::use_plugin (PluginInfo* pi)
 void
 PluginSelector::btn_add_clicked()
 {
-       bool vst = notebook.get_current_page(); // 0 = LADSPA, 1 = VST
        std::string name;
-       ARDOUR::PluginInfo *pi;
+       PluginInfoPtr pi;
        Gtk::TreeModel::Row newrow = *(amodel->append());
        
-       if (vst) {
+       Gtk::TreeModel::Row row;
+
+       switch (current_selection) {
+               case PluginInfo::LADSPA:
+                       row = *(ladspa_display.get_selection()->get_selected());
+                       name = row[lcols.name];
+                       pi = row[lcols.plugin];
+                       break;
+               case PluginInfo::VST:
 #ifdef VST_SUPPORT
-               Gtk::TreeModel::Row row = *(vst_display.get_selection()->get_selected());
-               name = row[vcols.name];
-               pi = row[vcols.plugin];
-               added_plugins.push_back (row[vcols.plugin]);
+                       row = *(vst_display.get_selection()->get_selected());
+                       name = row[vcols.name];
+                       pi = row[vcols.plugin];
 #endif
-       } else {
-               Gtk::TreeModel::Row row = *(ladspa_display.get_selection()->get_selected());
-               name = row[lcols.name];
-               pi = row[lcols.plugin];
-               added_plugins.push_back (row[lcols.plugin]);
+                       break;
+               case PluginInfo::AudioUnit:
+#ifdef HAVE_COREAUDIO
+                       row = *(au_display.get_selection()->get_selected());
+                       name = row[aucols.name];
+                       pi = row[aucols.plugin];
+#endif
+                       break;
+               default:
+                       error << "Programming error.  Unknown plugin selected." << endmsg;
+                       return;
        }
+
        newrow[acols.text] = name;
        newrow[acols.plugin] = pi;
 
        if (!amodel->children().empty()) {
-         set_response_sensitive (RESPONSE_APPLY, true);
+               set_response_sensitive (RESPONSE_APPLY, true);
        }
 }
 
 void
 PluginSelector::btn_remove_clicked()
 {
-       list<PluginInfo*>::iterator i;
        Gtk::TreeModel::iterator iter = added_list.get_selection()->get_selected();
-       for (i = added_plugins.begin(); (*i) != (*iter)[acols.plugin]; ++i);
-
-       added_plugins.erase(i); 
+       
        amodel->erase(iter);
        if (amodel->children().empty()) {
-         set_response_sensitive (RESPONSE_APPLY, false);
+               set_response_sensitive (RESPONSE_APPLY, false);
        }
-
-
 }
 
 void
@@ -313,28 +412,21 @@ PluginSelector::btn_update_clicked()
 #ifdef VST_SUPPORT
        vst_refiller ();
 #endif 
-}
-
-#ifdef VST_SUPPORT
-void
-PluginSelector::vst_display_selection_changed()
-{
-  if (vst_display.get_selection()->count_selected_rows() != 0) {
-    btn_add->set_sensitive (true);
-  } else {
-    btn_add->set_sensitive (false);
-  }
-}
+#ifdef HAVE_COREAUDIO
+       au_refiller ();
 #endif
+}
 
 void
 PluginSelector::ladspa_display_selection_changed()
 {
-  if (ladspa_display.get_selection()->count_selected_rows() != 0) {
-    btn_add->set_sensitive (true);
-  } else {
-    btn_add->set_sensitive (false);
-  }
+       if (ladspa_display.get_selection()->count_selected_rows() != 0) {
+               btn_add->set_sensitive (true);
+       } else {
+               btn_add->set_sensitive (false);
+       }
+       
+       current_selection = PluginInfo::LADSPA;
 }
 
 void
@@ -351,14 +443,14 @@ int
 PluginSelector::run ()
 {
        ResponseType r;
-       list<PluginInfo*>::iterator i;
+       TreeModel::Children::iterator i;
 
        r = (ResponseType) Dialog::run ();
 
        switch (r) {
        case RESPONSE_APPLY:
-               for (i = added_plugins.begin(); i != added_plugins.end(); ++i){
-                       use_plugin (*i);
+               for (i = amodel->children().begin(); i != amodel->children().end(); ++i) {
+                       use_plugin ((*i)[acols.plugin]);
                }
                break;
 
@@ -375,7 +467,5 @@ void
 PluginSelector::cleanup ()
 {
        hide();
-       added_plugins.clear();
        amodel->clear();
 }
-
index 125ce1b80ad84422bcf7b47f62bd6b7946cd3701..583506972a896b80b9f6d26c0b08957895f80214 100644 (file)
 #include <gtkmm/treeview.h>
 #include <gtkmm2ext/selector.h>
 
+#include <ardour/plugin.h>
+
 namespace ARDOUR {
        class Session;
        class PluginManager;
-       class Plugin;
 }
 
 class PluginSelector : public ArdourDialog
 {
   public:
        PluginSelector (ARDOUR::PluginManager *);
-       sigc::signal<void,ARDOUR::Plugin *> PluginCreated;
+       sigc::signal<void,boost::shared_ptr<ARDOUR::Plugin> > PluginCreated;
 
        int run (); // XXX should we try not to overload the non-virtual Gtk::Dialog::run() ?
 
@@ -44,9 +45,12 @@ class PluginSelector : public ArdourDialog
   private:
        ARDOUR::Session* session;
        Gtk::Notebook notebook;
-       Gtk::ScrolledWindow lscroller;
-       Gtk::ScrolledWindow vscroller;
-       Gtk::ScrolledWindow ascroller;
+       Gtk::ScrolledWindow lscroller;  // ladspa
+       Gtk::ScrolledWindow vscroller;  // vst
+       Gtk::ScrolledWindow auscroller; // AudioUnit
+       Gtk::ScrolledWindow ascroller;  // Added plugins
+       
+       ARDOUR::PluginInfo::Type current_selection;
 
        // page 1
        struct LadspaColumns : public Gtk::TreeModel::ColumnRecord {
@@ -61,7 +65,7 @@ class PluginSelector : public ArdourDialog
                Gtk::TreeModelColumn<std::string> type;
                Gtk::TreeModelColumn<std::string> ins;
                Gtk::TreeModelColumn<std::string> outs;
-           Gtk::TreeModelColumn<ARDOUR::PluginInfo *> plugin;
+           Gtk::TreeModelColumn<ARDOUR::PluginInfoPtr> plugin;
        };
        LadspaColumns lcols;
        Glib::RefPtr<Gtk::ListStore> lmodel;
@@ -76,7 +80,7 @@ class PluginSelector : public ArdourDialog
                        add (plugin);
                }
                Gtk::TreeModelColumn<std::string> text;
-               Gtk::TreeModelColumn<ARDOUR::PluginInfo *> plugin;
+               Gtk::TreeModelColumn<ARDOUR::PluginInfoPtr> plugin;
        };
        AddedColumns acols;
        Glib::RefPtr<Gtk::ListStore> amodel;
@@ -95,7 +99,7 @@ class PluginSelector : public ArdourDialog
            Gtk::TreeModelColumn<std::string> name;
                Gtk::TreeModelColumn<std::string> ins;
                Gtk::TreeModelColumn<std::string> outs;
-           Gtk::TreeModelColumn<ARDOUR::PluginInfo *> plugin;
+           Gtk::TreeModelColumn<ARDOUR::PluginInfoPtr> plugin;
        };
        VstColumns vcols;
        Glib::RefPtr<Gtk::ListStore> vmodel;
@@ -104,16 +108,32 @@ class PluginSelector : public ArdourDialog
        static void _vst_refiller (void *);
        void vst_refiller ();
        void vst_display_selection_changed();
-#endif 
-
-       ARDOUR::PluginInfo* i_selected_plug;
+#endif // VST_SUPPORT
 
-       // We need an integer for the output side because
-       // the name isn't promised to be unique.
-       gint o_selected_plug;
+#ifdef HAVE_COREAUDIO
+       // page 3
+       struct AUColumns : public Gtk::TreeModel::ColumnRecord {
+               AUColumns () {
+                       add (name);
+                       add (ins);
+                       add (outs);
+                       add (plugin);
+               }
+               Gtk::TreeModelColumn<std::string> name;
+               Gtk::TreeModelColumn<std::string> ins;
+               Gtk::TreeModelColumn<std::string> outs;
+               Gtk::TreeModelColumn<ARDOUR::PluginInfoPtr> plugin;
+       };
+       AUColumns aucols;
+       Glib::RefPtr<Gtk::ListStore> aumodel;
+       Glib::RefPtr<Gtk::TreeSelection> auselection;
+       Gtk::TreeView au_display;
+       static void _au_refiller (void *);
+       void au_refiller ();
+       void au_display_selection_changed();
+#endif //HAVE_COREAUDIO
 
        ARDOUR::PluginManager *manager;
-       list<ARDOUR::PluginInfo*> added_plugins;
 
        static void _input_refiller (void *);
        
@@ -125,8 +145,9 @@ class PluginSelector : public ArdourDialog
        void added_list_selection_changed();
        void ladspa_display_selection_changed();
        void btn_apply_clicked();
-       void use_plugin (ARDOUR::PluginInfo*);
+       void use_plugin (ARDOUR::PluginInfoPtr);
        void cleanup ();
 };
 
 #endif // __ardour_plugin_selector_h__
+
index 749ab9d4ac76a8d372cc0c08da19b66c9c95e1b8..5e5263b9ad3ce97da44016a86295f73f09b724dd 100644 (file)
 
 #include <gtkmm2ext/click_box.h>
 #include <gtkmm2ext/fastmeter.h>
-#include <gtkmm2ext/slider_controller.h>
 #include <gtkmm2ext/barcontroller.h>
 #include <gtkmm2ext/utils.h>
 #include <gtkmm2ext/doi.h>
+#include <gtkmm2ext/slider_controller.h>
 
 #include <midi++/manager.h>
 
@@ -61,19 +61,19 @@ using namespace Gtkmm2ext;
 using namespace Gtk;
 using namespace sigc;
 
-PluginUIWindow::PluginUIWindow (AudioEngine &engine, PluginInsert& insert, bool scrollable)
+PluginUIWindow::PluginUIWindow (AudioEngine &engine, boost::shared_ptr<PluginInsert> insert, bool scrollable)
        : ArdourDialog ("plugin ui")
 {
-       if (insert.plugin().has_editor()) {
+       if (insert->plugin()->has_editor()) {
 
 #ifdef VST_SUPPORT
 
-               VSTPlugin* vp;
+               boost::shared_ptr<VSTPlugin> vp;
 
-               if ((vp = dynamic_cast<VSTPlugin*> (&insert.plugin())) != 0) {
+               if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (insert->plugin())) != 0) {
                        
                        
-                       VSTPluginUI* vpu = new VSTPluginUI (insert, *vp);
+                       VSTPluginUI* vpu = new VSTPluginUI (insert, vp);
                        
                        _pluginui = vpu;
                        get_vbox()->add (*vpu);
@@ -104,7 +104,7 @@ PluginUIWindow::PluginUIWindow (AudioEngine &engine, PluginInsert& insert, bool
        add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
 
        signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), reinterpret_cast<Window*> (this)));
-       insert.GoingAway.connect (mem_fun(*this, &PluginUIWindow::plugin_going_away));
+       insert->GoingAway.connect (mem_fun(*this, &PluginUIWindow::plugin_going_away));
 
        if (scrollable) {
                gint h = _pluginui->get_preferred_height ();
@@ -117,7 +117,7 @@ PluginUIWindow::~PluginUIWindow ()
 {
 }
 
-PluginUI::PluginUI (AudioEngine &engine, PluginInsert& pi, bool scrollable)
+PluginUI::PluginUI (AudioEngine &engine, boost::shared_ptr<PluginInsert> pi, bool scrollable)
        : PlugUIBase (pi),
          engine(engine),
          button_table (initial_button_rows, initial_button_cols),
@@ -165,8 +165,8 @@ PluginUI::PluginUI (AudioEngine &engine, PluginInsert& pi, bool scrollable)
                pack_start (hpacker, false, false);
        }
 
-       insert.active_changed.connect (mem_fun(*this, &PluginUI::redirect_active_changed));
-       bypass_button.set_active (!insert.active());
+       insert->active_changed.connect (mem_fun(*this, &PluginUI::redirect_active_changed));
+       bypass_button.set_active (!insert->active());
        
        build (engine);
 }
@@ -233,13 +233,13 @@ PluginUI::build (AudioEngine &engine)
 
        /* find all ports. build control elements for all appropriate control ports */
 
-       for (i = 0; i < plugin.parameter_count(); ++i) {
+       for (i = 0; i < plugin->parameter_count(); ++i) {
 
-               if (plugin.parameter_is_control (i)) {
+               if (plugin->parameter_is_control (i)) {
                        
                        /* Don't show latency control ports */
 
-                       if (plugin.describe_parameter (i) == X_("latency")) {
+                       if (plugin->describe_parameter (i) == X_("latency")) {
                                continue;
                        }
 
@@ -263,7 +263,7 @@ PluginUI::build (AudioEngine &engine)
                                }
                        }
 
-                       if ((cui = build_control_ui (engine, i, plugin.get_nth_midi_control (i))) == 0) {
+                       if ((cui = build_control_ui (engine, i, plugin->get_nth_control (i))) == 0) {
                                error << string_compose(_("Plugin Editor: could not build control element for port %1"), i) << endmsg;
                                continue;
                        }
@@ -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);
@@ -387,7 +387,7 @@ PluginUI::automation_state_changed (ControlUI* cui)
 {
        /* update button label */
 
-       switch (insert.get_port_automation_state (cui->port_index) & (Off|Play|Touch|Write)) {
+       switch (insert->get_port_automation_state (cui->port_index) & (Off|Play|Touch|Write)) {
        case Off:
                cui->automate_button.set_label (_("Off"));
                break;
@@ -415,17 +415,17 @@ static void integer_printer (char buf[32], Adjustment &adj, void *arg)
 void
 PluginUI::print_parameter (char *buf, uint32_t len, uint32_t param)
 {
-       plugin.print_parameter (param, buf, len);
+       plugin->print_parameter (param, buf, len);
 }
 
 PluginUI::ControlUI*
-PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, MIDI::Controllable* mcontrol)
+PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, PBD::Controllable* mcontrol)
 
 {
        ControlUI* control_ui;
        Plugin::ParameterDescriptor desc;
 
-       plugin.get_parameter_descriptor (port_index, desc);
+       plugin->get_parameter_descriptor (port_index, desc);
 
        control_ui = manage (new ControlUI ());
        control_ui->adjustment = 0;
@@ -439,11 +439,11 @@ PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, MIDI::Contr
 
        control_ui->set_spacing (5);
 
-       if (plugin.parameter_is_input (port_index)) {
+       if (plugin->parameter_is_input (port_index)) {
 
-               LadspaPlugin* lp;
+               boost::shared_ptr<LadspaPlugin> lp;
 
-               if ((lp = dynamic_cast<LadspaPlugin*>(&plugin)) != 0) {
+               if ((lp = boost::dynamic_pointer_cast<LadspaPlugin>(plugin)) != 0) {
                        
                        lrdf_defaults* defaults = lrdf_get_scale_values(lp->unique_id(), port_index);
                        
@@ -453,7 +453,7 @@ PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, MIDI::Contr
                                //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));
+                               plugin->ParameterChanged.connect (bind (mem_fun (*this, &PluginUI::parameter_changed), control_ui));
                                control_ui->pack_start(control_ui->label, true, true);
                                control_ui->pack_start(*control_ui->combo, false, true);
                                
@@ -478,7 +478,7 @@ PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, MIDI::Contr
 
                        control_ui->button->signal_clicked().connect (bind (mem_fun(*this, &PluginUI::control_port_toggled), control_ui));
                
-                       if(plugin.get_parameter (port_index) == 1){
+                       if(plugin->get_parameter (port_index) == 1){
                                control_ui->button->set_active(true);
                        }
 
@@ -516,7 +516,7 @@ PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, MIDI::Contr
                } else {
                        sigc::slot<void,char*,uint32_t> pslot = sigc::bind (mem_fun(*this, &PluginUI::print_parameter), (uint32_t) port_index);
 
-                       control_ui->control = new BarController (*control_ui->adjustment, mcontrol, pslot);
+                       control_ui->control = new BarController (*control_ui->adjustment, *mcontrol, pslot);
                        // should really match the height of the text in the automation button+label
                        control_ui->control->set_size_request (200, 22);
                        control_ui->control->set_name (X_("PluginSlider"));
@@ -529,9 +529,9 @@ PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, MIDI::Contr
                }
 
                if (control_ui->logarithmic) {
-                       control_ui->adjustment->set_value(log(plugin.get_parameter(port_index)));
+                       control_ui->adjustment->set_value(log(plugin->get_parameter(port_index)));
                } else{
-                       control_ui->adjustment->set_value(plugin.get_parameter(port_index));
+                       control_ui->adjustment->set_value(plugin->get_parameter(port_index));
                }
 
                /* XXX memory leak: SliderController not destroyed by ControlUI
@@ -552,11 +552,11 @@ PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, MIDI::Contr
 
                automation_state_changed (control_ui);
 
-               plugin.ParameterChanged.connect (bind (mem_fun(*this, &PluginUI::parameter_changed), control_ui));
-               insert.automation_list (port_index).automation_state_changed.connect 
+               plugin->ParameterChanged.connect (bind (mem_fun(*this, &PluginUI::parameter_changed), control_ui));
+               insert->automation_list (port_index).automation_state_changed.connect 
                        (bind (mem_fun(*this, &PluginUI::automation_state_changed), control_ui));
 
-       } else if (plugin.parameter_is_output (port_index)) {
+       } else if (plugin->parameter_is_output (port_index)) {
 
                control_ui->display = manage (new EventBox);
                control_ui->display->set_name ("ParameterValueDisplay");
@@ -603,20 +603,20 @@ PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, MIDI::Contr
                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, &PluginUI::parameter_changed), control_ui));
        return control_ui;
 }
 
 void
 PluginUI::start_touch (PluginUI::ControlUI* cui)
 {
-       insert.automation_list (cui->port_index).start_touch ();
+       insert->automation_list (cui->port_index).start_touch ();
 }
 
 void
 PluginUI::stop_touch (PluginUI::ControlUI* cui)
 {
-       insert.automation_list (cui->port_index).stop_touch ();
+       insert->automation_list (cui->port_index).stop_touch ();
 }
 
 void
@@ -647,7 +647,7 @@ PluginUI::astate_clicked (ControlUI* cui, uint32_t port)
 void
 PluginUI::set_automation_state (AutoState state, ControlUI* cui)
 {
-       insert.set_port_automation_state (cui->port_index, state);
+       insert->set_port_automation_state (cui->port_index, state);
 }
 
 void
@@ -663,7 +663,7 @@ PluginUI::control_adjustment_changed (ControlUI* cui)
                value = exp(value);
        }
 
-       insert.set_parameter (cui->port_index, (float) value);
+       insert->set_parameter (cui->port_index, (float) value);
 }
 
 void
@@ -684,7 +684,7 @@ PluginUI::update_control_display (ControlUI* cui)
        
        cui->update_pending = false;
 
-       float val = plugin.get_parameter (cui->port_index);
+       float val = plugin->get_parameter (cui->port_index);
 
        cui->ignore_change++;
        if (cui->combo) {
@@ -718,7 +718,7 @@ void
 PluginUI::control_port_toggled (ControlUI* cui)
 {
        if (!cui->ignore_change) {
-               insert.set_parameter (cui->port_index, cui->button->get_active());
+               insert->set_parameter (cui->port_index, cui->button->get_active());
        }
 }
 
@@ -728,7 +728,7 @@ PluginUI::control_combo_changed (ControlUI* cui)
        if (!cui->ignore_change) {
                string value = cui->combo->get_active_text();
                std::map<string,float> mapping = *cui->combo_map;
-               insert.set_parameter (cui->port_index, mapping[value]);
+               insert->set_parameter (cui->port_index, mapping[value]);
        }
 
 }
@@ -774,7 +774,7 @@ void
 PluginUI::output_update ()
 {
        for (vector<ControlUI*>::iterator i = output_controls.begin(); i != output_controls.end(); ++i) {
-               float val = plugin.get_parameter ((*i)->port_index);
+               float val = plugin->get_parameter ((*i)->port_index);
                char buf[32];
                snprintf (buf, sizeof(buf), "%.2f", val);
                (*i)->display_label->set_text (buf);
@@ -808,7 +808,7 @@ vector<string>
 PluginUI::setup_scale_values(guint32 port_index, ControlUI* cui)
 {
        vector<string> enums;
-       LadspaPlugin* lp = dynamic_cast<LadspaPlugin*> (&plugin);
+       boost::shared_ptr<LadspaPlugin> lp = boost::dynamic_pointer_cast<LadspaPlugin> (plugin);
 
        cui->combo_map = new std::map<string, float>;
        lrdf_defaults* defaults = lrdf_get_scale_values(lp->unique_id(), port_index);
@@ -827,14 +827,14 @@ PluginUI::setup_scale_values(guint32 port_index, ControlUI* cui)
        return enums;
 }
 
-PlugUIBase::PlugUIBase (PluginInsert& pi)
+PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
        : insert (pi),
-         plugin (insert.plugin()),
+         plugin (insert->plugin()),
          save_button(_("Add")),
          bypass_button (_("Bypass"))
 {
         //combo.set_use_arrows_always(true);
-       set_popdown_strings (combo, plugin.get_presets());
+       set_popdown_strings (combo, plugin->get_presets());
        combo.set_size_request (100, -1);
        combo.set_active_text ("");
        combo.signal_changed().connect(mem_fun(*this, &PlugUIBase::setting_selected));
@@ -850,7 +850,7 @@ void
 PlugUIBase::setting_selected()
 {
        if (combo.get_active_text().length() > 0) {
-               if (!plugin.load_preset(combo.get_active_text())) {
+               if (!plugin->load_preset(combo.get_active_text())) {
                        warning << string_compose(_("Plugin preset %1 not found"), combo.get_active_text()) << endmsg;
                }
        }
@@ -875,8 +875,8 @@ PlugUIBase::save_plugin_setting ()
                prompter.get_result(name);
 
                if (name.length()) {
-                       if(plugin.save_preset(name)){
-                               set_popdown_strings (combo, plugin.get_presets());
+                       if(plugin->save_preset(name)){
+                               set_popdown_strings (combo, plugin->get_presets());
                                combo.set_active_text (name);
                        }
                }
@@ -889,8 +889,8 @@ PlugUIBase::bypass_toggled ()
 {
        bool x;
 
-       if ((x = bypass_button.get_active()) == insert.active()) {
-               insert.set_active (!x, this);
+       if ((x = bypass_button.get_active()) == insert->active()) {
+               insert->set_active (!x, this);
        }
 }
 
index e5800e8ece3ba2ea7514d4acb1471ec01d4f979f..570a224b66d5baf61320b2c4db18b56c30d167f7 100644 (file)
@@ -52,7 +52,7 @@ namespace ARDOUR {
        class Redirect;
 }
 
-namespace MIDI {
+namespace PBD {
        class Controllable;
 }
 
@@ -67,7 +67,7 @@ namespace Gtkmm2ext {
 class PlugUIBase : public virtual sigc::trackable
 {
   public:
-       PlugUIBase (ARDOUR::PluginInsert&);
+       PlugUIBase (boost::shared_ptr<ARDOUR::PluginInsert>);
        virtual ~PlugUIBase() {}
 
        virtual gint get_preferred_height () = 0;
@@ -75,8 +75,8 @@ class PlugUIBase : public virtual sigc::trackable
        virtual bool stop_updating(GdkEventAny*) = 0;
 
   protected:
-       ARDOUR::PluginInsert& insert;
-       ARDOUR::Plugin& plugin;
+       boost::shared_ptr<ARDOUR::PluginInsert> insert;
+       boost::shared_ptr<ARDOUR::Plugin> plugin;
        Gtk::ComboBoxText combo;
        Gtk::Button save_button;
        Gtk::ToggleButton bypass_button;
@@ -89,7 +89,7 @@ class PlugUIBase : public virtual sigc::trackable
 class PluginUI : public PlugUIBase, public Gtk::VBox 
 {
   public:
-       PluginUI (ARDOUR::AudioEngine &, ARDOUR::PluginInsert& plug, bool scrollable=false);
+       PluginUI (ARDOUR::AudioEngine &, boost::shared_ptr<ARDOUR::PluginInsert> plug, bool scrollable=false);
        ~PluginUI ();
        
        gint get_preferred_height () { return prefheight; }
@@ -174,7 +174,7 @@ class PluginUI : public PlugUIBase, public Gtk::VBox
        void output_update();
        
        void build (ARDOUR::AudioEngine &);
-       ControlUI* build_control_ui (ARDOUR::AudioEngine &, guint32 port_index, MIDI::Controllable *);
+       ControlUI* build_control_ui (ARDOUR::AudioEngine &, guint32 port_index, PBD::Controllable *);
        std::vector<string> setup_scale_values(guint32 port_index, ControlUI* cui);
        void control_adjustment_changed (ControlUI* cui);
        void parameter_changed (uint32_t, float, ControlUI* cui);
@@ -196,7 +196,7 @@ class PluginUI : public PlugUIBase, public Gtk::VBox
 class PluginUIWindow : public ArdourDialog
 {
   public:
-       PluginUIWindow (ARDOUR::AudioEngine &, ARDOUR::PluginInsert& insert, bool scrollable=false);
+       PluginUIWindow (ARDOUR::AudioEngine &, boost::shared_ptr<ARDOUR::PluginInsert> insert, bool scrollable=false);
        ~PluginUIWindow ();
 
        PlugUIBase& pluginui() { return *_pluginui; }
@@ -213,7 +213,7 @@ class PluginUIWindow : public ArdourDialog
 class VSTPluginUI : public PlugUIBase, public Gtk::VBox
 {
   public:
-       VSTPluginUI (ARDOUR::PluginInsert&, ARDOUR::VSTPlugin&);
+       VSTPluginUI (boost::shared_ptr<ARDOUR::PluginInsert>, boost::shared_ptr<ARDOUR::VSTPlugin>);
        ~VSTPluginUI ();
 
        gint get_preferred_height ();
@@ -223,7 +223,7 @@ class VSTPluginUI : public PlugUIBase, public Gtk::VBox
        int package (Gtk::Window&);
 
   private:
-       ARDOUR::VSTPlugin&  vst;
+       boost::shared_ptr<ARDOUR::VSTPlugin>  vst;
        Gtk::Socket socket;
        Gtk::HBox   preset_box;
        Gtk::VBox   vpacker;
index 868f123988bc0fa564b669987cff97aff5ad7544..d7e957b3eb3e544edb1f3d61c3c99bfc6dab8712 100644 (file)
@@ -27,7 +27,7 @@ print "Updating pot file: "
 domain = gtkardour['DOMAIN']
 potfile = gtkardour['POTFILE']
 
-poaction = Action('intltool-update -p -g=' + domain)
+poaction = env.Action('intltool-update -p -g=' + domain)
 
 Execute(poaction)
 
index 4c12b99d7c64ee6c1edbf3fc9d6d86968bd49cbb..f70e4c20bd5ee163f2bbf7ea2ccfe581d21194bc 100644 (file)
@@ -39,7 +39,7 @@ class AutomationLine;
 class ControlPoint;
 class SelectionRect;
 class CrossfadeView;
-class AudioTimeAxisView;
+class RouteTimeAxisView;
 class AudioRegionView;
 class TempoMarker;
 class MeterMarker;
@@ -145,10 +145,10 @@ class PublicEditor : public Gtk::Window, public Stateful {
        virtual bool canvas_fade_in_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0;
        virtual bool canvas_fade_out_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0;
        virtual bool canvas_fade_out_handle_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0;
-       virtual bool canvas_region_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0;
-       virtual bool canvas_region_view_name_highlight_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0;
-       virtual bool canvas_region_view_name_event (GdkEvent* event,ArdourCanvas::Item*, AudioRegionView*) = 0;
-       virtual bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, AudioTimeAxisView*) = 0;
+       virtual bool canvas_region_view_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*) = 0;
+       virtual bool canvas_region_view_name_highlight_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*) = 0;
+       virtual bool canvas_region_view_name_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*) = 0;
+       virtual bool canvas_stream_view_event (GdkEvent* event,ArdourCanvas::Item*, RouteTimeAxisView*) = 0;
        virtual bool canvas_marker_event (GdkEvent* event,ArdourCanvas::Item*, Marker*) = 0;
        virtual bool canvas_zoom_rect_event (GdkEvent* event,ArdourCanvas::Item*) = 0;
        virtual bool canvas_tempo_marker_event (GdkEvent* event,ArdourCanvas::Item*, TempoMarker*) = 0;
index 8971e8ff10245f9105e670321bb90650c4d3de91..1ea5013295ef79d445483a5d0ba9be616d05a65f 100644 (file)
@@ -55,7 +55,7 @@ RedirectAutomationLine::RedirectAutomationLine (const string & name, Redirect& r
                /*NOTREACHED*/
        }
 
-       pi->plugin().get_parameter_descriptor (_port, desc);
+       pi->plugin()->get_parameter_descriptor (_port, desc);
 
        upper = desc.upper;
        lower = desc.lower;
index e3ce4b08c6f8833a6bb8cf1f11884e0f6f5fce09..e527fd1d5e9123fee2cdc8e2e6389fd6da1b4ce7 100644 (file)
@@ -33,7 +33,8 @@ using namespace ARDOUR;
 using namespace PBD;
 using namespace Gtk;
 
-RedirectAutomationTimeAxisView::RedirectAutomationTimeAxisView (Session& s, Route& r, PublicEditor& e, TimeAxisView& parent, Canvas& canvas, std::string n,
+RedirectAutomationTimeAxisView::RedirectAutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r, 
+                                                               PublicEditor& e, TimeAxisView& parent, Canvas& canvas, std::string n,
                                                                uint32_t prt, Redirect& rd, string state_name)
 
        : AxisView (s),
index b8d94b2a3ee9b031f3170c4a3da5337a847aeaa6..6976dc2358e124dd26ce1baf89e8cfcac2debe15 100644 (file)
@@ -14,7 +14,7 @@ class RedirectAutomationTimeAxisView : public AutomationTimeAxisView
 {
   public:
        RedirectAutomationTimeAxisView (ARDOUR::Session&,
-                                       ARDOUR::Route&,
+                                       boost::shared_ptr<ARDOUR::Route>,
                                        PublicEditor&,
                                        TimeAxisView& parent,
                                        ArdourCanvas::Canvas& canvas,
index f5cb9522e06caf72c237fe2a888d6dfa8414df74..74198265d9e82cb34b9707e7cb061a500b237e81 100644 (file)
@@ -76,7 +76,7 @@ bool RedirectBox::get_colors = true;
 Gdk::Color* RedirectBox::active_redirect_color;
 Gdk::Color* RedirectBox::inactive_redirect_color;
 
-RedirectBox::RedirectBox (Placement pcmnt, Session& sess, Route& rt, PluginSelector &plugsel, 
+RedirectBox::RedirectBox (Placement pcmnt, Session& sess, boost::shared_ptr<Route> rt, PluginSelector &plugsel, 
                          RouteRedirectSelection & rsel, bool owner_is_mixer)
        : _route(rt), 
          _session(sess), 
@@ -132,7 +132,7 @@ RedirectBox::RedirectBox (Placement pcmnt, Session& sess, Route& rt, PluginSelec
 
        pack_start (redirect_eventbox, true, true);
 
-       _route.redirects_changed.connect (mem_fun(*this, &RedirectBox::redisplay_redirects));
+       _route->redirects_changed.connect (mem_fun(*this, &RedirectBox::redisplay_redirects));
 
        redirect_eventbox.signal_enter_notify_event().connect (bind (sigc::ptr_fun (RedirectBox::enter_box), this));
 
@@ -161,10 +161,10 @@ RedirectBox::object_drop (string type, uint32_t cnt, void** ptr)
 
        /* do something with the dropped redirects */
 
-       list<Redirect*> redirects;
-
+       list<boost::shared_ptr<Redirect> > redirects;
+       
        for (uint32_t n = 0; n < cnt; ++n) {
-               redirects.push_back ((Redirect*) ptr[n]);
+               redirects.push_back (boost::shared_ptr<Redirect> ((Redirect*) ptr[n]));
        }
        
        paste_redirect_list (redirects);
@@ -189,21 +189,21 @@ RedirectBox::set_width (Width w)
 }
 
 void
-RedirectBox::remove_redirect_gui (Redirect *redirect)
+RedirectBox::remove_redirect_gui (boost::shared_ptr<Redirect> redirect)
 {
-       Insert *insert = 0;
-       Send *send = 0;
-       PortInsert *port_insert = 0;
+       boost::shared_ptr<Insert> insert;
+       boost::shared_ptr<Send> send;
+       boost::shared_ptr<PortInsert> port_insert;
 
-       if ((insert = dynamic_cast<Insert *> (redirect)) != 0) {
+       if ((insert = boost::dynamic_pointer_cast<Insert> (redirect)) != 0) {
 
-               if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
+               if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (insert)) != 0) {
                        PortInsertUI *io_selector = reinterpret_cast<PortInsertUI *> (port_insert->get_gui());
                        port_insert->set_gui (0);
                        delete io_selector;
                } 
 
-       } else if ((send = dynamic_cast<Send *> (insert)) != 0) {
+       } else if ((send = boost::dynamic_pointer_cast<Send> (insert)) != 0) {
                SendUIWindow *sui = reinterpret_cast<SendUIWindow*> (send->get_gui());
                send->set_gui (0);
                delete sui;
@@ -268,7 +268,7 @@ RedirectBox::redirect_button_press_event (GdkEventButton *ev)
        TreeViewColumn* column;
        int cellx;
        int celly;
-       Redirect* redirect = 0;
+       boost::shared_ptr<Redirect> redirect;
        int ret = false;
        bool selected = false;
 
@@ -353,32 +353,32 @@ RedirectBox::choose_plugin ()
 }
 
 void
-RedirectBox::insert_plugin_chosen (Plugin *plugin)
+RedirectBox::insert_plugin_chosen (boost::shared_ptr<Plugin> plugin)
 {
        if (plugin) {
 
-               Redirect *redirect = new PluginInsert (_session, *plugin, _placement);
+               boost::shared_ptr<Redirect> redirect (new PluginInsert (_session, plugin, _placement));
                
                redirect->active_changed.connect (mem_fun(*this, &RedirectBox::show_redirect_active));
 
                uint32_t err_streams;
 
-               if (_route.add_redirect (redirect, this, &err_streams)) {
+               if (_route->add_redirect (redirect, this, &err_streams)) {
                        wierd_plugin_dialog (*plugin, err_streams, _route);
-                       delete redirect;
+                       // XXX SHAREDPTR delete plugin here .. do we even need to care? 
                }
        }
 }
 
 void
-RedirectBox::wierd_plugin_dialog (Plugin& p, uint32_t streams, IO& io)
+RedirectBox::wierd_plugin_dialog (Plugin& p, uint32_t streams, boost::shared_ptr<IO> io)
 {
        ArdourDialog dialog ("wierd plugin dialog");
        Label label;
 
        /* 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, IO& io)
 "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, IO& io)
 "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,10 +415,10 @@ RedirectBox::wierd_plugin_dialog (Plugin& p, uint32_t streams, IO& io)
 "\n"
 "Ardour does not understand what to do in such situations.\n"),
                                         p.name(),
-                                        p.get_info().n_inputs,
-                                        p.get_info().n_outputs,
-                                        io.n_inputs(),
-                                        io.n_outputs(),
+                                        p.get_info()->n_inputs,
+                                        p.get_info()->n_outputs,
+                                        io->n_inputs(),
+                                        io->n_outputs(),
                                         streams));
        }
 
@@ -436,36 +436,36 @@ RedirectBox::wierd_plugin_dialog (Plugin& p, uint32_t streams, IO& io)
 void
 RedirectBox::choose_insert ()
 {
-       Redirect *redirect = new PortInsert (_session, _placement);
+       boost::shared_ptr<Redirect> redirect (new PortInsert (_session, _placement));
        redirect->active_changed.connect (mem_fun(*this, &RedirectBox::show_redirect_active));
-       _route.add_redirect (redirect, this);
+       _route->add_redirect (redirect, this);
 }
 
 void
 RedirectBox::choose_send ()
 {
-       Send *send = new Send (_session, _placement);
+       boost::shared_ptr<Send> send (new Send (_session, _placement));
 
        /* XXX need redirect lock on route */
 
-       send->ensure_io (0, _route.max_redirect_outs(), false, this);
+       send->ensure_io (0, _route->max_redirect_outs(), false, this);
        
-       IOSelectorWindow *ios = new IOSelectorWindow (_session, *send, false, true);
+       IOSelectorWindow *ios = new IOSelectorWindow (_session, send, false, true);
        
        ios->show_all ();
-       ios->selector().Finished.connect (bind (mem_fun(*this, &RedirectBox::send_io_finished), static_cast<Redirect*>(send), ios));
+       ios->selector().Finished.connect (bind (mem_fun(*this, &RedirectBox::send_io_finished), boost::static_pointer_cast<Redirect>(send), ios));
 }
 
 void
-RedirectBox::send_io_finished (IOSelector::Result r, Redirect* redirect, IOSelectorWindow* ios)
+RedirectBox::send_io_finished (IOSelector::Result r, boost::shared_ptr<Redirect> redirect, IOSelectorWindow* ios)
 {
        switch (r) {
        case IOSelector::Cancelled:
-               delete redirect;
+               // delete redirect; XXX SHAREDPTR HOW TO DESTROY THE REDIRECT ? do we even need to think about it?
                break;
 
        case IOSelector::Accepted:
-               _route.add_redirect (redirect, this);
+               _route->add_redirect (redirect, this);
                break;
        }
 
@@ -488,7 +488,8 @@ RedirectBox::redisplay_redirects (void *src)
        redirect_active_connections.clear ();
        redirect_name_connections.clear ();
 
-       _route.foreach_redirect (this, &RedirectBox::add_redirect_to_display);
+       void (RedirectBox::*pmf)(boost::shared_ptr<Redirect>) = &RedirectBox::add_redirect_to_display;
+       _route->foreach_redirect (this, pmf);
 
        switch (_placement) {
        case PreFader:
@@ -501,33 +502,33 @@ RedirectBox::redisplay_redirects (void *src)
 }
 
 void
-RedirectBox::add_redirect_to_display (Redirect *redirect)
+RedirectBox::add_redirect_to_display (boost::shared_ptr<Redirect> redirect)
 {
        if (redirect->placement() != _placement) {
                return;
        }
        
        Gtk::TreeModel::Row row = *(model->append());
-       row[columns.text] = redirect_name (*redirect);
+       row[columns.text] = redirect_name (redirect);
        row[columns.redirect] = redirect;
        
-       show_redirect_active (redirect, this);
+       show_redirect_active (redirect.get(), this);
 
        redirect_active_connections.push_back (redirect->active_changed.connect (mem_fun(*this, &RedirectBox::show_redirect_active)));
        redirect_name_connections.push_back (redirect->name_changed.connect (bind (mem_fun(*this, &RedirectBox::show_redirect_name), redirect)));
 }
 
 string
-RedirectBox::redirect_name (Redirect& redirect)
+RedirectBox::redirect_name (boost::shared_ptr<Redirect> redirect)
 {
-       Send *send;
+       boost::shared_ptr<Send> send;
        string name_display;
 
-       if (!redirect.active()) {
+       if (!redirect->active()) {
                name_display = " (";
        }
 
-       if ((send = dynamic_cast<Send *> (&redirect)) != 0) {
+       if ((send = boost::dynamic_pointer_cast<Send> (redirect)) != 0) {
 
                name_display += '>';
 
@@ -550,16 +551,16 @@ RedirectBox::redirect_name (Redirect& redirect)
 
                switch (_width) {
                case Wide:
-                       name_display += redirect.name();
+                       name_display += redirect->name();
                        break;
                case Narrow:
-                       name_display += PBD::short_version (redirect.name(), 5);
+                       name_display += PBD::short_version (redirect->name(), 5);
                        break;
                }
 
        }
 
-       if (!redirect.active()) {
+       if (!redirect->active()) {
                name_display += ')';
        }
 
@@ -581,34 +582,36 @@ RedirectBox::build_redirect_tooltip (EventBox& box, string start)
 }
 
 void
-RedirectBox::show_redirect_name (void* src, Redirect *redirect)
+RedirectBox::show_redirect_name (void* src, boost::shared_ptr<Redirect> redirect)
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &RedirectBox::show_redirect_name), src, redirect));
-       
-       show_redirect_active (redirect, src);
+       show_redirect_active (redirect.get(), src);
 }
 
 void
-RedirectBox::show_redirect_active (Redirect *redirect, void *src)
+RedirectBox::show_redirect_active (Redirectredirect, void *src)
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &RedirectBox::show_redirect_active), redirect, src));
 
        Gtk::TreeModel::Children children = model->children();
        Gtk::TreeModel::Children::iterator iter = children.begin();
 
-       while( iter != children.end())
-       {
-               if ((*iter)[columns.redirect] == redirect)
-                       break;
-               iter++;
-       }
+       while (iter != children.end()) {
 
-       (*iter)[columns.text] = redirect_name (*redirect);
+               boost::shared_ptr<Redirect> r = (*iter)[columns.redirect];
 
-       if (redirect->active()) {
-               (*iter)[columns.color] = *active_redirect_color;
-       } else {
-               (*iter)[columns.color] = *inactive_redirect_color;
+               if (r.get() == redirect) {
+                       (*iter)[columns.text] = redirect_name (r);
+                       
+                       if (redirect->active()) {
+                               (*iter)[columns.color] = *active_redirect_color;
+                       } else {
+                               (*iter)[columns.color] = *inactive_redirect_color;
+                       }
+                       break;
+               }
+
+               iter++;
        }
 }
 
@@ -627,12 +630,12 @@ RedirectBox::compute_redirect_sort_keys ()
        Gtk::TreeModel::Children children = model->children();
 
        for (Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter) {
-               Redirect *redirect = (*iter)[columns.redirect];
-               redirect->set_sort_key (sort_key);
+               boost::shared_ptr<Redirect> r = (*iter)[columns.redirect];
+               r->set_sort_key (sort_key);
                sort_key++;
        }
 
-       if (_route.sort_redirects ()) {
+       if (_route->sort_redirects ()) {
 
                redisplay_redirects (0);
 
@@ -661,7 +664,7 @@ outputs do not work correctly."));
 void
 RedirectBox::rename_redirects ()
 {
-       vector<Redirect*> to_be_renamed;
+       vector<boost::shared_ptr<Redirect> > to_be_renamed;
        
        get_selected_redirects (to_be_renamed);
 
@@ -669,7 +672,7 @@ RedirectBox::rename_redirects ()
                return;
        }
 
-       for (vector<Redirect*>::iterator i = to_be_renamed.begin(); i != to_be_renamed.end(); ++i) {
+       for (vector<boost::shared_ptr<Redirect> >::iterator i = to_be_renamed.begin(); i != to_be_renamed.end(); ++i) {
                rename_redirect (*i);
        }
 }
@@ -677,7 +680,7 @@ RedirectBox::rename_redirects ()
 void
 RedirectBox::cut_redirects ()
 {
-       vector<Redirect*> to_be_removed;
+       vector<boost::shared_ptr<Redirect> > to_be_removed;
        
        get_selected_redirects (to_be_removed);
 
@@ -692,7 +695,7 @@ RedirectBox::cut_redirects ()
        
        _rr_selection.set (to_be_removed);
 
-       for (vector<Redirect*>::iterator i = to_be_removed.begin(); i != to_be_removed.end(); ++i) {
+       for (vector<boost::shared_ptr<Redirect> >::iterator i = to_be_removed.begin(); i != to_be_removed.end(); ++i) {
                
                void* gui = (*i)->get_gui ();
                
@@ -700,7 +703,7 @@ RedirectBox::cut_redirects ()
                        static_cast<Gtk::Widget*>(gui)->hide ();
                }
                
-               if (_route.remove_redirect (*i, this)) {
+               if (_route->remove_redirect (*i, this)) {
                        /* removal failed */
                        _rr_selection.remove (*i);
                }
@@ -711,8 +714,8 @@ RedirectBox::cut_redirects ()
 void
 RedirectBox::copy_redirects ()
 {
-       vector<Redirect*> to_be_copied;
-       vector<Redirect*> copies;
+       vector<boost::shared_ptr<Redirect> > to_be_copied;
+       vector<boost::shared_ptr<Redirect> > copies;
 
        get_selected_redirects (to_be_copied);
 
@@ -720,29 +723,24 @@ RedirectBox::copy_redirects ()
                return;
        }
 
-       for (vector<Redirect*>::iterator i = to_be_copied.begin(); i != to_be_copied.end(); ++i) {
-               copies.push_back (Redirect::clone (**i));
+       for (vector<boost::shared_ptr<Redirect> >::iterator i = to_be_copied.begin(); i != to_be_copied.end(); ++i) {
+               copies.push_back (Redirect::clone (*i));
        }
 
        _rr_selection.set (copies);
 }
 
 gint
-RedirectBox::idle_delete_redirect (Redirect *redirect)
+RedirectBox::idle_delete_redirect (boost::shared_ptr<Redirect> redirect)
 {
        /* NOT copied to _mixer.selection() */
 
-       if (_route.remove_redirect (redirect, this)) {
-               /* removal failed */
-               return FALSE;
-       }
-
-       delete redirect;
+       _route->remove_redirect (redirect, this);
        return FALSE;
 }
 
 void
-RedirectBox::rename_redirect (Redirect* redirect)
+RedirectBox::rename_redirect (boost::shared_ptr<Redirect> redirect)
 {
        ArdourPrompter name_prompter (true);
        string result;
@@ -767,7 +765,7 @@ RedirectBox::rename_redirect (Redirect* redirect)
 }
 
 void
-RedirectBox::cut_redirect (Redirect *redirect)
+RedirectBox::cut_redirect (boost::shared_ptr<Redirect> redirect)
 {
        /* this essentially transfers ownership of the redirect
           of the redirect from the route to the mixer
@@ -782,15 +780,15 @@ RedirectBox::cut_redirect (Redirect *redirect)
                static_cast<Gtk::Widget*>(gui)->hide ();
        }
        
-       if (_route.remove_redirect (redirect, this)) {
+       if (_route->remove_redirect (redirect, this)) {
                _rr_selection.remove (redirect);
        }
 }
 
 void
-RedirectBox::copy_redirect (Redirect *redirect)
+RedirectBox::copy_redirect (boost::shared_ptr<Redirect> redirect)
 {
-       Redirect* copy = Redirect::clone (*redirect);
+       boost::shared_ptr<Redirect> copy = Redirect::clone (redirect);
        _rr_selection.add (copy);
 }
 
@@ -805,22 +803,19 @@ RedirectBox::paste_redirects ()
 }
 
 void
-RedirectBox::paste_redirect_list (list<Redirect*>& redirects)
+RedirectBox::paste_redirect_list (list<boost::shared_ptr<Redirect> >& redirects)
 {
-       list<Redirect*> copies;
+       list<boost::shared_ptr<Redirect> > copies;
 
-       for (list<Redirect*>::iterator i = redirects.begin(); i != redirects.end(); ++i) {
+       for (list<boost::shared_ptr<Redirect> >::iterator i = redirects.begin(); i != redirects.end(); ++i) {
 
-               Redirect* copy = Redirect::clone (**i);
+               boost::shared_ptr<Redirect> copy = Redirect::clone (*i);
 
                copy->set_placement (_placement, this);
                copies.push_back (copy);
        }
 
-       if (_route.add_redirects (copies, this)) {
-               for (list<Redirect*>::iterator i = copies.begin(); i != copies.end(); ++i) {
-                       delete *i;
-               }
+       if (_route->add_redirects (copies, this)) {
 
                string msg = _(
                        "Copying the set of redirects on the clipboard failed,\n\
@@ -832,19 +827,19 @@ could not match the configuration of this track.");
 }
 
 void
-RedirectBox::activate_redirect (Redirect *r)
+RedirectBox::activate_redirect (boost::shared_ptr<Redirect> r)
 {
        r->set_active (true, 0);
 }
 
 void
-RedirectBox::deactivate_redirect (Redirect *r)
+RedirectBox::deactivate_redirect (boost::shared_ptr<Redirect> r)
 {
        r->set_active (false, 0);
 }
 
 void
-RedirectBox::get_selected_redirects (vector<Redirect*>& redirects)
+RedirectBox::get_selected_redirects (vector<boost::shared_ptr<Redirect> >& redirects)
 {
     vector<Gtk::TreeModel::Path> pathlist = redirect_display.get_selection()->get_selected_rows();
  
@@ -853,12 +848,12 @@ RedirectBox::get_selected_redirects (vector<Redirect*>& redirects)
 }
 
 void
-RedirectBox::for_selected_redirects (void (RedirectBox::*pmf)(Redirect*))
+RedirectBox::for_selected_redirects (void (RedirectBox::*pmf)(boost::shared_ptr<Redirect>))
 {
     vector<Gtk::TreeModel::Path> pathlist = redirect_display.get_selection()->get_selected_rows();
 
        for (vector<Gtk::TreeModel::Path>::iterator iter = pathlist.begin(); iter != pathlist.end(); ++iter) {
-               Redirect* redirect = (*(model->get_iter(*iter)))[columns.redirect];
+               boost::shared_ptr<Redirect> redirect = (*(model->get_iter(*iter)))[columns.redirect];
                (this->*pmf)(redirect);
        }
 }
@@ -869,7 +864,7 @@ RedirectBox::clone_redirects ()
        RouteSelection& routes (_rr_selection.routes);
 
        if (!routes.empty()) {
-               if (_route.copy_redirects (*routes.front(), _placement)) {
+               if (_route->copy_redirects (*routes.front(), _placement)) {
                        string msg = _(
 "Copying the set of redirects on the clipboard failed,\n\
 probably because the I/O configuration of the plugins\n\
@@ -883,7 +878,7 @@ could not match the configuration of this track.");
 void
 RedirectBox::all_redirects_active (bool state)
 {
-       _route.all_redirects_active (state);
+       _route->all_redirects_active (state);
 }
 
 void
@@ -892,7 +887,7 @@ RedirectBox::clear_redirects()
        string prompt;
        vector<string> choices;
 
-       if (dynamic_cast<AudioTrack*>(&_route) != 0) {
+       if (boost::dynamic_pointer_cast<AudioTrack>(_route) != 0) {
                prompt = _("Do you really want to remove all redirects from this track?\n"
                           "(this cannot be undone)");
        } else {
@@ -906,23 +901,23 @@ RedirectBox::clear_redirects()
        Gtkmm2ext::Choice prompter (prompt, choices);
 
        if (prompter.run () == 1) {
-               _route.clear_redirects (this);
+               _route->clear_redirects (this);
        }
 }
 
 void
-RedirectBox::edit_redirect (Redirect* redirect)
+RedirectBox::edit_redirect (boost::shared_ptr<Redirect> redirect)
 {
-       Insert *insert;
+       boost::shared_ptr<Insert> insert;
 
-       if (dynamic_cast<AudioTrack*>(&_route) != 0) {
+       if (boost::dynamic_pointer_cast<AudioTrack>(_route) != 0) {
 
-               if (dynamic_cast<AudioTrack*> (&_route)->freeze_state() == AudioTrack::Frozen) {
+               if (boost::dynamic_pointer_cast<AudioTrack> (_route)->freeze_state() == AudioTrack::Frozen) {
                        return;
                }
        }
        
-       if ((insert = dynamic_cast<Insert *> (redirect)) == 0) {
+       if ((insert = boost::dynamic_pointer_cast<Insert> (redirect)) == 0) {
                
                /* its a send */
                
@@ -930,7 +925,7 @@ RedirectBox::edit_redirect (Redirect* redirect)
                        return;
                }
 
-               Send *send = dynamic_cast<Send*> (redirect);
+               boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (redirect);
                
                SendUIWindow *send_ui;
                
@@ -939,7 +934,7 @@ RedirectBox::edit_redirect (Redirect* redirect)
                        string title;
                        title = string_compose(_("ardour: %1"), send->name());  
                        
-                       send_ui = new SendUIWindow (*send, _session);
+                       send_ui = new SendUIWindow (send, _session);
                        send_ui->set_title (title);
                        send->set_gui (send_ui);
                        
@@ -957,17 +952,17 @@ RedirectBox::edit_redirect (Redirect* redirect)
                
                /* its an insert */
                
-               PluginInsert *plugin_insert;
-               PortInsert *port_insert;
+               boost::shared_ptr<PluginInsert> plugin_insert;
+               boost::shared_ptr<PortInsert> port_insert;
                
-               if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
+               if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (insert)) != 0) {
                        
                        PluginUIWindow *plugin_ui;
                        
                        if (plugin_insert->get_gui() == 0) {
                                
                                string title;
-                               string maker = plugin_insert->plugin().maker();
+                               string maker = plugin_insert->plugin()->maker();
                                string::size_type email_pos;
                                
                                if ((email_pos = maker.find_first_of ('<')) != string::npos) {
@@ -979,9 +974,9 @@ RedirectBox::edit_redirect (Redirect* redirect)
                                        maker += " ...";
                                }
 
-                               title = string_compose(_("ardour: %1: %2 (by %3)"), _route.name(), plugin_insert->name(), maker);       
+                               title = string_compose(_("ardour: %1: %2 (by %3)"), _route->name(), plugin_insert->name(), maker);      
                                
-                               plugin_ui = new PluginUIWindow (_session.engine(), *plugin_insert);
+                               plugin_ui = new PluginUIWindow (_session.engine(), plugin_insert);
                                if (_owner_is_mixer) {
                                        ARDOUR_UI::instance()->the_mixer()->ensure_float (*plugin_ui);
                                } else {
@@ -1000,7 +995,7 @@ RedirectBox::edit_redirect (Redirect* redirect)
                                plugin_ui->show_all ();
                        }
                        
-               } else if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
+               } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (insert)) != 0) {
                        
                        if (!_session.engine().connected()) {
                                MessageDialog msg ( _("Not connected to JACK - no I/O changes are possible"));
@@ -1011,7 +1006,7 @@ RedirectBox::edit_redirect (Redirect* redirect)
                        PortInsertWindow *io_selector;
 
                        if (port_insert->get_gui() == 0) {
-                               io_selector = new PortInsertWindow (_session, *port_insert);
+                               io_selector = new PortInsertWindow (_session, port_insert);
                                port_insert->set_gui (io_selector);
                                
                        } else {
index bc162fac17170b793b003f354725f05292cacb99..51c17cad51e21086f82449929fcb2a3eabf1e131 100644 (file)
 #include <gtkmm2ext/click_box.h>
 #include <gtkmm2ext/dndtreeview.h>
 
+#include <pbd/stateful.h>
+
 #include <ardour/types.h>
 #include <ardour/ardour.h>
 #include <ardour/io.h>
 #include <ardour/insert.h>
-#include <ardour/stateful.h>
 #include <ardour/redirect.h>
 
 #include <pbd/fastlog.h>
@@ -64,7 +65,8 @@ namespace ARDOUR {
 class RedirectBox : public Gtk::HBox
 {
   public:
-       RedirectBox (ARDOUR::Placement, ARDOUR::Session&, ARDOUR::Route &, PluginSelector &, RouteRedirectSelection &, bool owner_is_mixer = false);
+       RedirectBox (ARDOUR::Placement, ARDOUR::Session&, 
+                    boost::shared_ptr<ARDOUR::Route>, PluginSelector &, RouteRedirectSelection &, bool owner_is_mixer = false);
        ~RedirectBox ();
 
        void set_width (Width);
@@ -77,8 +79,8 @@ class RedirectBox : public Gtk::HBox
        void select_all_inserts ();
        void select_all_sends ();
        
-       sigc::signal<void,ARDOUR::Redirect *> RedirectSelected;
-       sigc::signal<void,ARDOUR::Redirect *> RedirectUnselected;
+       sigc::signal<void,boost::shared_ptr<ARDOUR::Redirect> > RedirectSelected;
+       sigc::signal<void,boost::shared_ptr<ARDOUR::Redirect> > RedirectUnselected;
        
        static void register_actions();
 
@@ -86,7 +88,7 @@ class RedirectBox : public Gtk::HBox
        void set_stuff_from_route ();
 
   private:
-       ARDOUR::Route &     _route;
+       boost::shared_ptr<ARDOUR::Route>  _route;
        ARDOUR::Session &   _session;
        bool                _owner_is_mixer;
 
@@ -102,7 +104,7 @@ class RedirectBox : public Gtk::HBox
                    add (color);
            }
            Gtk::TreeModelColumn<std::string>       text;
-           Gtk::TreeModelColumn<ARDOUR::Redirect*> redirect;
+           Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Redirect> > redirect;
            Gtk::TreeModelColumn<Gdk::Color>        color;
        };
 
@@ -137,24 +139,29 @@ class RedirectBox : public Gtk::HBox
        void show_redirect_menu (gint arg);
 
        void choose_send ();
-       void send_io_finished (IOSelector::Result, ARDOUR::Redirect*, IOSelectorWindow*);
+       void send_io_finished (IOSelector::Result, boost::shared_ptr<ARDOUR::Redirect>, IOSelectorWindow*);
        void choose_insert ();
        void choose_plugin ();
-       void insert_plugin_chosen (ARDOUR::Plugin *);
+       void insert_plugin_chosen (boost::shared_ptr<ARDOUR::Plugin>);
 
        bool no_redirect_redisplay;
        bool ignore_delete;
 
        bool redirect_button_press_event (GdkEventButton *);
        void redisplay_redirects (void* src);
-       void show_redirect_active (ARDOUR::Redirect *, void *);
-       void show_redirect_name (void*, ARDOUR::Redirect *);
-       void add_redirect_to_display (ARDOUR::Redirect *);
+       void add_redirect_to_display (boost::shared_ptr<ARDOUR::Redirect>);
        void row_deleted (const Gtk::TreeModel::Path& path);
+       void show_redirect_name (void*, boost::shared_ptr<ARDOUR::Redirect>);
+
+       /* these are handlers for Redirect signals, so they take Redirect*
+          directly, rather than shared_ptr<Redirect>
+       */
+
+       void show_redirect_active (ARDOUR::Redirect*, void *);
 
-       string redirect_name (ARDOUR::Redirect&);
+       string redirect_name (boost::shared_ptr<ARDOUR::Redirect>);
 
-       void remove_redirect_gui (ARDOUR::Redirect *);
+       void remove_redirect_gui (boost::shared_ptr<ARDOUR::Redirect>);
 
        void redirects_reordered (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator&, int*);
        void compute_redirect_sort_keys ();
@@ -173,23 +180,23 @@ class RedirectBox : public Gtk::HBox
        void clone_redirects ();
        void rename_redirects ();
 
-       void for_selected_redirects (void (RedirectBox::*pmf)(ARDOUR::Redirect*));
-       void get_selected_redirects (vector<ARDOUR::Redirect*>&);
+       void for_selected_redirects (void (RedirectBox::*pmf)(boost::shared_ptr<ARDOUR::Redirect>));
+       void get_selected_redirects (vector<boost::shared_ptr<ARDOUR::Redirect> >&);
 
        static Glib::RefPtr<Gtk::Action> paste_action;
-       void paste_redirect_list (std::list<ARDOUR::Redirect*>& redirects);
+       void paste_redirect_list (std::list<boost::shared_ptr<ARDOUR::Redirect> >& redirects);
        
-       void activate_redirect (ARDOUR::Redirect*);
-       void deactivate_redirect (ARDOUR::Redirect*);
-       void cut_redirect (ARDOUR::Redirect*);
-       void copy_redirect (ARDOUR::Redirect*);
-       void edit_redirect (ARDOUR::Redirect*);
-       void hide_redirect_editor (ARDOUR::Redirect*);
-       void rename_redirect (ARDOUR::Redirect*);
+       void activate_redirect (boost::shared_ptr<ARDOUR::Redirect>);
+       void deactivate_redirect (boost::shared_ptr<ARDOUR::Redirect>);
+       void cut_redirect (boost::shared_ptr<ARDOUR::Redirect>);
+       void copy_redirect (boost::shared_ptr<ARDOUR::Redirect>);
+       void edit_redirect (boost::shared_ptr<ARDOUR::Redirect>);
+       void hide_redirect_editor (boost::shared_ptr<ARDOUR::Redirect>);
+       void rename_redirect (boost::shared_ptr<ARDOUR::Redirect>);
 
-       gint idle_delete_redirect (ARDOUR::Redirect *);
+       gint idle_delete_redirect (boost::shared_ptr<ARDOUR::Redirect>);
 
-       void wierd_plugin_dialog (ARDOUR::Plugin& p, uint32_t streams, ARDOUR::IO& io);
+       void wierd_plugin_dialog (ARDOUR::Plugin& p, uint32_t streams, boost::shared_ptr<ARDOUR::IO> io);
 
        static RedirectBox* _current_redirect_box;
        static bool enter_box (GdkEventCrossing*, RedirectBox*);
index 3695f85c600b96855d2fee45efec0d6c631b6d73..5bcd77cfe47a3ab01603a502d05353097eae3bb2 100644 (file)
@@ -2,11 +2,12 @@
 #define __ardour_gtk_redirect_selection_h__
 
 #include <list>
+#include <boost/shared_ptr.hpp>
 
 namespace ARDOUR {
        class Redirect;
 }
 
-struct RedirectSelection : list<ARDOUR::Redirect*> {};
+struct RedirectSelection : list<boost::shared_ptr<ARDOUR::Redirect> > {};
 
 #endif /* __ardour_gtk_redirect_selection_h__ */
diff --git a/gtk2_ardour/region_editor.cc b/gtk2_ardour/region_editor.cc
deleted file mode 100644 (file)
index 413ff01..0000000
+++ /dev/null
@@ -1,732 +0,0 @@
-/*
-    Copyright (C) 2001 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$
-*/
-
-#include <ardour/audioregion.h>
-#include <ardour/utils.h>
-#include <gtkmm2ext/utils.h>
-#include <gtkmm2ext/stop_signal.h>
-#include <cmath>
-
-#include "region_editor.h"
-#include "regionview.h"
-#include "ardour_ui.h"
-#include "utils.h"
-#include "gui_thread.h"
-
-#include "i18n.h"
-
-using namespace ARDOUR;
-using namespace PBD;
-using namespace sigc;
-using namespace std;
-
-AudioRegionEditor::AudioRegionEditor (Session&s, AudioRegion& r, AudioRegionView& rv)
-       : ArdourDialog ("audio region editor"),
-         _session (s),
-         _region (r),
-         _region_view (rv),
-         name_label (_("NAME:")),
-         lock_button (_("lock")),
-         mute_button (_("mute")),
-         opaque_button (_("opaque")),
-         envelope_active_button(_("active")),
-         envelope_view_button(_("visible")),
-         raise_arrow (Gtk::ARROW_UP, Gtk::SHADOW_OUT),
-         lower_arrow (Gtk::ARROW_DOWN, Gtk::SHADOW_OUT),
-         layer_label (_("Layer")),
-         audition_button (_("play")),
-         time_table (3, 2),
-         start_clock ("AudioRegionEditorClock", true),
-         end_clock ("AudioRegionEditorClock", true),
-         length_clock ("AudioRegionEditorClock", true, true),
-         sync_offset_clock ("AudioRegionEditorClock", true, true),
-         envelope_loop_table (1, 3),
-         envelope_label (_("ENVELOPE")),
-         fade_in_table (4, 3),
-         fade_in_length_adjustment (5.0, 0.0, 10000, 0.05, 1),
-         fade_in_length_spinner (fade_in_length_adjustment, 10),
-         fade_out_table (4, 3),
-         fade_out_length_adjustment (5.0, 0.0, 10000, 0.05, 1),
-         fade_out_length_spinner (fade_out_length_adjustment, 10)
-
-{
-       start_clock.set_session (&_session);
-       end_clock.set_session (&_session);
-       length_clock.set_session (&_session);
-
-       name_entry.set_name ("AudioRegionEditorEntry");
-       name_label.set_name ("AudioRegionEditorLabel");
-
-       name_hbox.set_spacing (5);
-       name_hbox.pack_start (name_label, false, false);
-       name_hbox.pack_start (name_entry, false, false);
-
-       raise_button.add (raise_arrow);
-       lower_button.add (lower_arrow);
-       layer_frame.set_name ("BaseFrame");
-       layer_frame.set_shadow_type (Gtk::SHADOW_IN);
-       layer_frame.add (layer_value_label);
-       layer_label.set_name ("AudioRegionEditorLabel");
-       layer_value_label.set_name ("AudioRegionEditorLabel");
-       Gtkmm2ext::set_size_request_to_display_given_text (layer_value_label, "99", 5, 2);
-
-       layer_hbox.set_spacing (5);
-       layer_hbox.pack_start (layer_label, false, false);
-       layer_hbox.pack_start (layer_frame, false, false);
-#if 0
-       layer_hbox.pack_start (raise_button, false, false);
-       layer_hbox.pack_start (lower_button, false, false);
-#endif
-
-       mute_button.set_name ("AudioRegionEditorToggleButton");
-       opaque_button.set_name ("AudioRegionEditorToggleButton");
-       lock_button.set_name ("AudioRegionEditorToggleButton");
-       envelope_active_button.set_name ("AudioRegionEditorToggleButton");
-       envelope_view_button.set_name ("AudioRegionEditorToggleButton");
-       fade_in_active_button.set_name ("AudioRegionEditorToggleButton");
-       fade_out_active_button.set_name ("AudioRegionEditorToggleButton");
-       audition_button.set_name ("AudioRegionEditorToggleButton");
-
-       ARDOUR_UI::instance()->tooltips().set_tip (mute_button, _("mute this region"));
-       ARDOUR_UI::instance()->tooltips().set_tip (opaque_button, _("regions underneath this one cannot be heard"));
-       ARDOUR_UI::instance()->tooltips().set_tip (lock_button, _("prevent any changes to this region"));
-       ARDOUR_UI::instance()->tooltips().set_tip (envelope_active_button, _("use the gain envelope during playback"));
-       ARDOUR_UI::instance()->tooltips().set_tip (envelope_view_button, _("show the gain envelope"));
-       ARDOUR_UI::instance()->tooltips().set_tip (fade_in_active_button, _("use fade in curve during playback"));
-       ARDOUR_UI::instance()->tooltips().set_tip (fade_out_active_button, _("use fade out curve during playback"));
-       ARDOUR_UI::instance()->tooltips().set_tip (audition_button, _("audition this region"));
-
-       mute_button.unset_flags (Gtk::CAN_FOCUS);
-       opaque_button.unset_flags (Gtk::CAN_FOCUS);
-       lock_button.unset_flags (Gtk::CAN_FOCUS);
-       envelope_active_button.unset_flags (Gtk::CAN_FOCUS);
-       envelope_view_button.unset_flags (Gtk::CAN_FOCUS);
-       fade_in_active_button.unset_flags (Gtk::CAN_FOCUS);
-       fade_out_active_button.unset_flags (Gtk::CAN_FOCUS);
-       audition_button.unset_flags (Gtk::CAN_FOCUS);
-       
-       mute_button.set_events (mute_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       opaque_button.set_events (opaque_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       lock_button.set_events (lock_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       envelope_active_button.set_events (envelope_active_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       envelope_view_button.set_events (envelope_view_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       fade_in_active_button.set_events (fade_in_active_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       fade_out_active_button.set_events (fade_out_active_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-       audition_button.set_events (audition_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
-
-       top_row_button_hbox.set_border_width (5);
-       top_row_button_hbox.set_spacing (5);
-       top_row_button_hbox.set_homogeneous (false);
-       top_row_button_hbox.pack_start (mute_button, false, false);
-       top_row_button_hbox.pack_start (opaque_button, false, false);
-       top_row_button_hbox.pack_start (lock_button, false, false);
-       top_row_button_hbox.pack_start (layer_hbox, false, false, 5);
-       top_row_button_hbox.pack_end (audition_button, false, false);
-       
-       top_row_hbox.pack_start (name_hbox, true, true);
-       top_row_hbox.pack_end (top_row_button_hbox, true, true);
-
-       start_label.set_name ("AudioRegionEditorLabel");
-       start_label.set_text (_("START:"));
-       end_label.set_name ("AudioRegionEditorLabel");
-       end_label.set_text (_("END:"));
-       length_label.set_name ("AudioRegionEditorLabel");
-       length_label.set_text (_("LENGTH:"));
-       
-       time_table.set_col_spacings (2);
-       time_table.set_row_spacings (5);
-       time_table.set_border_width (5);
-
-       start_alignment.set (1.0, 0.5);
-       end_alignment.set (1.0, 0.5);
-       length_alignment.set (1.0, 0.5);
-
-       start_alignment.add (start_label);
-       end_alignment.add (end_label);
-       length_alignment.add (length_label);
-
-       time_table.attach (start_alignment, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
-       time_table.attach (start_clock, 1, 2, 0, 1, Gtk::FILL, Gtk::FILL);
-
-       time_table.attach (end_alignment, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL);
-       time_table.attach (end_clock, 1, 2, 1, 2, Gtk::FILL, Gtk::FILL);
-
-       time_table.attach (length_alignment, 0, 1, 2, 3, Gtk::FILL, Gtk::FILL);
-       time_table.attach (length_clock, 1, 2, 2, 3, Gtk::FILL, Gtk::FILL);
-
-       envelope_label.set_name ("AudioRegionEditorLabel");
-
-       envelope_loop_table.set_border_width (5);
-       envelope_loop_table.set_row_spacings (2);
-       envelope_loop_table.attach (envelope_label, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
-       envelope_loop_table.attach (envelope_active_button, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-       envelope_loop_table.attach (envelope_view_button, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       /* fade in */
-
-       fade_in_table.set_border_width (5);
-       fade_in_table.set_homogeneous (false);
-
-       fade_in_label.set_name ("AudioRegionEditorLabel");
-       fade_in_active_button_label.set_name ("AudioRegionEditorSmallLabel");
-       fade_in_length_label.set_name ("AudioRegionEditorSmallLabel");
-
-       fade_in_label.set_text (_("FADE IN"));
-       fade_in_active_button_label.set_text (_("active"));
-       fade_in_length_label.set_text (_("msecs"));
-
-       fade_in_active_button.add (fade_in_active_button_label);
-
-       fade_in_length_spinner.set_name("GenericSpinner");
-
-       fade_in_length_spinner.set_digits (3);
-
-       // fade_in_length_spinner.signal_activate().connect (mem_fun(*this, &AudioRegionEditor::activation));
-
-       Gtkmm2ext::set_size_request_to_display_given_text (fade_in_length_spinner, "500g", 20, -1);
-
-       fade_in_label_align.add (fade_in_label);
-       fade_in_label_align.set (0.5);
-
-
-       fade_in_table.attach (fade_in_label_align,   0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       fade_in_table.attach (fade_in_length_label,   0, 1, 1, 2, Gtk::EXPAND, Gtk::FILL);
-       fade_in_table.attach (fade_in_length_spinner, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       fade_in_table.attach (fade_in_active_button,        0, 2, 3, 5, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       /* fade out */
-
-       fade_out_table.set_border_width (5);
-       fade_out_table.set_homogeneous (false);
-
-       fade_out_label.set_name ("AudioRegionEditorLabel");
-       fade_out_active_button_label.set_name ("AudioRegionEditorSmallLabel");
-       fade_out_length_label.set_name ("AudioRegionEditorSmallLabel");
-
-       fade_out_label.set_text (_("FADE OUT"));
-       fade_out_active_button_label.set_text (_("active"));
-       fade_out_length_label.set_text (_("msecs"));
-
-       fade_out_active_button.add (fade_out_active_button_label);
-
-       fade_out_length_spinner.set_name("GenericSpinner");
-       
-       fade_out_length_spinner.set_digits (3);
-
-       fade_out_length_spinner.signal_activate().connect (mem_fun(*this, &AudioRegionEditor::activation));
-
-       Gtkmm2ext::set_size_request_to_display_given_text (fade_out_length_spinner, "500g", 20, -1);
-
-       fade_out_label_align.add (fade_out_label);
-       fade_out_label_align.set (0.5);
-
-       fade_out_table.attach (fade_out_label_align,   0, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       fade_out_table.attach (fade_out_length_label,   0, 1, 1, 2, Gtk::EXPAND, Gtk::FILL);
-       fade_out_table.attach (fade_out_length_spinner, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       fade_out_table.attach (fade_out_active_button,        0, 2, 3, 5, Gtk::FILL|Gtk::EXPAND, Gtk::FILL);
-
-       lower_hbox.pack_start (time_table, true, true);
-       lower_hbox.pack_start (sep1, false, false);
-       lower_hbox.pack_start (envelope_loop_table, true, true);
-       lower_hbox.pack_start (sep2, false, false);
-       lower_hbox.pack_start (fade_in_table, true, true);
-       lower_hbox.pack_start (fade_out_table, true, true);
-
-       get_vbox()->pack_start (top_row_hbox, true, true);
-       get_vbox()->pack_start (sep3, false, false);
-       get_vbox()->pack_start (lower_hbox, true, true);
-
-       set_name ("AudioRegionEditorWindow");
-       add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
-
-       signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (this)));
-
-       string title = _("ardour: region ");
-       title += _region.name();
-       set_title (title);
-
-       show_all();
-
-       name_changed ();
-       bounds_changed (Change (StartChanged|LengthChanged|PositionChanged));
-       envelope_active_changed ();
-       mute_changed ();
-       opacity_changed ();
-       lock_changed ();
-       layer_changed ();
-       fade_in_changed ();
-       fade_out_changed ();
-
-       XMLNode *node  = _region.extra_xml ("GUI");
-       XMLProperty *prop = 0;
-       bool showing_envelope = false;
-
-       if (node && (prop = node->property ("envelope-visible")) != 0) {
-               if (prop->value() == "yes") {
-                       showing_envelope = true;
-               } 
-       } 
-
-       if (showing_envelope) {
-               envelope_view_button.set_active (true);
-       } else {
-               envelope_view_button.set_active (false);
-       }
-
-       _region.StateChanged.connect (mem_fun(*this, &AudioRegionEditor::region_changed));
-       
-       spin_arrow_grab = false;
-       
-       connect_editor_events ();
-}
-
-AudioRegionEditor::~AudioRegionEditor ()
-{
-}
-
-void
-AudioRegionEditor::region_changed (Change what_changed)
-{
-       if (what_changed & NameChanged) {
-               name_changed ();
-       }
-       if (what_changed & BoundsChanged) {
-               bounds_changed (what_changed);
-       }
-
-       if (what_changed & Region::OpacityChanged) {
-               opacity_changed ();
-       }
-       if (what_changed & Region::MuteChanged) {
-               mute_changed ();
-       }
-       if (what_changed & Region::LockChanged) {
-               lock_changed ();
-       }
-       if (what_changed & Region::LayerChanged) {
-               layer_changed ();
-       }
-
-       if (what_changed & AudioRegion::EnvelopeActiveChanged) {
-               envelope_active_changed ();
-       }
-       if (what_changed & AudioRegion::FadeInChanged) {
-               fade_in_changed ();
-       }
-       if (what_changed & AudioRegion::FadeOutChanged) {
-               fade_out_changed ();
-       }
-       if (what_changed & AudioRegion::FadeInActiveChanged) {
-               fade_in_active_changed ();
-       }
-       if (what_changed & AudioRegion::FadeOutActiveChanged) {
-               fade_out_active_changed ();
-       }
-}
-
-void
-AudioRegionEditor::fade_in_realized ()
-{
-       fade_in_changed ();
-}
-
-void
-AudioRegionEditor::fade_out_realized ()
-{
-       fade_out_changed ();
-}
-
-gint 
-AudioRegionEditor::bpressed (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)())
-{
-       switch (ev->button) {
-       case 1:
-       case 2:
-       case 3:
-               if (ev->type == GDK_BUTTON_PRESS) { /* no double clicks here */
-                       if (!spin_arrow_grab) {
-                               // GTK2FIX probably nuke the region editor
-                               // if ((ev->window == but->gobj()->panel)) {
-                               // spin_arrow_grab = true;
-                               // (this->*pmf)();
-                               // } 
-                       } 
-               } 
-               break;
-       default:
-               break;
-       }
-       return FALSE;
-}
-
-gint 
-AudioRegionEditor::breleased (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)())
-{
-       if (spin_arrow_grab) {
-               (this->*pmf)();
-               spin_arrow_grab = false;
-       }
-       return FALSE;
-}
-
-void
-AudioRegionEditor::start_editing_fade_in ()
-{
-       _region.freeze ();
-}
-
-void
-AudioRegionEditor::stop_editing_fade_in ()
-{
-       _region.thaw (_("fade in edit"));
-}
-
-void
-AudioRegionEditor::start_editing_fade_out ()
-{
-       _region.freeze ();
-}
-
-void
-AudioRegionEditor::stop_editing_fade_out ()
-{
-       _region.thaw (_("fade out edit"));
-}
-
-void
-AudioRegionEditor::connect_editor_events ()
-{
-  name_entry.signal_changed().connect (mem_fun(*this, &AudioRegionEditor::name_entry_changed));
-
-       start_clock.ValueChanged.connect (mem_fun(*this, &AudioRegionEditor::start_clock_changed));
-       end_clock.ValueChanged.connect (mem_fun(*this, &AudioRegionEditor::end_clock_changed));
-       length_clock.ValueChanged.connect (mem_fun(*this, &AudioRegionEditor::length_clock_changed));
-
-       fade_in_length_spinner.signal_button_press_event().connect (bind (mem_fun(*this, &AudioRegionEditor::bpressed), &fade_in_length_spinner, 
-                                                                &AudioRegionEditor::start_editing_fade_in));
-       fade_in_length_spinner.signal_button_release_event().connect (bind (mem_fun (*this, &AudioRegionEditor::breleased), &fade_in_length_spinner, 
-                                                                  &AudioRegionEditor::stop_editing_fade_in));
-
-       fade_out_length_spinner.signal_button_press_event().connect (bind (mem_fun(*this, &AudioRegionEditor::bpressed), &fade_out_length_spinner, 
-                                                                &AudioRegionEditor::start_editing_fade_out));
-       fade_out_length_spinner.signal_button_release_event().connect (bind (mem_fun (*this, &AudioRegionEditor::breleased), &fade_out_length_spinner, 
-                                                                  &AudioRegionEditor::stop_editing_fade_out));
-
-       fade_in_length_adjustment.signal_value_changed().connect (mem_fun(*this, &AudioRegionEditor::fade_in_length_adjustment_changed));
-       fade_out_length_adjustment.signal_value_changed().connect (mem_fun(*this, &AudioRegionEditor::fade_out_length_adjustment_changed));
-
-       fade_in_active_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::fade_in_active_toggled));
-       fade_out_active_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::fade_out_active_toggled));
-
-       envelope_active_button.signal_button_press_event().connect (mem_fun(*this, &AudioRegionEditor::envelope_active_button_press));
-       envelope_active_button.signal_button_release_event().connect (mem_fun(*this, &AudioRegionEditor::envelope_active_button_release));
-       audition_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::audition_button_toggled));
-       envelope_view_button.signal_toggled().connect (mem_fun(*this, &AudioRegionEditor::envelope_view_button_toggled));
-       lock_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::lock_button_clicked));
-       mute_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::mute_button_clicked));
-       opaque_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::opaque_button_clicked));
-       raise_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::raise_button_clicked));
-       lower_button.signal_clicked().connect (mem_fun(*this, &AudioRegionEditor::lower_button_clicked));
-       _session.AuditionActive.connect (mem_fun(*this, &AudioRegionEditor::audition_state_changed));
-}
-
-void
-AudioRegionEditor::start_clock_changed ()
-{
-       _region.set_position (start_clock.current_time(), this);
-}
-
-void
-AudioRegionEditor::end_clock_changed ()
-{
-       _region.trim_end (end_clock.current_time(), this);
-
-       end_clock.set (_region.position() + _region.length(), true);
-}
-
-void
-AudioRegionEditor::length_clock_changed ()
-{
-       jack_nframes_t frames = length_clock.current_time();
-       _region.trim_end (_region.position() + frames, this);
-
-       length_clock.set (_region.length());
-}
-
-gint
-AudioRegionEditor::envelope_active_button_press(GdkEventButton *ev)
-{
-       return stop_signal (envelope_active_button, "button_press_event");
-}
-
-gint
-AudioRegionEditor::envelope_active_button_release (GdkEventButton *ev)
-{
-       _region.set_envelope_active (!_region.envelope_active());
-       return stop_signal (envelope_active_button, "button_release_event");
-}
-
-void
-AudioRegionEditor::envelope_view_button_toggled ()
-{
-       bool visible = envelope_view_button.get_active ();
-
-       _region_view.set_envelope_visible (visible);
-}
-
-void
-AudioRegionEditor::audition_button_toggled ()
-{
-       if (audition_button.get_active()) {
-               _session.audition_region (_region);
-       } else {
-               _session.cancel_audition ();
-       }
-}
-
-void
-AudioRegionEditor::raise_button_clicked ()
-{
-       _region.raise ();
-}
-
-void
-AudioRegionEditor::lower_button_clicked ()
-{
-       _region.lower ();
-}
-
-void
-AudioRegionEditor::opaque_button_clicked ()
-{
-       bool ractive = _region.opaque();
-
-       if (opaque_button.get_active() != ractive) {
-               _region.set_opaque (!ractive);
-       }
-}
-
-void
-AudioRegionEditor::mute_button_clicked ()
-{
-       bool ractive = _region.muted();
-
-       if (mute_button.get_active() != ractive) {
-               _region.set_muted (!ractive);
-       }
-}
-
-void
-AudioRegionEditor::lock_button_clicked ()
-{
-       bool ractive = _region.locked();
-
-       if (lock_button.get_active() != ractive) {
-               _region.set_locked (!ractive);
-       }
-}
-
-void
-AudioRegionEditor::layer_changed ()
-{
-       char buf[8];
-       snprintf (buf, sizeof(buf), "%d", (int) _region.layer() + 1);
-       layer_value_label.set_text (buf);
-}
-
-void
-AudioRegionEditor::name_changed ()
-{
-       if (name_entry.get_text() != _region.name()) {
-               name_entry.set_text (_region.name());
-       }
-}
-
-void
-AudioRegionEditor::lock_changed ()
-{
-       bool yn;
-
-       if ((yn = _region.locked()) != lock_button.get_active()) {
-               lock_button.set_active (yn);
-       }
-
-       start_clock.set_sensitive (!yn);
-       end_clock.set_sensitive (!yn);
-       length_clock.set_sensitive (!yn);
-}
-
-void
-AudioRegionEditor::envelope_active_changed ()
-{
-       bool yn;
-
-       if ((yn = _region.envelope_active()) != envelope_active_button.get_active()) {
-               envelope_active_button.set_active (yn);
-       }
-}
-
-void
-AudioRegionEditor::opacity_changed ()
-{
-       bool yn;
-       if ((yn = _region.opaque()) != opaque_button.get_active()) {
-               opaque_button.set_active (yn);
-       }
-}
-
-void
-AudioRegionEditor::mute_changed ()
-{
-       bool yn;
-       if ((yn = _region.muted()) != mute_button.get_active()) {
-               mute_button.set_active (yn);
-       }
-}
-
-void
-AudioRegionEditor::bounds_changed (Change what_changed)
-{
-       if (what_changed & Change ((PositionChanged|LengthChanged))) {
-               start_clock.set (_region.position(), true);
-               end_clock.set (_region.position() + _region.length(), true);
-               length_clock.set (_region.length(), true);
-       }
-}
-
-void
-AudioRegionEditor::activation ()
-{
-       
-}      
-
-void
-AudioRegionEditor::name_entry_changed ()
-{
-       if (name_entry.get_text() != _region.name()) {
-               _region.set_name (name_entry.get_text());
-       }
-}
-
-void
-AudioRegionEditor::fade_in_changed ()
-{
-       float msecs = fade_in_length_adjustment.get_value();
-       jack_nframes_t sr = _session.frame_rate();
-       jack_nframes_t adj_frames = (jack_nframes_t) floor (msecs * (sr/1000.0f));
-       jack_nframes_t frames;
-       bool x;
-
-       if (adj_frames != (frames = (jack_nframes_t) _region.fade_in().back()->when)) {
-               fade_in_length_adjustment.set_value ((frames * 1000.0f) / sr);
-       }
-
-       if ((x = _region.fade_in_active()) != fade_in_active_button.get_active()) {
-               fade_in_active_button.set_active (x);
-       }
-}
-
-void
-AudioRegionEditor::fade_out_changed ()
-{
-       float msecs = fade_out_length_adjustment.get_value();
-       jack_nframes_t sr = _session.frame_rate();
-       jack_nframes_t adj_frames = (jack_nframes_t) floor (msecs * (sr/1000.0f));
-       jack_nframes_t frames;
-       bool x;
-       if (adj_frames != (frames = (jack_nframes_t) _region.fade_out().back()->when)) {
-               fade_out_length_adjustment.set_value ((frames * 1000.0f) / sr);
-       }
-
-       if ((x = _region.fade_out_active()) != fade_out_active_button.get_active()) {
-               fade_out_active_button.set_active (x);
-       }
-}
-
-void
-AudioRegionEditor::fade_in_length_adjustment_changed ()
-{
-       jack_nframes_t fade_length = (jack_nframes_t) floor (fade_in_length_adjustment.get_value() * _session.frame_rate() * 0.001); 
-       fade_length = max (fade_length, (jack_nframes_t) 64);
-       fade_length = min (fade_length, _region.length());
-       
-       _region.set_fade_in_length (fade_length);
-       /* region is frozen, no worries */
-       fade_in_changed();
-}
-
-void
-AudioRegionEditor::fade_out_length_adjustment_changed ()
-{
-       jack_nframes_t fade_length = (jack_nframes_t) floor (fade_out_length_adjustment.get_value() * _session.frame_rate() * 0.001); 
-       fade_length = max (fade_length, (jack_nframes_t) 64);
-       fade_length = min (fade_length, _region.length());
-       
-       _region.set_fade_out_length (fade_length);      
-       /* region is frozen, no worries */
-       fade_out_changed();
-}
-
-void
-AudioRegionEditor::fade_in_active_toggled ()
-{
-       _region.set_fade_in_active (fade_in_active_button.get_active());
-}
-
-void
-AudioRegionEditor::fade_out_active_toggled ()
-{
-       _region.set_fade_out_active (fade_out_active_button.get_active());
-}
-
-void
-AudioRegionEditor::fade_out_active_changed ()
-{
-       bool x;
-
-       if ((x = _region.fade_out_active()) != fade_out_active_button.get_active()) {
-               fade_out_active_button.set_active (x);
-       }
-}
-
-void
-AudioRegionEditor::fade_in_active_changed ()
-{
-       bool x;
-
-       if ((x = _region.fade_in_active()) != fade_in_active_button.get_active()) {
-               fade_in_active_button.set_active (x);
-       }
-}
-
-void
-AudioRegionEditor::audition_state_changed (bool yn)
-{
-       ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionEditor::audition_state_changed), yn));
-
-       if (!yn) {
-               audition_button.set_active (false);
-       }
-}
-
index 65b0bbaa9478322a7e845a71e18d5c5cfc93126d..70590b0db5886e155507c0e17e7e09da343e1d2c 100644 (file)
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id$
+    $Id: /local/undo/gtk2_ardour/region_editor.h 5 2006-05-31T02:48:48.738745Z paul  $
 */
 
 #ifndef __gtk_ardour_region_edit_h__
 #define __gtk_ardour_region_edit_h__
 
-#include <map>
-
-#include <gtkmm/label.h>
-#include <gtkmm/entry.h>
-#include <gtkmm/box.h>
-#include <gtkmm/togglebutton.h>
-#include <gtkmm/button.h>
-#include <gtkmm/arrow.h>
-#include <gtkmm/frame.h>
-#include <gtkmm/table.h>
-#include <gtkmm/alignment.h>
-#include <gtkmm/adjustment.h>
-#include <gtkmm/separator.h>
-#include <gtkmm/spinbutton.h>
-
-#include <libgnomecanvas/libgnomecanvas.h>
-#include <sigc++/signal.h>
-
-#include "audio_clock.h"
 #include "ardour_dialog.h"
 
-namespace ARDOUR {
-       class AudioRegion;
-       class Session;
-}
-
-class AudioRegionView;
+namespace ARDOUR { class Session; }
 
-class AudioRegionEditor : public ArdourDialog
+/** Just a useless stub for now... */
+class RegionEditor : public ArdourDialog
 {
   public:
-       AudioRegionEditor (ARDOUR::Session&, ARDOUR::AudioRegion&, AudioRegionView& rv);
-       ~AudioRegionEditor ();
-
-  private:
-       ARDOUR::Session& _session;
-       ARDOUR::AudioRegion& _region;
-       AudioRegionView& _region_view;
-
-       void connect_editor_events ();
-
-       Gtk::Label name_label;
-       Gtk::Entry name_entry;
-       Gtk::HBox  name_hbox;
-
-       Gtk::HBox  top_row_hbox;
-       Gtk::HBox  top_row_button_hbox;
-
-       Gtk::ToggleButton lock_button;
-       Gtk::ToggleButton mute_button;
-       Gtk::ToggleButton opaque_button;
-       Gtk::ToggleButton envelope_active_button;
-       Gtk::ToggleButton envelope_view_button;
-
-       Gtk::Button       raise_button;
-       Gtk::Arrow        raise_arrow;
-       Gtk::Button       lower_button;
-       Gtk::Arrow        lower_arrow;
-       Gtk::Frame        layer_frame;
-       Gtk::Label        layer_value_label;
-       Gtk::Label        layer_label;
-       Gtk::HBox         layer_hbox;
-
-       Gtk::ToggleButton  audition_button;
-
-       Gtk::HBox  lower_hbox;
-       
-       Gtk::Table time_table;
-
-       Gtk::Label start_label;
-       Gtk::Label end_label;
-       Gtk::Label length_label;
-       Gtk::Alignment start_alignment;
-       Gtk::Alignment end_alignment;
-       Gtk::Alignment length_alignment;
-
-       AudioClock start_clock;
-       AudioClock end_clock;
-       AudioClock length_clock;
-       AudioClock sync_offset_clock;
-
-       Gtk::Table  envelope_loop_table;
-       Gtk::Button loop_button;
-       Gtk::Label  loop_label;
-       Gtk::Label  envelope_label;
-
-       Gtk::Table fade_in_table;
-       Gtk::Label fade_in_label;
-       Gtk::Alignment fade_in_label_align;
-       Gtk::Label fade_in_active_button_label;
-       Gtk::ToggleButton fade_in_active_button;
-       Gtk::Label fade_in_length_label;
-
-       Gtk::Adjustment fade_in_length_adjustment;
-       Gtk::SpinButton fade_in_length_spinner;
-
-       Gtk::Table fade_out_table;
-       Gtk::Label fade_out_label;
-       Gtk::Alignment fade_out_label_align;
-       Gtk::Label fade_out_active_button_label;
-       Gtk::ToggleButton fade_out_active_button;
-       Gtk::Label fade_out_length_label;
-
-       Gtk::Adjustment fade_out_length_adjustment;
-       Gtk::SpinButton fade_out_length_spinner;
-
-       Gtk::HSeparator sep3;
-       Gtk::VSeparator sep1;
-       Gtk::VSeparator sep2;
-
-       void region_changed (ARDOUR::Change);
-       void bounds_changed (ARDOUR::Change);
-       void name_changed ();
-       void opacity_changed ();
-       void mute_changed ();
-       void envelope_active_changed ();
-       void lock_changed ();
-       void layer_changed ();
-
-       void fade_in_length_adjustment_changed ();
-       void fade_out_length_adjustment_changed ();
-       void fade_in_changed ();
-       void fade_out_changed ();
-       void audition_state_changed (bool);
-
-       void activation ();
-
-       void name_entry_changed ();
-       void start_clock_changed ();
-       void end_clock_changed ();
-       void length_clock_changed ();
-
-       gint envelope_active_button_press (GdkEventButton *);
-       gint envelope_active_button_release (GdkEventButton *);
-
-       void audition_button_toggled ();
-       void envelope_view_button_toggled ();
-       void lock_button_clicked ();
-       void mute_button_clicked ();
-       void opaque_button_clicked ();
-       void raise_button_clicked ();
-       void lower_button_clicked ();
-
-       void fade_in_active_toggled ();
-       void fade_out_active_toggled ();
-       void fade_in_active_changed ();
-       void fade_out_active_changed ();
-
-       void fade_in_realized ();
-       void fade_out_realized ();
-
-       void start_editing_fade_in ();
-       void start_editing_fade_out ();
-       void stop_editing_fade_in ();
-       void stop_editing_fade_out ();
+       RegionEditor(ARDOUR::Session& s)
+       : ArdourDialog ("region editor")
+       , _session(s)
+       {}
 
-       gint bpressed (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)());
-       gint breleased (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)());
+       virtual ~RegionEditor () {}
 
-       bool spin_arrow_grab;
+  protected:
+       ARDOUR::Session&     _session;
 };
 
 #endif /* __gtk_ardour_region_edit_h__ */
index ebcf65ceddc89647bc764b2855632ee5e8a9baf1..920d2cdca999a814f325d1b3da29956ff4a85782 100644 (file)
@@ -3,7 +3,7 @@
 #include <pbd/memento_command.h>
 
 #include "region_gain_line.h"
-#include "regionview.h"
+#include "audio_region_view.h"
 #include "utils.h"
 
 #include "time_axis_view.h"
@@ -47,8 +47,8 @@ void
 AudioRegionGainLine::start_drag (ControlPoint* cp, float fraction) 
 {
        AutomationLine::start_drag(cp,fraction);
-       if (!rv.region.envelope_active()) {
-                trackview.session().add_command(new MementoUndoCommand<AudioRegion>(rv.region, rv.region.get_state()));
+       if (!rv.audio_region().envelope_active()) {
+                trackview.session().add_command(new MementoUndoCommand<AudioRegion>(rv.audio_region(), rv.audio_region().get_state()));
                 rv.region.set_envelope_active(false);
        }
 }
@@ -64,11 +64,11 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
        trackview.editor.current_session()->begin_reversible_command (_("remove control point"));
         XMLNode &before = get_state();
 
-       if (!rv.region.envelope_active()) {
-                XMLNode &before = rv.region.get_state();
-               rv.region.set_envelope_active(true);
-                XMLNode &after = rv.region.get_state();
-                trackview.session().add_command(new MementoCommand<AudioRegion>(rv.region, before, after));
+       if (!rv.audio_region().envelope_active()) {
+                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);
@@ -81,9 +81,9 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
 void
 AudioRegionGainLine::end_drag (ControlPoint* cp) 
 {
-       if (!rv.region.envelope_active()) {
-               rv.region.set_envelope_active(true);
-                trackview.session().add_command(new MementoRedoCommand<AudioRegion>(rv.region, rv.region.get_state()));
+       if (!rv.audio_region().envelope_active()) {
+               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 751584cab7a5ddfe6ff9c13b308b1b6ef89c2eba..f8c9f384a9b13ce5069dc233b9cb756029016c2c 100644 (file)
@@ -1,8 +1,26 @@
+/*
+    Copyright (C) 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
+    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 <algorithm>
 
-#include <ardour/audioregion.h>
+#include <ardour/region.h>
 
-#include "regionview.h"
+#include "region_view.h"
 #include "region_selection.h"
 
 using namespace ARDOUR;
@@ -11,7 +29,7 @@ using namespace sigc;
 
 
 bool 
-AudioRegionComparator::operator() (const AudioRegionView* a, const AudioRegionView* b) const
+RegionComparator::operator() (const RegionView* a, const RegionView* b) const
 {
        if (a == b) {
                return false;
@@ -20,16 +38,16 @@ AudioRegionComparator::operator() (const AudioRegionView* a, const AudioRegionVi
        }
 }
 
-AudioRegionSelection::AudioRegionSelection ()
+RegionSelection::RegionSelection ()
 {
        _current_start = 0;
        _current_end = 0;
 }
 
-AudioRegionSelection::AudioRegionSelection (const AudioRegionSelection& other)
+RegionSelection::RegionSelection (const RegionSelection& other)
 {
 
-       for (AudioRegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
+       for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
                add (*i, false);
        }
        _current_start = other._current_start;
@@ -38,14 +56,14 @@ AudioRegionSelection::AudioRegionSelection (const AudioRegionSelection& other)
 
 
 
-AudioRegionSelection&
-AudioRegionSelection::operator= (const AudioRegionSelection& other)
+RegionSelection&
+RegionSelection::operator= (const RegionSelection& other)
 {
        if (this != &other) {
 
                clear_all();
                
-               for (AudioRegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
+               for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
                        add (*i, false);
                }
 
@@ -57,13 +75,13 @@ AudioRegionSelection::operator= (const AudioRegionSelection& other)
 }
 
 void
-AudioRegionSelection::clear_all()
+RegionSelection::clear_all()
 {
        clear();
        _bylayer.clear();
 }
 
-bool AudioRegionSelection::contains (AudioRegionView* rv)
+bool RegionSelection::contains (RegionView* rv)
 {
        if (this->find (rv) != end()) {
                return true;
@@ -75,21 +93,21 @@ bool AudioRegionSelection::contains (AudioRegionView* rv)
 }
 
 void
-AudioRegionSelection::add (AudioRegionView* rv, bool dosort)
+RegionSelection::add (RegionView* rv, bool dosort)
 {
        if (this->find (rv) != end()) {
                /* we already have it */
                return;
        }
 
-       rv->AudioRegionViewGoingAway.connect (mem_fun(*this, &AudioRegionSelection::remove_it));
+       rv->RegionViewGoingAway.connect (mem_fun(*this, &RegionSelection::remove_it));
 
-       if (rv->region.first_frame() < _current_start || empty()) {
-               _current_start = rv->region.first_frame();
+       if (rv->region().first_frame() < _current_start || empty()) {
+               _current_start = rv->region().first_frame();
        }
        
-       if (rv->region.last_frame() > _current_end || empty()) {
-               _current_end = rv->region.last_frame();
+       if (rv->region().last_frame() > _current_end || empty()) {
+               _current_end = rv->region().last_frame();
        }
        
        insert (rv);
@@ -100,15 +118,15 @@ AudioRegionSelection::add (AudioRegionView* rv, bool dosort)
 }
 
 void
-AudioRegionSelection::remove_it (AudioRegionView *rv)
+RegionSelection::remove_it (RegionView *rv)
 {
        remove (rv);
 }
 
 bool
-AudioRegionSelection::remove (AudioRegionView* rv)
+RegionSelection::remove (RegionView* rv)
 {
-       AudioRegionSelection::iterator i;
+       RegionSelection::iterator i;
 
        if ((i = this->find (rv)) != end()) {
 
@@ -124,7 +142,7 @@ AudioRegionSelection::remove (AudioRegionView* rv)
 
                } else {
                        
-                       AudioRegion& region ((*i)->region);
+                       Region& region ((*i)->region());
 
                        if (region.first_frame() == _current_start) {
                                
@@ -165,15 +183,15 @@ AudioRegionSelection::remove (AudioRegionView* rv)
 }
 
 void
-AudioRegionSelection::add_to_layer (AudioRegionView * rv)
+RegionSelection::add_to_layer (RegionView * rv)
 {
        // insert it into layer sorted position
 
-       list<AudioRegionView*>::iterator i;
+       list<RegionView*>::iterator i;
 
        for (i = _bylayer.begin(); i != _bylayer.end(); ++i)
        {
-               if (rv->region.layer() < (*i)->region.layer()) {
+               if (rv->region().layer() < (*i)->region().layer()) {
                        _bylayer.insert(i, rv);
                        return;
                }
@@ -184,16 +202,16 @@ AudioRegionSelection::add_to_layer (AudioRegionView * rv)
 }
 
 struct RegionSortByTime {
-    bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
-           return a->region.position() < b->region.position();
+    bool operator() (const RegionView* a, const RegionView* b) {
+           return a->region().position() < b->region().position();
     }
 };
 
 
 void
-AudioRegionSelection::by_position (list<AudioRegionView*>& foo) const
+RegionSelection::by_position (list<RegionView*>& foo) const
 {
-       list<AudioRegionView*>::const_iterator i;
+       list<RegionView*>::const_iterator i;
        RegionSortByTime sorter;
 
        for (i = _bylayer.begin(); i != _bylayer.end(); ++i) {
index 0c2b7be0255d73e42a807f834098c3099925735e..2192442cb0cbdf5ac0eb53435f1af27c5fdd3716 100644 (file)
@@ -1,3 +1,21 @@
+/*
+    Copyright (C) 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
+    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.
+*/
+
 #ifndef __ardour_gtk_region_selection_h__
 #define __ardour_gtk_region_selection_h__
 
 using std::list;
 using std::set;
 
-class AudioRegionView;
+class RegionView;
 
-struct AudioRegionComparator {
-    bool operator() (const AudioRegionView* a, const AudioRegionView* b) const;
+struct RegionComparator {
+    bool operator() (const RegionView* a, const RegionView* b) const;
 };
 
-class AudioRegionSelection : public set<AudioRegionView*, AudioRegionComparator>, public sigc::trackable
+class RegionSelection : public set<RegionView*, RegionComparator>, public sigc::trackable
 {
   public:
-        AudioRegionSelection();
-       AudioRegionSelection (const AudioRegionSelection&);
+       RegionSelection();
+       RegionSelection (const RegionSelection&);
 
-       AudioRegionSelection& operator= (const AudioRegionSelection&);
+       RegionSelection& operator= (const RegionSelection&);
 
-       void add (AudioRegionView*, bool dosort = true);
-       bool remove (AudioRegionView*);
-       bool contains (AudioRegionView*);
+       void add (RegionView*, bool dosort = true);
+       bool remove (RegionView*);
+       bool contains (RegionView*);
 
        void clear_all();
        
@@ -39,18 +57,18 @@ class AudioRegionSelection : public set<AudioRegionView*, AudioRegionComparator>
                return _current_end;
        }
 
-       const list<AudioRegionView *> & by_layer() const { return _bylayer; }
-       void  by_position (list<AudioRegionView*>&) const;
+       const list<RegionView *> & by_layer() const { return _bylayer; }
+       void  by_position (list<RegionView*>&) const;
        
   private:
-       void remove_it (AudioRegionView*);
+       void remove_it (RegionView*);
 
-       void add_to_layer (AudioRegionView *);
+       void add_to_layer (RegionView *);
        
        jack_nframes_t _current_start;
        jack_nframes_t _current_end;
 
-       list<AudioRegionView *> _bylayer;
+       list<RegionView *> _bylayer;
 };
 
 #endif /* __ardour_gtk_region_selection_h__ */
diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc
new file mode 100644 (file)
index 0000000..ebec426
--- /dev/null
@@ -0,0 +1,494 @@
+/*
+    Copyright (C) 2001-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
+    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: regionview.cc 691 2006-07-23 12:03:19Z drobilla $
+*/
+
+#include <cmath>
+#include <cassert>
+#include <algorithm>
+
+#include <gtkmm.h>
+
+#include <gtkmm2ext/gtk_ui.h>
+
+#include <ardour/playlist.h>
+#include <ardour/audioregion.h>
+#include <ardour/audiosource.h>
+#include <ardour/audio_diskstream.h>
+
+#include "streamview.h"
+#include "region_view.h"
+#include "route_time_axis.h"
+#include "simplerect.h"
+#include "simpleline.h"
+#include "waveview.h"
+#include "public_editor.h"
+#include "region_editor.h"
+#include "ghostregion.h"
+#include "route_time_axis.h"
+#include "utils.h"
+#include "rgb_macros.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace sigc;
+using namespace ARDOUR;
+using namespace PBD;
+using namespace Editing;
+using namespace ArdourCanvas;
+
+static const int32_t sync_mark_width = 9;
+
+sigc::signal<void,RegionView*> RegionView::RegionViewGoingAway;
+
+RegionView::RegionView (ArdourCanvas::Group* parent, 
+                        TimeAxisView&        tv,
+                        ARDOUR::Region&      r,
+                        double               spu,
+                        Gdk::Color&          basic_color)
+       : TimeAxisViewItem (r.name(), *parent, tv, spu, basic_color, r.position(), r.length(),
+                       TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText|
+                                                     TimeAxisViewItem::ShowNameHighlight|
+                                                     TimeAxisViewItem::ShowFrame))
+       , _region (r)
+       , sync_mark(0)
+       , no_wave_msg(0)
+       , editor(0)
+       , current_visible_sync_position(0.0)
+       , valid(false)
+       , _pixel_width(1.0)
+       , _height(1.0)
+       , in_destructor(false)
+       , wait_for_data(false)
+{
+}
+
+RegionView::RegionView (ArdourCanvas::Group*         parent, 
+                        TimeAxisView&                tv,
+                        ARDOUR::Region&              r,
+                        double                       spu,
+                        Gdk::Color&                  basic_color,
+                        TimeAxisViewItem::Visibility visibility)
+       : TimeAxisViewItem (r.name(), *parent, tv, spu, basic_color, r.position(), r.length(), visibility)
+       , _region (r)
+       , sync_mark(0)
+       , no_wave_msg(0)
+       , editor(0)
+       , current_visible_sync_position(0.0)
+       , valid(false)
+       , _pixel_width(1.0)
+       , _height(1.0)
+       , in_destructor(false)
+       , wait_for_data(false)
+{
+}
+
+void
+RegionView::init (Gdk::Color& basic_color, bool wfd)
+{
+       editor        = 0;
+       valid         = true;
+       in_destructor = false;
+       _height       = 0;
+       wait_for_data = wfd;
+
+       compute_colors (basic_color);
+
+       name_highlight->set_data ("regionview", this);
+       name_text->set_data ("regionview", this);
+
+       /* an equilateral triangle */
+    ArdourCanvas::Points shape;
+       shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1));
+       shape.push_back (Gnome::Art::Point ((sync_mark_width - 1)/2, 1));
+       shape.push_back (Gnome::Art::Point (0, sync_mark_width - 1));
+       shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1));
+
+       sync_mark =  new ArdourCanvas::Polygon (*group);
+       sync_mark->property_points() = shape;
+       sync_mark->property_fill_color_rgba() = fill_color;
+       sync_mark->hide();
+
+       reset_width_dependent_items ((double) _region.length() / samples_per_unit);
+
+       set_height (trackview.height);
+
+       region_muted ();
+       region_sync_changed ();
+       region_resized (BoundsChanged);
+       region_locked ();
+
+       _region.StateChanged.connect (mem_fun(*this, &RegionView::region_changed));
+
+       group->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_event), group, this));
+       name_highlight->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_name_highlight_event), name_highlight, this));
+
+       set_colors ();
+
+       ColorChanged.connect (mem_fun (*this, &RegionView::color_handler));
+
+       /* XXX sync mark drag? */
+}
+
+RegionView::~RegionView ()
+{
+       in_destructor = true;
+
+       RegionViewGoingAway (this); /* EMIT_SIGNAL */
+
+       for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
+               delete *g;
+       }
+
+       if (editor) {
+               delete editor;
+       }
+}
+
+gint
+RegionView::_lock_toggle (ArdourCanvas::Item* item, GdkEvent* ev, void* arg)
+{
+       switch (ev->type) {
+       case GDK_BUTTON_RELEASE:
+               static_cast<RegionView*>(arg)->lock_toggle ();
+               return TRUE;
+               break;
+       default:
+               break;
+       } 
+       return FALSE;
+}
+
+void
+RegionView::lock_toggle ()
+{
+       _region.set_locked (!_region.locked());
+}
+
+void
+RegionView::region_changed (Change what_changed)
+{
+       ENSURE_GUI_THREAD (bind (mem_fun(*this, &RegionView::region_changed), what_changed));
+
+       if (what_changed & BoundsChanged) {
+               region_resized (what_changed);
+               region_sync_changed ();
+       }
+       if (what_changed & Region::MuteChanged) {
+               region_muted ();
+       }
+       if (what_changed & Region::OpacityChanged) {
+               region_opacity ();
+       }
+       if (what_changed & ARDOUR::NameChanged) {
+               region_renamed ();
+       }
+       if (what_changed & Region::SyncOffsetChanged) {
+               region_sync_changed ();
+       }
+       if (what_changed & Region::LayerChanged) {
+               region_layered ();
+       }
+       if (what_changed & Region::LockChanged) {
+               region_locked ();
+       }
+}
+
+void
+RegionView::region_locked ()
+{
+       /* name will show locked status */
+       region_renamed ();
+}
+
+void
+RegionView::region_resized (Change what_changed)
+{
+       double unit_length;
+
+       if (what_changed & ARDOUR::PositionChanged) {
+               set_position (_region.position(), 0);
+       }
+
+       if (what_changed & Change (StartChanged|LengthChanged)) {
+
+               set_duration (_region.length(), 0);
+
+               unit_length = _region.length() / samples_per_unit;
+               
+               reset_width_dependent_items (unit_length);
+               
+               for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+
+                       (*i)->set_duration (unit_length);
+
+               }
+       }
+}
+
+void
+RegionView::reset_width_dependent_items (double pixel_width)
+{
+       TimeAxisViewItem::reset_width_dependent_items (pixel_width);
+       _pixel_width = pixel_width;
+}
+
+void
+RegionView::region_layered ()
+{
+       RouteTimeAxisView *rtv = dynamic_cast<RouteTimeAxisView*>(&get_time_axis_view());
+       assert(rtv);
+       rtv->view()->region_layered (this);
+}
+       
+void
+RegionView::region_muted ()
+{
+       set_frame_color ();
+       region_renamed ();
+}
+
+void
+RegionView::region_opacity ()
+{
+       set_frame_color ();
+}
+
+void
+RegionView::raise ()
+{
+       _region.raise ();
+}
+
+void
+RegionView::raise_to_top ()
+{
+       _region.raise_to_top ();
+}
+
+void
+RegionView::lower ()
+{
+       _region.lower ();
+}
+
+void
+RegionView::lower_to_bottom ()
+{
+       _region.lower_to_bottom ();
+}
+
+bool
+RegionView::set_position (jack_nframes_t pos, void* src, double* ignored)
+{
+       double delta;
+       bool ret;
+
+       if (!(ret = TimeAxisViewItem::set_position (pos, this, &delta))) {
+               return false;
+       }
+
+       if (ignored) {
+               *ignored = delta;
+       }
+
+       if (delta) {
+               for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+                       (*i)->group->move (delta, 0.0);
+               }
+       }
+
+       return ret;
+}
+
+void
+RegionView::set_samples_per_unit (gdouble spu)
+{
+       TimeAxisViewItem::set_samples_per_unit (spu);
+
+       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+               (*i)->set_samples_per_unit (spu);
+               (*i)->set_duration (_region.length() / samples_per_unit);
+       }
+
+       region_sync_changed ();
+}
+
+bool
+RegionView::set_duration (jack_nframes_t frames, void *src)
+{
+       if (!TimeAxisViewItem::set_duration (frames, src)) {
+               return false;
+       }
+       
+       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+               (*i)->set_duration (_region.length() / samples_per_unit);
+       }
+
+       return true;
+}
+
+void
+RegionView::compute_colors (Gdk::Color& basic_color)
+{
+       TimeAxisViewItem::compute_colors (basic_color);
+}
+
+void
+RegionView::set_colors ()
+{
+       TimeAxisViewItem::set_colors ();
+       
+       if (sync_mark) {
+               sync_mark->property_fill_color_rgba() = fill_color;
+       }
+}
+
+void
+RegionView::set_frame_color ()
+{
+       if (_region.opaque()) {
+               fill_opacity = 180;
+       } else {
+               fill_opacity = 100;
+       }
+
+       TimeAxisViewItem::set_frame_color ();
+}
+
+void
+RegionView::hide_region_editor()
+{
+       if (editor) {
+               editor->hide_all ();
+       }
+}
+
+void
+RegionView::region_renamed ()
+{
+       string str;
+
+       if (_region.locked()) {
+               str += '>';
+               str += _region.name();
+               str += '<';
+       } else {
+               str = _region.name();
+       }
+
+       if (_region.speed_mismatch (trackview.session().frame_rate())) {
+               str = string ("*") + str;
+       }
+
+       if (_region.muted()) {
+               str = string ("!") + str;
+       }
+
+       set_item_name (str, this);
+       set_name_text (str);
+}
+
+void
+RegionView::region_sync_changed ()
+{
+       if (sync_mark == 0) {
+               return;
+       }
+
+       int sync_dir;
+       jack_nframes_t sync_offset;
+
+       sync_offset = _region.sync_offset (sync_dir);
+
+       /* this has to handle both a genuine change of position, a change of samples_per_unit,
+          and a change in the bounds of the _region.
+        */
+
+       if (sync_offset == 0) {
+
+               /* no sync mark - its the start of the region */
+
+               sync_mark->hide();
+
+       } else {
+
+               if ((sync_dir < 0) || ((sync_dir > 0) && (sync_offset > _region.length()))) { 
+
+                       /* no sync mark - its out of the bounds of the region */
+
+                       sync_mark->hide();
+
+               } else {
+
+                       /* lets do it */
+
+                       Points points;
+                       
+                       //points = sync_mark->property_points().get_value();
+                       
+                       double offset = sync_offset / samples_per_unit;
+                       points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1));
+                       points.push_back (Gnome::Art::Point (offset + ((sync_mark_width-1)/2), 1));
+                       points.push_back (Gnome::Art::Point (offset, sync_mark_width - 1));
+                       points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1));     
+                       sync_mark->property_points().set_value (points);
+                       sync_mark->show();
+
+               }
+       }
+}
+
+void
+RegionView::move (double x_delta, double y_delta)
+{
+       if (_region.locked() || (x_delta == 0 && y_delta == 0)) {
+               return;
+       }
+
+       get_canvas_group()->move (x_delta, y_delta);
+
+       /* note: ghosts never leave their tracks so y_delta for them is always zero */
+
+       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+               (*i)->group->move (x_delta, 0.0);
+       }
+}
+
+void
+RegionView::remove_ghost (GhostRegion* ghost)
+{
+       if (in_destructor) {
+               return;
+       }
+
+       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+               if (*i == ghost) {
+                       ghosts.erase (i);
+                       break;
+               }
+       }
+}
+
+uint32_t
+RegionView::get_fill_color ()
+{
+       return fill_color;
+}
+
diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h
new file mode 100644 (file)
index 0000000..fdc69ea
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+    Copyright (C) 2001-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
+    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.
+*/
+
+#ifndef __gtk_ardour_region_view_h__
+#define __gtk_ardour_region_view_h__
+
+#include <vector>
+
+#include <libgnomecanvasmm.h>
+#include <libgnomecanvasmm/polygon.h>
+#include <sigc++/signal.h>
+#include <ardour/region.h>
+
+#include "time_axis_view_item.h"
+#include "automation_line.h"
+#include "enums.h"
+#include "waveview.h"
+#include "canvas.h"
+#include "color.h"
+
+class TimeAxisView;
+class RegionEditor;
+class GhostRegion;
+class AutomationTimeAxisView;
+
+class RegionView : public TimeAxisViewItem
+{
+  public:
+       RegionView (ArdourCanvas::Group* parent, 
+                   TimeAxisView&        time_view,
+                   ARDOUR::Region&      region,
+                   double               samples_per_unit,
+                   Gdk::Color&          basic_color);
+
+       ~RegionView ();
+       
+       virtual void init (Gdk::Color& base_color, bool wait_for_data);
+    
+       ARDOUR::Region& region() const { return _region; }
+       
+       bool is_valid() const    { return valid; }
+    void set_valid (bool yn) { valid = yn; }
+
+    virtual void set_height (double) = 0;
+    virtual void set_samples_per_unit (double);
+    virtual bool set_duration (jack_nframes_t, void*);
+
+    void move (double xdelta, double ydelta);
+
+    void raise ();
+    void raise_to_top ();
+    void lower ();
+    void lower_to_bottom ();
+
+    bool set_position(jack_nframes_t pos, void* src, double* delta = 0);
+
+    virtual void show_region_editor () = 0;
+    virtual void hide_region_editor();
+
+    virtual void region_changed (ARDOUR::Change);
+
+    virtual GhostRegion* add_ghost (AutomationTimeAxisView&) = 0;
+    void                 remove_ghost (GhostRegion*);
+
+    uint32_t get_fill_color ();
+
+    virtual void entered () {}
+    virtual void exited () {}
+    
+       static sigc::signal<void,RegionView*> RegionViewGoingAway;
+    sigc::signal<void>                    GoingAway;
+
+  protected:
+
+    /** Allows derived types to specify their visibility requirements
+     * to the TimeAxisViewItem parent class
+        */
+    RegionView (ArdourCanvas::Group *, 
+                   TimeAxisView&,
+                   ARDOUR::Region&,
+                   double      samples_per_unit,
+                   Gdk::Color& basic_color,
+                   TimeAxisViewItem::Visibility);
+
+    virtual void region_resized (ARDOUR::Change);
+    void         region_moved (void *);
+    virtual void region_muted ();
+    void         region_locked ();
+    void         region_opacity ();
+    void         region_layered ();
+    void         region_renamed ();
+    void         region_sync_changed ();
+
+    static gint _lock_toggle (ArdourCanvas::Item*, GdkEvent*, void*);
+    void        lock_toggle ();
+
+    virtual void set_colors ();
+    virtual void compute_colors (Gdk::Color&);
+    virtual void set_frame_color ();
+    virtual void reset_width_dependent_items (double pixel_width);
+    
+    virtual void color_handler (ColorID, uint32_t) {}
+       
+       ARDOUR::Region& _region;
+    
+    ArdourCanvas::Polygon* sync_mark; ///< polgyon for sync position 
+    ArdourCanvas::Text*    no_wave_msg;
+
+    RegionEditor* editor;
+
+    vector<ControlPoint *> control_points;
+    double current_visible_sync_position;
+
+    bool     valid; ///< see StreamView::redisplay_diskstream() 
+    double  _pixel_width;
+    double  _height;
+    bool    in_destructor;
+
+    bool             wait_for_data;
+       sigc::connection data_ready_connection;
+    
+       vector<GhostRegion*> ghosts;
+};
+
+#endif /* __gtk_ardour_region_view_h__ */
diff --git a/gtk2_ardour/regionview.cc b/gtk2_ardour/regionview.cc
deleted file mode 100644 (file)
index dcc71a0..0000000
+++ /dev/null
@@ -1,1411 +0,0 @@
-/*
-    Copyright (C) 2001 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$
-*/
-
-#include <cmath>
-#include <algorithm>
-
-#include <gtkmm.h>
-
-#include <gtkmm2ext/gtk_ui.h>
-
-#include <ardour/playlist.h>
-#include <ardour/audioregion.h>
-#include <ardour/audiosource.h>
-#include <ardour/audio_diskstream.h>
-#include <pbd/memento_command.h>
-
-#include "streamview.h"
-#include "regionview.h"
-#include "audio_time_axis.h"
-#include "simplerect.h"
-#include "simpleline.h"
-#include "waveview.h"
-#include "public_editor.h"
-#include "region_editor.h"
-#include "region_gain_line.h"
-#include "ghostregion.h"
-#include "audio_time_axis.h"
-#include "utils.h"
-#include "rgb_macros.h"
-#include "gui_thread.h"
-
-#include "i18n.h"
-
-using namespace sigc;
-using namespace ARDOUR;
-using namespace PBD;
-using namespace Editing;
-using namespace ArdourCanvas;
-
-static const int32_t sync_mark_width = 9;
-
-sigc::signal<void,AudioRegionView*> AudioRegionView::AudioRegionViewGoingAway;
-
-AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, AudioTimeAxisView &tv, AudioRegion& r, double spu,
-                                 Gdk::Color& basic_color)
-       : TimeAxisViewItem (r.name(), *parent, tv, spu, basic_color, r.position(), r.length(),
-                           TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText|
-                                                         TimeAxisViewItem::ShowNameHighlight|
-                                                         TimeAxisViewItem::ShowFrame)),
-         region (r)
-{
-}
-
-AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, AudioTimeAxisView &tv, AudioRegion& r, double spu, 
-                                 Gdk::Color& basic_color, TimeAxisViewItem::Visibility visibility)
-       : TimeAxisViewItem (r.name(), *parent, tv, spu, basic_color, r.position(), r.length(), visibility),
-         region (r)
-{
-}
-
-void
-AudioRegionView::init (double amplitude_above_axis, Gdk::Color& basic_color, bool wfw)
-{
-        ArdourCanvas::Points shape;
-       XMLNode *node;
-
-       editor = 0;
-       valid = true;
-       in_destructor = false;
-       _amplitude_above_axis = amplitude_above_axis;
-       zero_line = 0;
-       wait_for_waves = wfw;
-       _height = 0;
-
-       _flags = 0;
-
-       if ((node = region.extra_xml ("GUI")) != 0) {
-               set_flags (node);
-       } else {
-               _flags = WaveformVisible;
-               store_flags ();
-       }
-
-       if (trackview.editor.new_regionviews_display_gain()) {
-               _flags |= EnvelopeVisible;
-       }
-
-       compute_colors (basic_color);
-
-       create_waves ();
-
-       name_highlight->set_data ("regionview", this);
-       name_text->set_data ("regionview", this);
-
-       //      shape = new ArdourCanvas::Points ();
-
-       /* an equilateral triangle */
-
-       shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1));
-       shape.push_back (Gnome::Art::Point ((sync_mark_width - 1)/2, 1));
-       shape.push_back (Gnome::Art::Point (0, sync_mark_width - 1));
-       shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1));
-
-       sync_mark =  new ArdourCanvas::Polygon (*group);
-       sync_mark->property_points() = shape;
-       sync_mark->property_fill_color_rgba() = fill_color;
-       sync_mark->hide();
-
-       fade_in_shape = new ArdourCanvas::Polygon (*group);
-       fade_in_shape->property_fill_color_rgba() = fade_color;
-       fade_in_shape->set_data ("regionview", this);
-       
-       fade_out_shape = new ArdourCanvas::Polygon (*group);
-       fade_out_shape->property_fill_color_rgba() = fade_color;
-       fade_out_shape->set_data ("regionview", this);
-
-
-       {
-               uint32_t r,g,b,a;
-               UINT_TO_RGBA(fill_color,&r,&g,&b,&a);
-       
-
-               fade_in_handle = new ArdourCanvas::SimpleRect (*group);
-               fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,0);
-               fade_in_handle->property_outline_pixels() = 0;
-               fade_in_handle->property_y1() = 2.0;
-               fade_in_handle->property_y2() = 7.0;
-               
-               fade_in_handle->set_data ("regionview", this);
-               
-               fade_out_handle = new ArdourCanvas::SimpleRect (*group);
-               fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,0);
-               fade_out_handle->property_outline_pixels() = 0;
-               fade_out_handle->property_y1() = 2.0;
-               fade_out_handle->property_y2() = 7.0;
-               
-               fade_out_handle->set_data ("regionview", this);
-       }
-
-       string foo = region.name();
-       foo += ':';
-       foo += "gain";
-
-       gain_line = new AudioRegionGainLine (foo, trackview.session(), *this, *group, region.envelope());
-
-       if (!(_flags & EnvelopeVisible)) {
-               gain_line->hide ();
-       } else {
-               gain_line->show ();
-       }
-
-       reset_width_dependent_items ((double) region.length() / samples_per_unit);
-
-       gain_line->reset ();
-
-       set_height (trackview.height);
-
-       region_muted ();
-       region_sync_changed ();
-       region_resized (BoundsChanged);
-       set_waveview_data_src();
-       region_locked ();
-       envelope_active_changed ();
-       fade_in_active_changed ();
-       fade_out_active_changed ();
-
-       region.StateChanged.connect (mem_fun(*this, &AudioRegionView::region_changed));
-
-       group->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_event), group, this));
-       name_highlight->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_name_highlight_event), name_highlight, this));
-       fade_in_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_event), fade_in_shape, this));
-       fade_in_handle->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_handle_event), fade_in_handle, this));
-       fade_out_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_event), fade_out_shape, this));
-       fade_out_handle->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_handle_event), fade_out_handle, this));
-
-       set_colors ();
-
-       ColorChanged.connect (mem_fun (*this, &AudioRegionView::color_handler));
-
-       /* XXX sync mark drag? */
-}
-
-AudioRegionView::~AudioRegionView ()
-{
-       in_destructor = true;
-
-       AudioRegionViewGoingAway (this); /* EMIT_SIGNAL */
-
-       for (vector<GnomeCanvasWaveViewCache *>::iterator cache = wave_caches.begin(); cache != wave_caches.end() ; ++cache) {
-               gnome_canvas_waveview_cache_destroy (*cache);
-       }
-
-       /* all waveviews etc will be destroyed when the group is destroyed */
-
-       for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
-               delete *g;
-       }
-
-       if (editor) {
-               delete editor;
-       }
-
-       if (gain_line) {
-               delete gain_line;
-       }
-}
-
-gint
-AudioRegionView::_lock_toggle (ArdourCanvas::Item* item, GdkEvent* ev, void* arg)
-{
-       switch (ev->type) {
-       case GDK_BUTTON_RELEASE:
-               static_cast<AudioRegionView*>(arg)->lock_toggle ();
-               return TRUE;
-               break;
-       default:
-               break;
-       } 
-       return FALSE;
-}
-
-void
-AudioRegionView::lock_toggle ()
-{
-       region.set_locked (!region.locked());
-}
-
-void
-AudioRegionView::region_changed (Change what_changed)
-{
-       ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionView::region_changed), what_changed));
-
-       if (what_changed & BoundsChanged) {
-               region_resized (what_changed);
-               region_sync_changed ();
-       }
-       if (what_changed & Region::MuteChanged) {
-               region_muted ();
-       }
-       if (what_changed & Region::OpacityChanged) {
-               region_opacity ();
-       }
-       if (what_changed & ARDOUR::NameChanged) {
-               region_renamed ();
-       }
-       if (what_changed & Region::SyncOffsetChanged) {
-               region_sync_changed ();
-       }
-       if (what_changed & Region::LayerChanged) {
-               region_layered ();
-       }
-       if (what_changed & Region::LockChanged) {
-               region_locked ();
-       }
-       if (what_changed & AudioRegion::ScaleAmplitudeChanged) {
-               region_scale_amplitude_changed ();
-       }
-       if (what_changed & AudioRegion::FadeInChanged) {
-               fade_in_changed ();
-       }
-       if (what_changed & AudioRegion::FadeOutChanged) {
-               fade_out_changed ();
-       }
-       if (what_changed & AudioRegion::FadeInActiveChanged) {
-               fade_in_active_changed ();
-       }
-       if (what_changed & AudioRegion::FadeOutActiveChanged) {
-               fade_out_active_changed ();
-       }
-       if (what_changed & AudioRegion::EnvelopeActiveChanged) {
-               envelope_active_changed ();
-       }
-}
-
-void
-AudioRegionView::fade_in_changed ()
-{
-       reset_fade_in_shape ();
-}
-
-void
-AudioRegionView::fade_out_changed ()
-{
-       reset_fade_out_shape ();
-}
-
-void
-AudioRegionView::set_fade_in_active (bool yn)
-{
-       region.set_fade_in_active (yn);
-}
-
-void
-AudioRegionView::set_fade_out_active (bool yn)
-{
-       region.set_fade_out_active (yn);
-}
-
-void
-AudioRegionView::fade_in_active_changed ()
-{
-       uint32_t r,g,b,a;
-       uint32_t col;
-       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
-
-       if (region.fade_in_active()) {
-               col = RGBA_TO_UINT(r,g,b,120);
-               fade_in_shape->property_fill_color_rgba() = col;
-               fade_in_shape->property_width_pixels() = 0;
-               fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,0);
-       } else { 
-               col = RGBA_TO_UINT(r,g,b,0);
-               fade_in_shape->property_fill_color_rgba() = col;
-               fade_in_shape->property_width_pixels() = 1;
-               fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,255);
-       }
-}
-
-void
-AudioRegionView::fade_out_active_changed ()
-{
-       uint32_t r,g,b,a;
-       uint32_t col;
-       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
-
-       if (region.fade_out_active()) {
-               col = RGBA_TO_UINT(r,g,b,120);
-               fade_out_shape->property_fill_color_rgba() = col;
-               fade_out_shape->property_width_pixels() = 0;
-               fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,0);
-       } else { 
-               col = RGBA_TO_UINT(r,g,b,0);
-               fade_out_shape->property_fill_color_rgba() = col;
-               fade_out_shape->property_width_pixels() = 1;
-               fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,255);
-       }
-}
-
-
-void
-AudioRegionView::region_scale_amplitude_changed ()
-{
-       ENSURE_GUI_THREAD (mem_fun(*this, &AudioRegionView::region_scale_amplitude_changed));
-
-       for (uint32_t n = 0; n < waves.size(); ++n) {
-               // force a reload of the cache
-               waves[n]->property_data_src() = &region;
-       }
-}
-
-void
-AudioRegionView::region_locked ()
-{
-       /* name will show locked status */
-       region_renamed ();
-}
-
-void
-AudioRegionView::region_resized (Change what_changed)
-{
-       double unit_length;
-
-       if (what_changed & ARDOUR::PositionChanged) {
-               set_position (region.position(), 0);
-       }
-
-       if (what_changed & Change (StartChanged|LengthChanged)) {
-
-               set_duration (region.length(), 0);
-
-               unit_length = region.length() / samples_per_unit;
-               
-               reset_width_dependent_items (unit_length);
-               
-               for (uint32_t n = 0; n < waves.size(); ++n) {
-                       waves[n]->property_region_start() = region.start();
-               }
-               
-               for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-
-                       (*i)->set_duration (unit_length);
-
-                       for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
-                               (*w)->property_region_start() = region.start();
-                       }
-               }
-       }
-}
-
-void
-AudioRegionView::reset_width_dependent_items (double pixel_width)
-{
-       TimeAxisViewItem::reset_width_dependent_items (pixel_width);
-       _pixel_width = pixel_width;
-
-       if (zero_line) {
-               zero_line->property_x2() = pixel_width - 1.0;
-       }
-
-       if (fade_in_handle) {
-               if (pixel_width <= 6.0) {
-                       fade_in_handle->hide();
-                       fade_out_handle->hide();
-               } else {
-                       if (_height < 5.0) {
-                               fade_in_handle->hide();
-                               fade_out_handle->hide();
-                       } else {
-                               fade_in_handle->show();
-                               fade_out_handle->show();
-                       }
-               }
-       }
-
-       reset_fade_shapes ();
-}
-
-void
-AudioRegionView::region_layered ()
-{
-       AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (&get_time_axis_view());
-       atv->view->region_layered (this);
-}
-       
-void
-AudioRegionView::region_muted ()
-{
-       set_frame_color ();
-       region_renamed ();
-
-       for (uint32_t n=0; n < waves.size(); ++n) {
-               if (region.muted()) {
-                       waves[n]->property_wave_color() = color_map[cMutedWaveForm];
-               } else {
-                       waves[n]->property_wave_color() = color_map[cWaveForm];
-               }
-       }
-}
-
-void
-AudioRegionView::region_opacity ()
-{
-       set_frame_color ();
-}
-
-void
-AudioRegionView::raise ()
-{
-       region.raise ();
-}
-
-void
-AudioRegionView::raise_to_top ()
-{
-       region.raise_to_top ();
-}
-
-void
-AudioRegionView::lower ()
-{
-       region.lower ();
-}
-
-void
-AudioRegionView::lower_to_bottom ()
-{
-       region.lower_to_bottom ();
-}
-
-bool
-AudioRegionView::set_position (jack_nframes_t pos, void* src, double* ignored)
-{
-       double delta;
-       bool ret;
-
-       if (!(ret = TimeAxisViewItem::set_position (pos, this, &delta))) {
-               return false;
-       }
-
-       if (ignored) {
-               *ignored = delta;
-       }
-
-       if (delta) {
-               for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-                       (*i)->group->move (delta, 0.0);
-               }
-       }
-
-       return ret;
-}
-
-void
-AudioRegionView::set_height (gdouble height)
-{
-       uint32_t wcnt = waves.size();
-
-       TimeAxisViewItem::set_height (height - 2);
-       
-       _height = height;
-
-       for (uint32_t n=0; n < wcnt; ++n) {
-               gdouble ht;
-
-               if ((height) < NAME_HIGHLIGHT_THRESH) {
-                       ht = ((height-2*wcnt) / (double) wcnt);
-               } else {
-                       ht = (((height-2*wcnt) - NAME_HIGHLIGHT_SIZE) / (double) wcnt);
-               }
-               
-               gdouble yoff = n * (ht+1);
-               
-               waves[n]->property_height() = ht;
-               waves[n]->property_y() = yoff + 2;
-       }
-
-       if (gain_line) {
-               if ((height/wcnt) < NAME_HIGHLIGHT_SIZE) {
-                       gain_line->hide ();
-               } else {
-                       if (_flags & EnvelopeVisible) {
-                               gain_line->show ();
-                       }
-               }
-               gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE));
-       }
-
-       manage_zero_line ();
-       reset_fade_shapes ();
-       
-       if (name_text) {
-               name_text->raise_to_top();
-       }
-}
-
-void
-AudioRegionView::manage_zero_line ()
-{
-       if (!zero_line) {
-               return;
-       }
-
-       if (_height >= 100) {
-               gdouble wave_midpoint = (_height - NAME_HIGHLIGHT_SIZE) / 2.0;
-               zero_line->property_y1() = wave_midpoint;
-               zero_line->property_y2() = wave_midpoint;
-               zero_line->show();
-       } else {
-               zero_line->hide();
-       }
-}
-
-void
-AudioRegionView::reset_fade_shapes ()
-{
-       reset_fade_in_shape ();
-       reset_fade_out_shape ();
-}
-
-void
-AudioRegionView::reset_fade_in_shape ()
-{
-       reset_fade_in_shape_width ((jack_nframes_t) region.fade_in().back()->when);
-}
-       
-void
-AudioRegionView::reset_fade_in_shape_width (jack_nframes_t width)
-{
-       if (fade_in_handle == 0) {
-               return;
-       }
-
-       /* smallest size for a fade is 64 frames */
-
-       width = std::max ((jack_nframes_t) 64, width);
-
-       Points* points;
-       double pwidth = width / samples_per_unit;
-       uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth);
-       double h; 
-       
-       if (_height < 5) {
-               fade_in_shape->hide();
-               fade_in_handle->hide();
-               return;
-       }
-
-       double handle_center;
-       handle_center = pwidth;
-       
-       if (handle_center > 7.0) {
-               handle_center -= 3.0;
-       } else {
-               handle_center = 3.0;
-       }
-       
-       fade_in_handle->property_x1() =  handle_center - 3.0;
-       fade_in_handle->property_x2() =  handle_center + 3.0;
-       
-       if (pwidth < 5) {
-               fade_in_shape->hide();
-               return;
-       }
-
-       fade_in_shape->show();
-
-       float curve[npoints];
-       region.fade_in().get_vector (0, region.fade_in().back()->when, curve, npoints);
-
-       points = get_canvas_points ("fade in shape", npoints+3);
-
-       if (_height > NAME_HIGHLIGHT_THRESH) {
-               h = _height - NAME_HIGHLIGHT_SIZE;
-       } else {
-               h = _height;
-       }
-
-       /* points *MUST* be in anti-clockwise order */
-
-       uint32_t pi, pc;
-       double xdelta = pwidth/npoints;
-
-       for (pi = 0, pc = 0; pc < npoints; ++pc) {
-               (*points)[pi].set_x(1 + (pc * xdelta));
-               (*points)[pi++].set_y(2 + (h - (curve[pc] * h)));
-       }
-       
-       /* fold back */
-
-       (*points)[pi].set_x(pwidth);
-       (*points)[pi++].set_y(2);
-
-       (*points)[pi].set_x(1);
-       (*points)[pi++].set_y(2);
-
-       /* connect the dots ... */
-
-       (*points)[pi] = (*points)[0];
-       
-       fade_in_shape->property_points() = *points;
-       delete points;
-}
-
-void
-AudioRegionView::reset_fade_out_shape ()
-{
-       reset_fade_out_shape_width ((jack_nframes_t) region.fade_out().back()->when);
-}
-
-void
-AudioRegionView::reset_fade_out_shape_width (jack_nframes_t width)
-{      
-       if (fade_out_handle == 0) {
-               return;
-       }
-
-       /* smallest size for a fade is 64 frames */
-
-       width = std::max ((jack_nframes_t) 64, width);
-
-       Points* points;
-       double pwidth = width / samples_per_unit;
-       uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth);
-       double h;
-
-       if (_height < 5) {
-               fade_out_shape->hide();
-               fade_out_handle->hide();
-               return;
-       }
-
-       double handle_center;
-       handle_center = (region.length() - width) / samples_per_unit;
-       
-       if (handle_center > 7.0) {
-               handle_center -= 3.0;
-       } else {
-               handle_center = 3.0;
-       }
-       
-       fade_out_handle->property_x1() =  handle_center - 3.0;
-       fade_out_handle->property_x2() =  handle_center + 3.0;
-
-       /* don't show shape if its too small */
-       
-       if (pwidth < 5) {
-               fade_out_shape->hide();
-               return;
-       } 
-       
-       fade_out_shape->show();
-
-       float curve[npoints];
-       region.fade_out().get_vector (0, region.fade_out().back()->when, curve, npoints);
-
-       if (_height > NAME_HIGHLIGHT_THRESH) {
-               h = _height - NAME_HIGHLIGHT_SIZE;
-       } else {
-               h = _height;
-       }
-
-       /* points *MUST* be in anti-clockwise order */
-
-       points = get_canvas_points ("fade out shape", npoints+3);
-
-       uint32_t pi, pc;
-       double xdelta = pwidth/npoints;
-
-       for (pi = 0, pc = 0; pc < npoints; ++pc) {
-               (*points)[pi].set_x(_pixel_width - 1 - pwidth + (pc*xdelta));
-               (*points)[pi++].set_y(2 + (h - (curve[pc] * h)));
-       }
-       
-       /* fold back */
-
-       (*points)[pi].set_x(_pixel_width);
-       (*points)[pi++].set_y(h);
-
-       (*points)[pi].set_x(_pixel_width);
-       (*points)[pi++].set_y(2);
-
-       /* connect the dots ... */
-
-       (*points)[pi] = (*points)[0];
-
-       fade_out_shape->property_points() = *points;
-       delete points;
-}
-
-void
-AudioRegionView::set_samples_per_unit (gdouble spu)
-{
-       TimeAxisViewItem::set_samples_per_unit (spu);
-
-       for (uint32_t n=0; n < waves.size(); ++n) {
-               waves[n]->property_samples_per_unit() = spu;
-       }
-
-       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-               (*i)->set_samples_per_unit (spu);
-               (*i)->set_duration (region.length() / samples_per_unit);
-       }
-
-       if (gain_line) {
-               gain_line->reset ();
-       }
-       reset_fade_shapes ();
-       region_sync_changed ();
-}
-
-bool
-AudioRegionView::set_duration (jack_nframes_t frames, void *src)
-{
-       if (!TimeAxisViewItem::set_duration (frames, src)) {
-               return false;
-       }
-       
-       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-               (*i)->set_duration (region.length() / samples_per_unit);
-       }
-
-       return true;
-}
-
-void
-AudioRegionView::set_amplitude_above_axis (gdouble spp)
-{
-       for (uint32_t n=0; n < waves.size(); ++n) {
-               waves[n]->property_amplitude_above_axis() = spp;
-       }
-}
-
-void
-AudioRegionView::compute_colors (Gdk::Color& basic_color)
-{
-       TimeAxisViewItem::compute_colors (basic_color);
-       uint32_t r, g, b, a;
-
-       /* gain color computed in envelope_active_changed() */
-
-       UINT_TO_RGBA (fill_color, &r, &g, &b, &a);
-       fade_color = RGBA_TO_UINT(r,g,b,120);
-}
-
-void
-AudioRegionView::set_colors ()
-{
-       TimeAxisViewItem::set_colors ();
-       
-       if (gain_line) {
-               gain_line->set_line_color (region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]);
-       }
-
-       if (sync_mark) {
-               sync_mark->property_fill_color_rgba() = fill_color;
-       }
-
-       for (uint32_t n=0; n < waves.size(); ++n) {
-               if (region.muted()) {
-                       waves[n]->property_wave_color() = color_map[cMutedWaveForm];
-               } else {
-                       waves[n]->property_wave_color() = color_map[cWaveForm];
-               }
-       }
-}
-
-void
-AudioRegionView::set_frame_color ()
-{
-       if (region.opaque()) {
-               fill_opacity = 180;
-       } else {
-               fill_opacity = 100;
-       }
-
-       TimeAxisViewItem::set_frame_color ();
-}
-
-void
-AudioRegionView::show_region_editor ()
-{
-       if (editor == 0) {
-               editor = new AudioRegionEditor (trackview.session(), region, *this);
-               // GTK2FIX : how to ensure float without realizing
-               // editor->realize ();
-               // trackview.editor.ensure_float (*editor);
-       } 
-
-       editor->show_all ();
-       editor->get_window()->raise();
-}
-
-void
-AudioRegionView::hide_region_editor()
-{
-       if (editor) {
-               editor->hide_all ();
-       }
-}
-
-void
-AudioRegionView::region_renamed ()
-{
-       string str;
-
-       if (region.locked()) {
-               str += '>';
-               str += region.name();
-               str += '<';
-       } else {
-               str = region.name();
-       }
-
-       if (region.speed_mismatch (trackview.session().frame_rate())) {
-               str = string ("*") + str;
-       }
-
-       if (region.muted()) {
-               str = string ("!") + str;
-       }
-
-       set_item_name (str, this);
-       set_name_text (str);
-}
-
-void
-AudioRegionView::region_sync_changed ()
-{
-       if (sync_mark == 0) {
-               return;
-       }
-
-       int sync_dir;
-       jack_nframes_t sync_offset;
-
-       sync_offset = region.sync_offset (sync_dir);
-
-       /* this has to handle both a genuine change of position, a change of samples_per_unit,
-          and a change in the bounds of the region.
-        */
-
-       if (sync_offset == 0) {
-
-               /* no sync mark - its the start of the region */
-
-               sync_mark->hide();
-
-       } else {
-
-               if ((sync_dir < 0) || ((sync_dir > 0) && (sync_offset > region.length()))) { 
-
-                       /* no sync mark - its out of the bounds of the region */
-
-                       sync_mark->hide();
-
-               } else {
-
-                       /* lets do it */
-
-                       Points points;
-                       
-                       //points = sync_mark->property_points().get_value();
-                       
-                       double offset = sync_offset / samples_per_unit;
-                       points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1));
-                       points.push_back (Gnome::Art::Point (offset + ((sync_mark_width-1)/2), 1));
-                       points.push_back (Gnome::Art::Point (offset, sync_mark_width - 1));
-                       points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1));     
-                       sync_mark->property_points().set_value (points);
-                       sync_mark->show();
-
-               }
-       }
-}
-
-void
-AudioRegionView::set_waveform_visible (bool yn)
-{
-       if (((_flags & WaveformVisible) != yn)) {
-               if (yn) {
-                       for (uint32_t n=0; n < waves.size(); ++n) {
-                               waves[n]->show();
-                       }
-                       _flags |= WaveformVisible;
-               } else {
-                       for (uint32_t n=0; n < waves.size(); ++n) {
-                               waves[n]->hide();
-                       }
-                       _flags &= ~WaveformVisible;
-               }
-               store_flags ();
-       }
-}
-
-void
-AudioRegionView::temporarily_hide_envelope ()
-{
-       if (gain_line) {
-               gain_line->hide ();
-       }
-}
-
-void
-AudioRegionView::unhide_envelope ()
-{
-       if (gain_line && (_flags & EnvelopeVisible)) {
-               gain_line->show ();
-       }
-}
-
-void
-AudioRegionView::set_envelope_visible (bool yn)
-{
-       if (gain_line && ((_flags & EnvelopeVisible) != yn)) {
-               if (yn) {
-                       gain_line->show ();
-                       _flags |= EnvelopeVisible;
-               } else {
-                       gain_line->hide ();
-                       _flags &= ~EnvelopeVisible;
-               }
-               store_flags ();
-       }
-}
-
-void
-AudioRegionView::create_waves ()
-{
-       bool create_zero_line = true;
-
-       AudioTimeAxisView& atv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick
-
-       if (!atv.get_diskstream()) {
-               return;
-       }
-
-       uint32_t nchans = atv.get_diskstream()->n_channels();
-       
-       /* in tmp_waves, set up null pointers for each channel so the vector is allocated */
-       for (uint32_t n = 0; n < nchans; ++n) {
-               tmp_waves.push_back (0);
-       }
-       
-       for (uint32_t n = 0; n < nchans; ++n) {
-               
-               if (n >= region.n_channels()) {
-                       break;
-               }
-               
-               wave_caches.push_back (WaveView::create_cache ());
-
-               if (wait_for_waves) {
-                       if (region.source(n).peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), peaks_ready_connection)) {
-                               create_one_wave (n, true);
-                       } else {
-                               create_zero_line = false;
-                       }
-               } else {
-                       create_one_wave (n, true);
-               }
-       }
-
-       if (create_zero_line) {
-               zero_line = new ArdourCanvas::SimpleLine (*group);
-               zero_line->property_x1() = (gdouble) 1.0;
-               zero_line->property_x2() = (gdouble) (region.length() / samples_per_unit) - 1.0;
-               zero_line->property_color_rgba() = (guint) color_map[cZeroLine];
-               manage_zero_line ();
-       }
-}
-
-void
-AudioRegionView::create_one_wave (uint32_t which, bool direct)
-{
-       AudioTimeAxisView& atv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick
-       uint32_t nchans = atv.get_diskstream()->n_channels();
-       uint32_t n;
-       uint32_t nwaves = std::min (nchans, region.n_channels());
-       gdouble ht;
-
-       if (trackview.height < NAME_HIGHLIGHT_SIZE) {
-               ht = ((trackview.height) / (double) nchans);
-       } else {
-               ht = ((trackview.height - NAME_HIGHLIGHT_SIZE) / (double) nchans);
-       }
-
-       gdouble yoff = which * ht;
-
-       WaveView *wave = new WaveView(*group);
-
-       wave->property_data_src() = (gpointer) &region;
-       wave->property_cache() =  wave_caches[which];
-       wave->property_cache_updater() = true;
-       wave->property_channel() =  which;
-       wave->property_length_function() = (gpointer) region_length_from_c;
-       wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c;
-       wave->property_peak_function() =  (gpointer) region_read_peaks_from_c;
-       wave->property_x() =  0.0;
-       wave->property_y() =  yoff;
-       wave->property_height() =  (double) ht;
-       wave->property_samples_per_unit() =  samples_per_unit;
-       wave->property_amplitude_above_axis() =  _amplitude_above_axis;
-       wave->property_wave_color() = region.muted() ? color_map[cMutedWaveForm] : color_map[cWaveForm];
-       wave->property_region_start() = region.start();
-
-       if (!(_flags & WaveformVisible)) {
-               wave->hide();
-       }
-
-       /* note: calling this function is serialized by the lock
-          held in the peak building thread that signals that
-          peaks are ready for use *or* by the fact that it is
-          called one by one from the GUI thread.
-       */
-
-       if (which < nchans) {
-               tmp_waves[which] = wave;
-       } else {
-               /* n-channel track, >n-channel source */
-       }
-       
-       /* see if we're all ready */
-       
-       for (n = 0; n < nchans; ++n) {
-               if (tmp_waves[n] == 0) {
-                       break;
-               }
-       }
-       
-       if (n == nwaves && waves.empty()) {
-               /* all waves are ready */
-               tmp_waves.resize(nwaves);
-
-               waves = tmp_waves;
-               tmp_waves.clear ();
-
-               if (!zero_line) {
-                       zero_line = new ArdourCanvas::SimpleLine (*group);
-                       zero_line->property_x1() = (gdouble) 1.0;
-                       zero_line->property_x2() = (gdouble) (region.length() / samples_per_unit) - 1.0;
-                       zero_line->property_color_rgba() = (guint) color_map[cZeroLine];
-                       manage_zero_line ();
-               }
-       }
-}
-
-void
-AudioRegionView::peaks_ready_handler (uint32_t which)
-{
-       Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &AudioRegionView::create_one_wave), which, false));
-
-       if (!waves.empty()) {
-               /* all waves created, don't hook into peaks ready anymore */
-               peaks_ready_connection.disconnect ();           
-       }
-}
-
-void
-AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
-{
-       if (gain_line == 0) {
-               return;
-       }
-
-       double x, y;
-
-       /* don't create points that can't be seen */
-
-       set_envelope_visible (true);
-       
-       x = ev->button.x;
-       y = ev->button.y;
-
-       item->w2i (x, y);
-
-       jack_nframes_t fx = trackview.editor.pixel_to_frame (x);
-
-       if (fx > region.length()) {
-               return;
-       }
-
-       /* compute vertical fractional position */
-
-       y = 1.0 - (y / (trackview.height - NAME_HIGHLIGHT_SIZE));
-       
-       /* map using gain line */
-
-       gain_line->view_to_model_y (y);
-
-       trackview.session().begin_reversible_command (_("add gain control point"));
-        XMLNode &before = region.envelope().get_state();
-
-
-       if (!region.envelope_active()) {
-                XMLNode &before = region.get_state();
-               region.set_envelope_active(true);
-                XMLNode &after = region.get_state();
-               trackview.session().add_command(new MementoCommand<AudioRegion>(region, before, after));
-       }
-
-       region.envelope().add (fx, y);
-       
-       XMLNode &after = region.envelope().get_state();
-       trackview.session().add_command(new MementoCommand<Curve>(region.envelope(), before, after));
-       trackview.session().commit_reversible_command ();
-}
-
-void
-AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
-{
-        ControlPoint *cp = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"));
-       region.envelope().erase (cp->model);
-}
-
-void
-AudioRegionView::store_flags()
-{
-       XMLNode *node = new XMLNode ("GUI");
-
-       node->add_property ("waveform-visible", (_flags & WaveformVisible) ? "yes" : "no");
-       node->add_property ("envelope-visible", (_flags & EnvelopeVisible) ? "yes" : "no");
-
-       region.add_extra_xml (*node);
-}
-
-void
-AudioRegionView::set_flags (XMLNode* node)
-{
-       XMLProperty *prop;
-
-       if ((prop = node->property ("waveform-visible")) != 0) {
-               if (prop->value() == "yes") {
-                       _flags |= WaveformVisible;
-               }
-       }
-
-       if ((prop = node->property ("envelope-visible")) != 0) {
-               if (prop->value() == "yes") {
-                       _flags |= EnvelopeVisible;
-               }
-       }
-}
-       
-void
-AudioRegionView::set_waveform_shape (WaveformShape shape)
-{
-       bool yn;
-
-       /* this slightly odd approach is to leave the door open to 
-          other "shapes" such as spectral displays, etc.
-       */
-
-       switch (shape) {
-       case Rectified:
-               yn = true;
-               break;
-
-       default:
-               yn = false;
-               break;
-       }
-
-       if (yn != (bool) (_flags & WaveformRectified)) {
-               for (vector<WaveView *>::iterator wave = waves.begin(); wave != waves.end() ; ++wave) {
-                       (*wave)->property_rectified() = yn;
-               }
-
-               if (zero_line) {
-                       if (yn) {
-                               zero_line->hide();
-                       } else {
-                               zero_line->show();
-                       }
-               }
-
-               if (yn) {
-                       _flags |= WaveformRectified;
-               } else {
-                       _flags &= ~WaveformRectified;
-               }
-       }
-}
-
-void
-AudioRegionView::move (double x_delta, double y_delta)
-{
-       if (region.locked() || (x_delta == 0 && y_delta == 0)) {
-               return;
-       }
-
-       get_canvas_group()->move (x_delta, y_delta);
-
-       /* note: ghosts never leave their tracks so y_delta for them is always zero */
-
-       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-               (*i)->group->move (x_delta, 0.0);
-       }
-}
-
-GhostRegion*
-AudioRegionView::add_ghost (AutomationTimeAxisView& atv)
-{
-       AudioTimeAxisView& myatv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick
-       double unit_position = region.position () / samples_per_unit;
-       GhostRegion* ghost = new GhostRegion (atv, unit_position);
-       uint32_t nchans;
-       
-       nchans = myatv.get_diskstream()->n_channels();
-
-       for (uint32_t n = 0; n < nchans; ++n) {
-               
-               if (n >= region.n_channels()) {
-                       break;
-               }
-               
-               WaveView *wave = new WaveView(*ghost->group);
-
-               wave->property_data_src() =  &region;
-               wave->property_cache() =  wave_caches[n];
-               wave->property_cache_updater() = false;
-               wave->property_channel() = n;
-               wave->property_length_function() = (gpointer)region_length_from_c;
-               wave->property_sourcefile_length_function() = (gpointer) sourcefile_length_from_c;
-               wave->property_peak_function() =  (gpointer) region_read_peaks_from_c;
-               wave->property_x() =  0.0;
-               wave->property_samples_per_unit() =  samples_per_unit;
-               wave->property_amplitude_above_axis() =  _amplitude_above_axis;
-               wave->property_wave_color() = color_map[cGhostTrackWave];
-               wave->property_region_start() = region.start();
-
-               ghost->waves.push_back(wave);
-       }
-
-       ghost->set_height ();
-       ghost->set_duration (region.length() / samples_per_unit);
-       ghosts.push_back (ghost);
-
-       ghost->GoingAway.connect (mem_fun(*this, &AudioRegionView::remove_ghost));
-
-       return ghost;
-}
-
-void
-AudioRegionView::remove_ghost (GhostRegion* ghost)
-{
-       if (in_destructor) {
-               return;
-       }
-
-       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-               if (*i == ghost) {
-                       ghosts.erase (i);
-                       break;
-               }
-       }
-}
-
-uint32_t
-AudioRegionView::get_fill_color ()
-{
-       return fill_color;
-}
-
-void
-AudioRegionView::entered ()
-{
-       if (gain_line && _flags & EnvelopeVisible) {
-               gain_line->show_all_control_points ();
-       }
-
-       uint32_t r,g,b,a;
-       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
-       a=255;
-       
-       if (fade_in_handle) {
-               fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
-               fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
-       }
-}
-
-void
-AudioRegionView::exited ()
-{
-       if (gain_line) {
-               gain_line->hide_all_but_selected_control_points ();
-       }
-       
-       uint32_t r,g,b,a;
-       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
-       a=0;
-       
-       if (fade_in_handle) {
-               fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
-               fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
-       }
-}
-
-void
-AudioRegionView::envelope_active_changed ()
-{
-       if (gain_line) {
-               gain_line->set_line_color (region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]);
-       }
-}
-
-void
-AudioRegionView::set_waveview_data_src()
-{
-
-       double unit_length= region.length() / samples_per_unit;
-
-       for (uint32_t n = 0; n < waves.size(); ++n) {
-               // TODO: something else to let it know the channel
-               waves[n]->property_data_src() = &region;
-       }
-       
-       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-               
-               (*i)->set_duration (unit_length);
-               
-               for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
-                       (*w)->property_data_src() = &region;
-               }
-       }
-
-}
-
-void
-AudioRegionView::color_handler (ColorID id, uint32_t val)
-{
-       switch (id) {
-       case cMutedWaveForm:
-       case cWaveForm:
-               set_colors ();
-               break;
-
-       case cGainLineInactive:
-       case cGainLine:
-               envelope_active_changed();
-               break;
-               
-       case cZeroLine:
-               if (zero_line) {
-                       zero_line->property_color_rgba() = (guint) color_map[cZeroLine];
-               }
-               break;
-
-       case cGhostTrackWave:
-               break;
-
-       default:
-               break;
-       }
-}
diff --git a/gtk2_ardour/regionview.h b/gtk2_ardour/regionview.h
deleted file mode 100644 (file)
index f49b46a..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
-    Copyright (C) 2001-2004 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$
-*/
-
-#ifndef __gtk_ardour_region_view_h__
-#define __gtk_ardour_region_view_h__
-
-#include <vector>
-
-#include <libgnomecanvasmm.h>
-#include <libgnomecanvasmm/polygon.h>
-#include <sigc++/signal.h>
-#include <ardour/region.h>
-
-#include "time_axis_view_item.h"
-#include "automation_line.h"
-#include "enums.h"
-#include "waveview.h"
-#include "canvas.h"
-#include "color.h"
-
-namespace ARDOUR {
-       class AudioRegion;
-       class PeakData;
-};
-
-class AudioTimeAxisView;
-class AudioRegionGainLine;
-class AudioRegionEditor;
-class GhostRegion;
-class AutomationTimeAxisView;
-
-class AudioRegionView : public TimeAxisViewItem
-{
-  public:
-       AudioRegionView (ArdourCanvas::Group *, 
-                        AudioTimeAxisView&,
-                        ARDOUR::AudioRegion&,
-                        double initial_samples_per_unit,
-                        Gdk::Color& basic_color);
-
-       ~AudioRegionView ();
-       
-       virtual void init (double amplitude_above_axis, Gdk::Color& base_color, bool wait_for_waves);
-    
-    ARDOUR::AudioRegion& region;  // ok, let 'em have it
-    bool is_valid() const { return valid; }
-    void set_valid (bool yn) { valid = yn; }
-
-    void set_height (double);
-    void set_samples_per_unit (double);
-    bool set_duration (jack_nframes_t, void*);
-
-    void set_amplitude_above_axis (gdouble spp);
-
-    void move (double xdelta, double ydelta);
-
-    void raise ();
-    void raise_to_top ();
-    void lower ();
-    void lower_to_bottom ();
-
-    bool set_position(jack_nframes_t pos, void* src, double* delta = 0);
-    
-    void temporarily_hide_envelope (); // dangerous
-    void unhide_envelope (); // dangerous
-
-    void set_envelope_visible (bool);
-    void set_waveform_visible (bool yn);
-    void set_waveform_shape (WaveformShape);
-
-    bool waveform_rectified() const { return _flags & WaveformRectified; }
-    bool waveform_visible() const { return _flags & WaveformVisible; }
-    bool envelope_visible() const { return _flags & EnvelopeVisible; }
-    
-    void show_region_editor ();
-    void hide_region_editor();
-
-    void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event);
-    void remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event);
-
-    AudioRegionGainLine* get_gain_line() const { return gain_line; }
-
-    void region_changed (ARDOUR::Change);
-    void envelope_active_changed ();
-
-    static sigc::signal<void,AudioRegionView*> AudioRegionViewGoingAway;
-    sigc::signal<void> GoingAway;
-
-    GhostRegion* add_ghost (AutomationTimeAxisView&);
-    void remove_ghost (GhostRegion*);
-
-    void reset_fade_in_shape_width (jack_nframes_t);
-    void reset_fade_out_shape_width (jack_nframes_t);
-    void set_fade_in_active (bool);
-    void set_fade_out_active (bool);
-
-    uint32_t get_fill_color ();
-
-    virtual void entered ();
-    virtual void exited ();
-
-  protected:
-
-    /* this constructor allows derived types
-       to specify their visibility requirements
-       to the TimeAxisViewItem parent class
-    */
-    
-    AudioRegionView (ArdourCanvas::Group *, 
-                    AudioTimeAxisView&,
-                    ARDOUR::AudioRegion&,
-                    double initial_samples_per_unit,
-                    Gdk::Color& basic_color,
-                    TimeAxisViewItem::Visibility);
-    
-    enum Flags {
-           EnvelopeVisible = 0x1,
-           WaveformVisible = 0x4,
-           WaveformRectified = 0x8
-    };
-
-    vector<ArdourCanvas::WaveView *> waves; /* waveviews */
-    vector<ArdourCanvas::WaveView *> tmp_waves; /* see ::create_waves()*/
-    ArdourCanvas::Polygon* sync_mark; /* polgyon for sync position */
-    ArdourCanvas::Text* no_wave_msg; /* text */
-    ArdourCanvas::SimpleLine* zero_line; /* simpleline */
-    ArdourCanvas::Polygon* fade_in_shape; /* polygon */
-    ArdourCanvas::Polygon* fade_out_shape; /* polygon */
-    ArdourCanvas::SimpleRect* fade_in_handle; /* simplerect */
-    ArdourCanvas::SimpleRect* fade_out_handle; /* simplerect */
-
-    AudioRegionGainLine* gain_line;
-    AudioRegionEditor *editor;
-
-    vector<ControlPoint *> control_points;
-    double _amplitude_above_axis;
-    double current_visible_sync_position;
-
-    uint32_t _flags;
-    uint32_t fade_color;
-    bool     valid; /* see StreamView::redisplay_diskstream() */
-    double _pixel_width;
-    double _height;
-    bool    in_destructor;
-    bool    wait_for_waves;
-    sigc::connection peaks_ready_connection;
-
-    void reset_fade_shapes ();
-    void reset_fade_in_shape ();
-    void reset_fade_out_shape ();
-    void fade_in_changed ();
-    void fade_out_changed ();
-    void fade_in_active_changed ();
-    void fade_out_active_changed ();
-
-    void region_resized (ARDOUR::Change);
-    void region_moved (void *);
-    void region_muted ();
-    void region_locked ();
-    void region_opacity ();
-    void region_layered ();
-    void region_renamed ();
-    void region_sync_changed ();
-    void region_scale_amplitude_changed ();
-
-    static gint _lock_toggle (ArdourCanvas::Item*, GdkEvent*, void*);
-    void lock_toggle ();
-
-    void create_waves ();
-    void create_one_wave (uint32_t, bool);
-    void manage_zero_line ();
-    void peaks_ready_handler (uint32_t);
-    void reset_name (gdouble width);
-    void set_flags (XMLNode *);
-    void store_flags ();
-
-    void set_colors ();
-    void compute_colors (Gdk::Color&);
-    virtual void set_frame_color ();
-    void reset_width_dependent_items (double pixel_width);
-    void set_waveview_data_src();
-
-    vector<GnomeCanvasWaveViewCache*> wave_caches;
-    vector<GhostRegion*> ghosts;
-    
-    void color_handler (ColorID, uint32_t);
-};
-
-#endif /* __gtk_ardour_region_view_h__ */
index d6ec7eab6c6042d3d5c1bbbc06a8958de24ac8d6..8b47a17511540f2f142a3fd29ec1588354bd6e18 100644 (file)
@@ -59,14 +59,10 @@ using namespace sigc;
 RouteParams_UI::RouteParams_UI (AudioEngine& eng)
        : ArdourDialog ("track/bus inspector"),
          engine (eng),
-         _route(0), 
          track_menu(0)
 {
        pre_redirect_box = 0;
        post_redirect_box = 0;
-       _route = 0;
-       _pre_redirect = 0;
-       _post_redirect = 0;
        _input_iosel = 0;
        _output_iosel = 0;
        _active_pre_view = 0;
@@ -163,7 +159,7 @@ RouteParams_UI::~RouteParams_UI ()
 }
 
 void
-RouteParams_UI::add_route (Route* route)
+RouteParams_UI::add_route (boost::shared_ptr<Route> route)
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::add_route), route));
        
@@ -183,22 +179,22 @@ RouteParams_UI::add_route (Route* route)
 
 
 void
-RouteParams_UI::route_name_changed (void *src, Route *route)
+RouteParams_UI::route_name_changed (void *src, boost::shared_ptr<Route> route)
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::route_name_changed), src, route));
 
        bool found = false ;
        TreeModel::Children rows = route_display_model->children();
        for(TreeModel::Children::iterator iter = rows.begin(); iter != rows.end(); ++iter) {
-               if((*iter)[route_display_columns.route] == route) {
+               boost::shared_ptr<Route> r =(*iter)[route_display_columns.route];
+               if (r == route) {
                        (*iter)[route_display_columns.text] = route->name() ;
                        found = true ;
                        break;
                }
        }
 
-       if(!found)
-       {
+       if(!found) {
                error << _("route display list item for renamed route not found!") << endmsg;
        }
 
@@ -217,8 +213,8 @@ RouteParams_UI::setup_redirect_boxes()
                cleanup_redirect_boxes();
                
                // construct new redirect boxes
-               pre_redirect_box = new RedirectBox(PreFader, *session, *_route, *_plugin_selector, _rr_selection);
-               post_redirect_box = new RedirectBox(PostFader, *session, *_route, *_plugin_selector, _rr_selection);
+               pre_redirect_box = new RedirectBox(PreFader, *session, _route, *_plugin_selector, _rr_selection);
+               post_redirect_box = new RedirectBox(PostFader, *session, _route, *_plugin_selector, _rr_selection);
 
                pre_redir_hpane.pack1 (*pre_redirect_box);
                post_redir_hpane.pack1 (*post_redirect_box);
@@ -256,13 +252,13 @@ RouteParams_UI::setup_io_frames()
        cleanup_io_frames();
        
        // input
-       _input_iosel = new IOSelector (*session, *_route, true);
+       _input_iosel = new IOSelector (*session, _route, true);
        _input_iosel->redisplay ();
         input_frame.add (*_input_iosel);
        input_frame.show_all();
        
        // output
-       _output_iosel = new IOSelector (*session, *_route, false);
+       _output_iosel = new IOSelector (*session, _route, false);
        _output_iosel->redisplay ();
         output_frame.add (*_output_iosel);
        output_frame.show_all();
@@ -322,36 +318,31 @@ RouteParams_UI::cleanup_post_view (bool stopupdate)
 
 
 void
-RouteParams_UI::route_removed (Route *route)
+RouteParams_UI::route_removed (boost::shared_ptr<Route> route)
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::route_removed), route));
-       /*
-       route_select_list.freeze ();
-       route_select_list.clear ();
-       session->foreach_route (this, &RouteParams_UI::add_route);
-       route_select_list.thaw ();
-       */
 
        TreeModel::Children rows = route_display_model->children();
        TreeModel::Children::iterator ri;
 
        for(TreeModel::Children::iterator iter = rows.begin(); iter != rows.end(); ++iter) {
-               if((*iter)[route_display_columns.route] == route) {
+               boost::shared_ptr<Route> r =(*iter)[route_display_columns.route];
+
+               if (r == route) {
                        route_display_model->erase(iter);
                        break;
                }
        }
 
-       if (route == _route)
-       {
+       if (route == _route) {
                cleanup_io_frames();
                cleanup_pre_view();
                cleanup_post_view();
                cleanup_redirect_boxes();
                
-               _route = 0;
-               _pre_redirect = 0;
-               _post_redirect = 0;
+               _route.reset ((Route*) 0);
+               _pre_redirect.reset ((Redirect*) 0);
+               _post_redirect.reset ((Redirect*) 0);
                update_title();
        }
 }
@@ -390,9 +381,9 @@ RouteParams_UI::session_gone ()
        cleanup_post_view();
        cleanup_redirect_boxes();
 
-       _route = 0;
-       _pre_redirect = 0;
-       _post_redirect = 0;
+       _route.reset ((Route*) 0);
+       _pre_redirect.reset ((Redirect*) 0);
+       _post_redirect.reset ((Redirect*) 0);
        update_title();
 
        ArdourDialog::session_gone();
@@ -406,7 +397,7 @@ RouteParams_UI::route_selected()
        TreeModel::iterator iter = selection->get_selected(); // only used with Gtk::SELECTION_SINGLE
        if(iter) {
                //If anything is selected
-               Route* route = (*iter)[route_display_columns.route] ;
+               boost::shared_ptr<Route> route = (*iter)[route_display_columns.route] ;
 
                if (_route == route) {
                        // do nothing
@@ -447,9 +438,9 @@ RouteParams_UI::route_selected()
                        cleanup_post_view();
                        cleanup_redirect_boxes();
 
-                       _route = 0;
-                       _pre_redirect = 0;
-                       _post_redirect = 0;
+                       _route.reset ((Route*) 0);
+                       _pre_redirect.reset ((Redirect*) 0);
+                       _post_redirect.reset ((Redirect *) 0);
                        track_input_label.set_text(_("NO TRACK"));
                        update_title();
                }
@@ -468,7 +459,7 @@ RouteParams_UI::route_selected()
 //             cleanup_post_view();
 //             cleanup_redirect_boxes();
                
-//             _route = 0;
+//             _route.reset ((Route*)0);
 //             _pre_redirect = 0;
 //             _post_redirect = 0;
 //             track_input_label.set_text(_("NO TRACK"));
@@ -495,8 +486,8 @@ RouteParams_UI::redirects_changed (void *src)
        cleanup_pre_view();
        cleanup_post_view();
        
-       _pre_redirect = 0;
-       _post_redirect = 0;
+       _pre_redirect.reset ((Redirect*) 0);
+       _post_redirect.reset ((Redirect*) 0);
        //update_title();
 }
 
@@ -520,24 +511,24 @@ RouteParams_UI::show_track_menu()
 
 
 void
-RouteParams_UI::redirect_selected (ARDOUR::Redirect *redirect, ARDOUR::Placement place)
+RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Redirect> redirect, ARDOUR::Placement place)
 {
-       Insert *insert;
+       boost::shared_ptr<Insert> insert;
 
        if ((place == PreFader && _pre_redirect == redirect)
            || (place == PostFader && _post_redirect == redirect)){
                return;
        }
        
-       if ((insert = dynamic_cast<Insert *> (redirect)) == 0) {
-
-               Send *send;
+       if ((insert = boost::dynamic_pointer_cast<Insert> (redirect)) == 0) {
 
-               if ((send = dynamic_cast<Send *> (redirect)) != 0) {
+               boost::shared_ptr<Send> send;
+               
+               if ((send = boost::dynamic_pointer_cast<Send> (redirect)) != 0) {
 
                        /* its a send */
 
-                       SendUI *send_ui = new SendUI (*send, *session);
+                       SendUI *send_ui = new SendUI (send, *session);
 
                        if (place == PreFader) {
                                cleanup_pre_view();
@@ -560,16 +551,16 @@ RouteParams_UI::redirect_selected (ARDOUR::Redirect *redirect, ARDOUR::Placement
        } else {
                /* its an insert, though we don't know what kind yet. */
 
-               PluginInsert *plugin_insert;
-               PortInsert *port_insert;
+               boost::shared_ptr<PluginInsert> plugin_insert;
+               boost::shared_ptr<PortInsert> port_insert;
                                
-               if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {                             
+               if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (insert)) != 0) {                                
 
-                       PluginUI *plugin_ui = new PluginUI (session->engine(), *plugin_insert, true);
+                       PluginUI *plugin_ui = new PluginUI (session->engine(), plugin_insert, true);
 
                        if (place == PreFader) {
                                cleanup_pre_view();
-                               _pre_plugin_conn = plugin_insert->plugin().GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::plugin_going_away), PreFader));
+                               _pre_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::plugin_going_away), PreFader));
                                plugin_ui->start_updating (0);
                                _active_pre_view = plugin_ui;
                                pre_redir_hpane.pack2 (*_active_pre_view);
@@ -577,16 +568,16 @@ RouteParams_UI::redirect_selected (ARDOUR::Redirect *redirect, ARDOUR::Placement
                        }
                        else {
                                cleanup_post_view();
-                               _post_plugin_conn = plugin_insert->plugin().GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::plugin_going_away), PostFader));
+                               _post_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::plugin_going_away), PostFader));
                                plugin_ui->start_updating (0);
                                _active_post_view = plugin_ui;
                                post_redir_hpane.pack2 (*_active_post_view);
                                post_redir_hpane.show_all();
                        }
 
-               } else if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
+               } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (insert)) != 0) {
 
-                       PortInsertUI *portinsert_ui = new PortInsertUI (*session, *port_insert);
+                       PortInsertUI *portinsert_ui = new PortInsertUI (*session, port_insert);
                                        
                        if (place == PreFader) {
                                cleanup_pre_view();
@@ -610,8 +601,7 @@ RouteParams_UI::redirect_selected (ARDOUR::Redirect *redirect, ARDOUR::Placement
 
        if (place == PreFader) {
                _pre_redirect = redirect;
-       }
-       else {
+       } else {
                _post_redirect = redirect;
        }
        
@@ -619,23 +609,6 @@ RouteParams_UI::redirect_selected (ARDOUR::Redirect *redirect, ARDOUR::Placement
                
 }
 
-void
-RouteParams_UI::redirect_unselected (ARDOUR::Redirect *redirect)
-{
-       // not called anymore
-       
-       if (redirect == _pre_redirect) {
-               cleanup_pre_view();
-               _pre_redirect = 0;
-       }
-       else if (redirect == _post_redirect) {
-               cleanup_post_view();
-               _post_redirect = 0;
-       }
-}
-
-
-
 void
 RouteParams_UI::plugin_going_away (Plugin *plugin, Placement place)
 {
@@ -645,11 +618,11 @@ RouteParams_UI::plugin_going_away (Plugin *plugin, Placement place)
 
        if (place == PreFader) {
                cleanup_pre_view (false);
-               _pre_redirect = 0;
+               _pre_redirect.reset ((Redirect*) 0);
        }
        else {
                cleanup_post_view (false);
-               _post_redirect = 0;
+               _post_redirect.reset ((Redirect*) 0);
        }
 }
 
@@ -661,13 +634,13 @@ RouteParams_UI::redirect_going_away (ARDOUR::Redirect *plugin)
        
        printf ("redirect going away\n");
        // delete the current view without calling finish
-       if (plugin == _pre_redirect) {
+       if (plugin == _pre_redirect.get()) {
                cleanup_pre_view (false);
-               _pre_redirect = 0;
+               _pre_redirect.reset ((Redirect*) 0);
        }
-       else if (plugin == _post_redirect) {
+       else if (plugin == _post_redirect.get()) {
                cleanup_post_view (false);
-               _post_redirect = 0;
+               _post_redirect.reset ((Redirect*) 0);
        }
 }
 
index 96b2041db4525f79cf82c7df7f476773d6af1206..5f487d6e5cfbbe44e30d642e40f1b8f93927465b 100644 (file)
@@ -33,8 +33,9 @@
 #include <gtkmm/togglebutton.h>
 #include <gtkmm/treeview.h>
 
+#include <pbd/stateful.h>
+
 #include <ardour/ardour.h>
-#include <ardour/stateful.h>
 #include <ardour/io.h>
 #include <ardour/redirect.h>
 
@@ -120,14 +121,14 @@ class RouteParams_UI : public ArdourDialog
        PluginSelector    *_plugin_selector;
        RouteRedirectSelection  _rr_selection;
 
-       ARDOUR::Route           *_route;
+       boost::shared_ptr<ARDOUR::Route> _route;
        sigc::connection            _route_conn;
        sigc::connection            _route_ds_conn;
 
-       ARDOUR::Redirect       * _pre_redirect;
+       boost::shared_ptr<ARDOUR::Redirect> _pre_redirect;
        sigc::connection            _pre_plugin_conn;
 
-       ARDOUR::Redirect       * _post_redirect;
+       boost::shared_ptr<ARDOUR::Redirect> _post_redirect;
        sigc::connection            _post_plugin_conn;
        
        
@@ -150,7 +151,7 @@ class RouteParams_UI : public ArdourDialog
                        add(route);
                }
                Gtk::TreeModelColumn<Glib::ustring> text;
-               Gtk::TreeModelColumn<ARDOUR::Route*> route;
+               Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Route> > route;
        };
 
        RouteDisplayModelColumns route_display_columns ;
@@ -158,10 +159,10 @@ class RouteParams_UI : public ArdourDialog
        Glib::RefPtr<Gtk::ListStore> route_display_model;
 
        
-       void add_route (ARDOUR::Route*);
+       void add_route (boost::shared_ptr<ARDOUR::Route>);
 
-       void route_name_changed (void *src, ARDOUR::Route *route);
-       void route_removed (ARDOUR::Route *route);
+       void route_name_changed (void *src, boost::shared_ptr<ARDOUR::Route> route);
+       void route_removed (boost::shared_ptr<ARDOUR::Route> route);
 
 
        void route_selected();
@@ -179,8 +180,7 @@ class RouteParams_UI : public ArdourDialog
        void setup_redirect_boxes();
        void cleanup_redirect_boxes();
 
-       void redirect_selected (ARDOUR::Redirect *, ARDOUR::Placement);
-       void redirect_unselected (ARDOUR::Redirect *);
+       void redirect_selected (boost::shared_ptr<ARDOUR::Redirect>, ARDOUR::Placement);
        
        void plugin_going_away (ARDOUR::Plugin *foo, ARDOUR::Placement);
        void redirect_going_away (ARDOUR::Redirect *foo);
index 6d315e0aaecd10429b5570d4cbf626d5c16c0144..76f202dd92c8ba4da9cdc12aead47b5e6b41df83 100644 (file)
@@ -61,17 +61,6 @@ RouteRedirectSelection::clear ()
 void
 RouteRedirectSelection::clear_redirects ()
 {
-       for (RedirectSelection::iterator i = redirects.begin(); i != redirects.end(); ) {
-               RedirectSelection::iterator tmp;
-
-               tmp = i;
-               ++tmp;
-
-               delete *i;
-
-               i = tmp;
-       }
-
        redirects.clear ();
        RedirectsChanged ();
 }
@@ -84,29 +73,32 @@ RouteRedirectSelection::clear_routes ()
 }
 
 void
-RouteRedirectSelection::add (Redirect* r)
+RouteRedirectSelection::add (boost::shared_ptr<Redirect> r)
 {
        if (find (redirects.begin(), redirects.end(), r) == redirects.end()) {
                redirects.push_back (r);
-               
-               void (RouteRedirectSelection::*pmf)(Redirect*) = &RouteRedirectSelection::remove;
-               r->GoingAway.connect (mem_fun(*this, pmf));
+
+               // XXX SHAREDPTR FIXME
+               // void (RouteRedirectSelection::*pmf)(Redirect*) = &RouteRedirectSelection::remove;
+               // r->GoingAway.connect (mem_fun(*this, pmf));
 
                RedirectsChanged();
        }
 }
 
 void
-RouteRedirectSelection::add (const vector<Redirect*>& rlist)
+RouteRedirectSelection::add (const vector<boost::shared_ptr<Redirect> >& rlist)
 {
        bool changed = false;
 
-       for (vector<Redirect*>::const_iterator i = rlist.begin(); i != rlist.end(); ++i) {
+       for (vector<boost::shared_ptr<Redirect> >::const_iterator i = rlist.begin(); i != rlist.end(); ++i) {
                if (find (redirects.begin(), redirects.end(), *i) == redirects.end()) {
                        redirects.push_back (*i);
                        
-                       void (RouteRedirectSelection::*pmf)(Redirect*) = &RouteRedirectSelection::remove;
-                       (*i)->GoingAway.connect (mem_fun(*this, pmf));
+                       // XXX SHAREDPTR FIXME
+
+                       //void (RouteRedirectSelection::*pmf)(Redirect*) = &RouteRedirectSelection::remove;
+                       // (*i)->GoingAway.connect (mem_fun(*this, pmf));
                        changed = true;
                }
        }
@@ -117,9 +109,9 @@ RouteRedirectSelection::add (const vector<Redirect*>& rlist)
 }
 
 void
-RouteRedirectSelection::remove (Redirect* r)
+RouteRedirectSelection::remove (boost::shared_ptr<Redirect> r)
 {
-       list<Redirect*>::iterator i;
+       list<boost::shared_ptr<Redirect> >::iterator i;
        if ((i = find (redirects.begin(), redirects.end(), r)) != redirects.end()) {
                redirects.erase (i);
                RedirectsChanged ();
@@ -127,36 +119,37 @@ RouteRedirectSelection::remove (Redirect* r)
 }
 
 void
-RouteRedirectSelection::set (Redirect *r)
+RouteRedirectSelection::set (boost::shared_ptr<Redirect> r)
 {
        clear_redirects ();
        add (r);
 }
 
 void
-RouteRedirectSelection::set (const vector<Redirect*>& rlist)
+RouteRedirectSelection::set (const vector<boost::shared_ptr<Redirect> >& rlist)
 {
        clear_redirects ();
        add (rlist);
 }
 
 void
-RouteRedirectSelection::add (Route* r)
+RouteRedirectSelection::add (boost::shared_ptr<Route> r)
 {
        if (find (routes.begin(), routes.end(), r) == routes.end()) {
                routes.push_back (r);
 
-               void (RouteRedirectSelection::*pmf)(Route*) = &RouteRedirectSelection::remove;
-               r->GoingAway.connect (bind (mem_fun(*this, pmf), r));
+               // XXX SHAREDPTR FIXME
+               // void (RouteRedirectSelection::*pmf)(Route*) = &RouteRedirectSelection::remove;
+               // r->GoingAway.connect (bind (mem_fun(*this, pmf), r));
 
                RoutesChanged();
        }
 }
 
 void
-RouteRedirectSelection::remove (Route* r)
+RouteRedirectSelection::remove (boost::shared_ptr<Route> r)
 {
-       list<Route*>::iterator i;
+       list<boost::shared_ptr<Route> >::iterator i;
        if ((i = find (routes.begin(), routes.end(), r)) != routes.end()) {
                routes.erase (i);
                RoutesChanged ();
@@ -164,16 +157,16 @@ RouteRedirectSelection::remove (Route* r)
 }
 
 void
-RouteRedirectSelection::set (Route *r)
+RouteRedirectSelection::set (boost::shared_ptr<Route> r)
 {
        clear_routes ();
        add (r);
 }
 
 bool
-RouteRedirectSelection::selected (Route* ms)
+RouteRedirectSelection::selected (boost::shared_ptr<Route> r)
 {
-       return find (routes.begin(), routes.end(), ms) != routes.end();
+       return find (routes.begin(), routes.end(), r) != routes.end();
 }
 
 bool
index 9e2b8661715253a8d3a682a423077267d37b66a4..60d301e762e500ba3640e1252fdf79979da5aad6 100644 (file)
@@ -43,20 +43,20 @@ class RouteRedirectSelection : public sigc::trackable
        void clear ();
        bool empty();
 
-       void set (ARDOUR::Redirect*);
-       void set (const std::vector<ARDOUR::Redirect*>&);
-       void add (ARDOUR::Redirect*);
-       void add (const std::vector<ARDOUR::Redirect*>&);
-       void remove (ARDOUR::Redirect*);
+       void set (boost::shared_ptr<ARDOUR::Redirect>);
+       void set (const std::vector<boost::shared_ptr<ARDOUR::Redirect> >&);
+       void add (boost::shared_ptr<ARDOUR::Redirect>);
+       void add (const std::vector<boost::shared_ptr<ARDOUR::Redirect> >&);
+       void remove (boost::shared_ptr<ARDOUR::Redirect>);
 
-       void set (ARDOUR::Route*);
-       void add (ARDOUR::Route*);
-       void remove (ARDOUR::Route*);
+       void set (boost::shared_ptr<ARDOUR::Route>);
+       void add (boost::shared_ptr<ARDOUR::Route>);
+       void remove (boost::shared_ptr<ARDOUR::Route>);
 
        void clear_redirects ();
        void clear_routes ();
 
-       bool selected (ARDOUR::Route*);
+       bool selected (boost::shared_ptr<ARDOUR::Route>);
 };
 
 bool operator==(const RouteRedirectSelection& a, const RouteRedirectSelection& b);
index 50797deed35255245415e72e2ff32a6966143ee8..8d5673a2eff4289d828eb280ed684b7e3740a4a2 100644 (file)
@@ -1,12 +1,14 @@
 #ifndef __ardour_gtk_route_selection_h__
 #define __ardour_gtk_route_selection_h__
 
+
+#include <boost/shared_ptr.hpp>
 #include <list>
 
 namespace ARDOUR {
        class Route;
 }
 
-struct RouteSelection : list<ARDOUR::Route*> {};
+struct RouteSelection : std::list<boost::shared_ptr<ARDOUR::Route> > {};
 
 #endif /* __ardour_gtk_route_selection_h__ */
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
new file mode 100644 (file)
index 0000000..8dca7be
--- /dev/null
@@ -0,0 +1,1601 @@
+/*
+    Copyright (C) 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
+    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 <cstdlib>
+#include <cmath>
+#include <cassert>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include <sigc++/bind.h>
+
+#include <pbd/error.h>
+#include <pbd/stl_delete.h>
+#include <pbd/whitespace.h>
+
+#include <gtkmm/menu.h>
+#include <gtkmm/menuitem.h>
+#include <gtkmm2ext/gtk_ui.h>
+#include <gtkmm2ext/selector.h>
+#include <gtkmm2ext/stop_signal.h>
+#include <gtkmm2ext/bindable_button.h>
+#include <gtkmm2ext/utils.h>
+
+#include <ardour/playlist.h>
+#include <ardour/diskstream.h>
+#include <ardour/insert.h>
+#include <ardour/ladspa_plugin.h>
+#include <ardour/location.h>
+#include <ardour/panner.h>
+#include <ardour/playlist.h>
+#include <ardour/session.h>
+#include <ardour/session_playlist.h>
+#include <ardour/utils.h>
+
+#include "ardour_ui.h"
+#include "route_time_axis.h"
+#include "automation_time_axis.h"
+#include "redirect_automation_time_axis.h"
+#include "redirect_automation_line.h"
+#include "canvas_impl.h"
+#include "crossfade_view.h"
+#include "enums.h"
+#include "gui_thread.h"
+#include "keyboard.h"
+#include "playlist_selector.h"
+#include "plugin_selector.h"
+#include "plugin_ui.h"
+#include "point_selection.h"
+#include "prompter.h"
+#include "public_editor.h"
+#include "region_view.h"
+#include "rgb_macros.h"
+#include "selection.h"
+#include "simplerect.h"
+#include "streamview.h"
+#include "utils.h"
+
+#include <ardour/track.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+using namespace Gtk;
+using namespace Editing;
+
+
+RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::shared_ptr<Route> rt, Canvas& canvas)
+       : AxisView(sess),
+         RouteUI(rt, sess, _("m"), _("s"), _("r")), // mute, solo, and record
+         TimeAxisView(sess,ed,(TimeAxisView*) 0, canvas),
+         parent_canvas (canvas),
+         button_table (3, 3),
+         edit_group_button (_("g")), // group
+         playlist_button (_("p")), 
+         size_button (_("h")), // height
+         automation_button (_("a")),
+         visual_button (_("v"))
+
+{
+       _has_state = true;
+       playlist_menu = 0;
+       playlist_action_menu = 0;
+       automation_action_menu = 0;
+       _view = 0;
+       timestretch_rect = 0;
+       no_redraw = false;
+
+       ignore_toggle = false;
+
+       mute_button->set_active (false);
+       solo_button->set_active (false);
+       
+       mute_button->set_name ("TrackMuteButton");
+       solo_button->set_name ("SoloButton");
+       edit_group_button.set_name ("TrackGroupButton");
+       playlist_button.set_name ("TrackPlaylistButton");
+       automation_button.set_name ("TrackAutomationButton");
+       size_button.set_name ("TrackSizeButton");
+       visual_button.set_name ("TrackVisualButton");
+       hide_button.set_name ("TrackRemoveButton");
+
+       hide_button.add (*(manage (new Image (get_xpm("small_x.xpm")))));
+
+       solo_button->signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
+       mute_button->signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
+       playlist_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
+       automation_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
+       size_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
+       visual_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
+       hide_button.signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
+
+       solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press), false);
+       solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release), false);
+       mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false);
+       mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release), false);
+       edit_group_button.signal_button_release_event().connect (mem_fun(*this, &RouteTimeAxisView::edit_click), false);
+       playlist_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::playlist_click));
+       automation_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::automation_click));
+       size_button.signal_button_release_event().connect (mem_fun(*this, &RouteTimeAxisView::size_click), false);
+       visual_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::visual_click));
+       hide_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::hide_click));
+
+       if (is_track()) {
+               rec_enable_button->set_active (false);
+               rec_enable_button->set_name ("TrackRecordEnableButton");
+               rec_enable_button->signal_button_press_event().connect (mem_fun (*this, &RouteTimeAxisView::select_me), false);
+               rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press));
+               controls_table.attach (*rec_enable_button, 5, 6, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
+               ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record"));
+       }
+
+       controls_table.attach (*mute_button, 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
+       controls_table.attach (*solo_button, 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::FILL|Gtk::EXPAND, 0, 0);
+
+       controls_table.attach (edit_group_button, 6, 7, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
+
+       ARDOUR_UI::instance()->tooltips().set_tip(*solo_button,_("Solo"));
+       ARDOUR_UI::instance()->tooltips().set_tip(*mute_button,_("Mute"));
+       ARDOUR_UI::instance()->tooltips().set_tip(edit_group_button,_("Edit Group"));
+       ARDOUR_UI::instance()->tooltips().set_tip(size_button,_("Display Height"));
+       ARDOUR_UI::instance()->tooltips().set_tip(playlist_button,_("Playlist"));
+       ARDOUR_UI::instance()->tooltips().set_tip(automation_button, _("Automation"));
+       ARDOUR_UI::instance()->tooltips().set_tip(visual_button, _("Visual options"));
+       ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("Hide this track"));
+       
+       label_view ();
+
+       controls_table.attach (hide_button, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+       controls_table.attach (visual_button, 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+       controls_table.attach (size_button, 2, 3, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+       controls_table.attach (automation_button, 3, 4, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+
+       if (is_track() && track()->mode() == ARDOUR::Normal) {
+               controls_table.attach (playlist_button, 5, 6, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+       }
+
+       /* remove focus from the buttons */
+       
+       automation_button.unset_flags (Gtk::CAN_FOCUS);
+       solo_button->unset_flags (Gtk::CAN_FOCUS);
+       mute_button->unset_flags (Gtk::CAN_FOCUS);
+       edit_group_button.unset_flags (Gtk::CAN_FOCUS);
+       size_button.unset_flags (Gtk::CAN_FOCUS);
+       playlist_button.unset_flags (Gtk::CAN_FOCUS);
+       hide_button.unset_flags (Gtk::CAN_FOCUS);
+       visual_button.unset_flags (Gtk::CAN_FOCUS);
+
+       /* map current state of the route */
+
+       update_diskstream_display ();
+       solo_changed(0);
+       mute_changed(0);
+       //redirects_changed (0);
+       //reset_redirect_automation_curves ();
+       y_position = -1;
+
+       _route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
+       _route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
+       _route->redirects_changed.connect (mem_fun(*this, &RouteTimeAxisView::redirects_changed));
+       _route->name_changed.connect (mem_fun(*this, &RouteTimeAxisView::route_name_changed));
+       _route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
+
+       if (is_track()) {
+
+               track()->FreezeChange.connect (mem_fun(*this, &RouteTimeAxisView::map_frozen));
+               track()->DiskstreamChanged.connect (mem_fun(*this, &RouteTimeAxisView::diskstream_changed));
+               get_diskstream()->SpeedChanged.connect (mem_fun(*this, &RouteTimeAxisView::speed_changed));
+
+               /* ask for notifications of any new RegionViews */
+               // FIXME: _view is NULL, but it would be nice to attach this here :/
+               //_view->RegionViewAdded.connect (mem_fun(*this, &RouteTimeAxisView::region_view_added));
+               //_view->attach ();
+
+               /* pick up the correct freeze state */
+               map_frozen ();
+
+       }
+
+       editor.ZoomChanged.connect (mem_fun(*this, &RouteTimeAxisView::reset_samples_per_unit));
+       ColorChanged.connect (mem_fun (*this, &RouteTimeAxisView::color_handler));
+}
+
+RouteTimeAxisView::~RouteTimeAxisView ()
+{
+       GoingAway (); /* EMIT_SIGNAL */
+
+       vector_delete (&redirect_automation_curves);
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               delete *i;
+       }
+
+       if (playlist_menu) {
+               delete playlist_menu;
+               playlist_menu = 0;
+       }
+  
+       if (playlist_action_menu) {
+               delete playlist_action_menu;
+               playlist_action_menu = 0;
+       }
+
+       if (_view) {
+               delete _view;
+               _view = 0;
+       }
+}
+
+void
+RouteTimeAxisView::set_playlist (Playlist *newplaylist)
+{
+       Playlist *pl = playlist();
+       assert(pl);
+
+       modified_connection.disconnect ();
+       state_changed_connection.disconnect ();
+       
+       state_changed_connection = pl->StateChanged.connect (mem_fun(*this, &RouteTimeAxisView::playlist_state_changed));
+       modified_connection = pl->Modified.connect (mem_fun(*this, &RouteTimeAxisView::playlist_modified));
+}
+
+void
+RouteTimeAxisView::playlist_modified ()
+{
+}
+
+gint
+RouteTimeAxisView::edit_click (GdkEventButton *ev)
+{
+       if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+               _route->set_edit_group (0, this);
+               return FALSE;
+       } 
+
+       using namespace Menu_Helpers;
+
+       MenuList& items = edit_group_menu.items ();
+       RadioMenuItem::Group group;
+
+       items.clear ();
+       items.push_back (RadioMenuElem (group, _("No group"), 
+                                       bind (mem_fun(*this, &RouteTimeAxisView::set_edit_group_from_menu), (RouteGroup *) 0)));
+       
+       if (_route->edit_group() == 0) {
+               static_cast<RadioMenuItem*>(&items.back())->set_active ();
+       }
+       
+       _session.foreach_edit_group (bind (mem_fun (*this, &RouteTimeAxisView::add_edit_group_menu_item), &group));
+       edit_group_menu.popup (ev->button, ev->time);
+
+       return FALSE;
+}
+
+void
+RouteTimeAxisView::add_edit_group_menu_item (RouteGroup *eg, RadioMenuItem::Group* group)
+{
+       using namespace Menu_Helpers;
+
+       MenuList &items = edit_group_menu.items();
+
+       cerr << "adding edit group " << eg->name() << endl;
+
+       items.push_back (RadioMenuElem (*group, eg->name(), bind (mem_fun(*this, &RouteTimeAxisView::set_edit_group_from_menu), eg)));
+       if (_route->edit_group() == eg) {
+               static_cast<RadioMenuItem*>(&items.back())->set_active ();
+       }
+}
+
+void
+RouteTimeAxisView::set_edit_group_from_menu (RouteGroup *eg)
+
+{
+       _route->set_edit_group (eg, this);
+}
+
+void
+RouteTimeAxisView::playlist_state_changed (Change ignored)
+{
+       // ENSURE_GUI_THREAD (bind (mem_fun(*this, &RouteTimeAxisView::playlist_state_changed), ignored));
+       // why are we here ?
+}
+
+void
+RouteTimeAxisView::playlist_changed ()
+
+{
+       label_view ();
+
+       if (is_track()) {
+               set_playlist (dynamic_cast<Playlist*>(get_diskstream()->playlist()));
+       }
+}
+
+void
+RouteTimeAxisView::label_view ()
+{
+       string x = _route->name();
+
+       if (x != name_entry.get_text()) {
+               name_entry.set_text (x);
+       }
+
+       ARDOUR_UI::instance()->tooltips().set_tip (name_entry, x);
+}
+
+void
+RouteTimeAxisView::route_name_changed (void *src)
+{
+       editor.route_name_changed (this);
+       label_view ();
+}
+
+void
+RouteTimeAxisView::take_name_changed (void *src)
+
+{
+       if (src != this) {
+               label_view ();
+       }
+}
+
+void
+RouteTimeAxisView::playlist_click ()
+{
+       // always build a new action menu
+       
+       if (playlist_action_menu == 0) {
+               playlist_action_menu = new Menu;
+               playlist_action_menu->set_name ("ArdourContextMenu");
+       }
+       
+       build_playlist_menu(playlist_action_menu);
+
+       playlist_action_menu->popup (1, 0);
+}
+
+void
+RouteTimeAxisView::automation_click ()
+{
+       if (automation_action_menu == 0) {
+               /* this seems odd, but the automation action
+                  menu is built as part of the display menu.
+               */
+               build_display_menu ();
+       }
+       automation_action_menu->popup (1, 0);
+}
+
+void
+RouteTimeAxisView::build_automation_action_menu ()
+{
+       using namespace Menu_Helpers;
+
+       automation_action_menu = manage (new Menu);
+       MenuList& automation_items = automation_action_menu->items();
+       automation_action_menu->set_name ("ArdourContextMenu");
+       
+       automation_items.push_back (MenuElem (_("Show all automation"),
+                                             mem_fun(*this, &RouteTimeAxisView::show_all_automation)));
+
+       automation_items.push_back (MenuElem (_("Show existing automation"),
+                                             mem_fun(*this, &RouteTimeAxisView::show_existing_automation)));
+
+       automation_items.push_back (MenuElem (_("Hide all automation"),
+                                             mem_fun(*this, &RouteTimeAxisView::hide_all_automation)));
+
+       automation_items.push_back (MenuElem (_("Plugins"), subplugin_menu));
+}
+
+void
+RouteTimeAxisView::build_display_menu ()
+{
+       using namespace Menu_Helpers;
+
+       /* get the size menu ready */
+
+       build_size_menu ();
+
+       /* prepare it */
+
+       TimeAxisView::build_display_menu ();
+
+       /* now fill it with our stuff */
+
+       MenuList& items = display_menu->items();
+       display_menu->set_name ("ArdourContextMenu");
+       
+       items.push_back (MenuElem (_("Height"), *size_menu));
+       items.push_back (MenuElem (_("Color"), mem_fun(*this, &RouteTimeAxisView::select_track_color)));
+
+       items.push_back (SeparatorElem());
+
+       build_remote_control_menu ();
+       items.push_back (MenuElem (_("Remote Control ID"), *remote_control_menu));
+
+       build_automation_action_menu ();
+       items.push_back (MenuElem (_("Automation"), *automation_action_menu));
+
+       // Hook for derived classes to add type specific stuff
+       items.push_back (SeparatorElem());
+       append_extra_display_menu_items ();
+       items.push_back (SeparatorElem());
+       
+       if (is_track()) {
+
+               Menu* alignment_menu = manage (new Menu);
+               MenuList& alignment_items = alignment_menu->items();
+               alignment_menu->set_name ("ArdourContextMenu");
+
+               RadioMenuItem::Group align_group;
+               
+               alignment_items.push_back (RadioMenuElem (align_group, _("Align with existing material"),
+                       bind (mem_fun(*this, &RouteTimeAxisView::set_align_style), ExistingMaterial)));
+               align_existing_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back());
+               if (get_diskstream()->alignment_style() == ExistingMaterial)
+                       align_existing_item->set_active();
+               
+               alignment_items.push_back (RadioMenuElem (align_group, _("Align with capture time"),
+                       bind (mem_fun(*this, &RouteTimeAxisView::set_align_style), CaptureTime)));
+               align_capture_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back());
+               if (get_diskstream()->alignment_style() == CaptureTime)
+                       align_capture_item->set_active();
+               
+               items.push_back (MenuElem (_("Alignment"), *alignment_menu));
+
+               get_diskstream()->AlignmentStyleChanged.connect (
+                       mem_fun(*this, &RouteTimeAxisView::align_style_changed));
+       }
+
+       items.push_back (SeparatorElem());
+       items.push_back (CheckMenuElem (_("Active"), mem_fun(*this, &RouteUI::toggle_route_active)));
+       route_active_menu_item = dynamic_cast<CheckMenuItem *> (&items.back());
+       route_active_menu_item->set_active (_route->active());
+
+       items.push_back (SeparatorElem());
+       items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route)));
+}
+
+
+void
+RouteTimeAxisView::show_timestretch (jack_nframes_t start, jack_nframes_t end)
+{
+       double x1;
+       double x2;
+       double y2;
+       
+       TimeAxisView::show_timestretch (start, end);
+
+       hide_timestretch ();
+
+#if 0  
+       if (ts.empty()) {
+               return;
+       }
+
+
+       /* check that the time selection was made in our route, or our edit group.
+          remember that edit_group() == 0 implies the route is *not* in a edit group.
+       */
+
+       if (!(ts.track == this || (ts.group != 0 && ts.group == _route->edit_group()))) {
+               /* this doesn't apply to us */
+               return;
+       }
+
+       /* ignore it if our edit group is not active */
+       
+       if ((ts.track != this) && _route->edit_group() && !_route->edit_group()->is_active()) {
+               return;
+       }
+#endif
+
+       if (timestretch_rect == 0) {
+               timestretch_rect = new SimpleRect (*canvas_display);
+               timestretch_rect->property_x1() =  0.0;
+               timestretch_rect->property_y1() =  0.0;
+               timestretch_rect->property_x2() =  0.0;
+               timestretch_rect->property_y2() =  0.0;
+               timestretch_rect->property_fill_color_rgba() =  color_map[cTimeStretchFill];
+               timestretch_rect->property_outline_color_rgba() = color_map[cTimeStretchOutline];
+       }
+
+       timestretch_rect->show ();
+       timestretch_rect->raise_to_top ();
+
+       x1 = start / editor.get_current_zoom();
+       x2 = (end - 1) / editor.get_current_zoom();
+       y2 = height - 2;
+       
+       timestretch_rect->property_x1() = x1;
+       timestretch_rect->property_y1() = 1.0;
+       timestretch_rect->property_x2() = x2;
+       timestretch_rect->property_y2() = y2;
+}
+
+void
+RouteTimeAxisView::hide_timestretch ()
+{
+       TimeAxisView::hide_timestretch ();
+
+       if (timestretch_rect) {
+               timestretch_rect->hide ();
+       }
+}
+
+void
+RouteTimeAxisView::show_selection (TimeSelection& ts)
+{
+
+#if 0
+       /* ignore it if our edit group is not active or if the selection was started
+          in some other track or edit group (remember that edit_group() == 0 means
+          that the track is not in an edit group).
+       */
+
+       if (((ts.track != this && !is_child (ts.track)) && _route->edit_group() && !_route->edit_group()->is_active()) ||
+           (!(ts.track == this || is_child (ts.track) || (ts.group != 0 && ts.group == _route->edit_group())))) {
+               hide_selection ();
+               return;
+       }
+#endif
+
+       TimeAxisView::show_selection (ts);
+}
+
+void
+RouteTimeAxisView::set_height (TrackHeight h)
+{
+       bool height_changed = (height == 0) || (h != height_style);
+
+       TimeAxisView::set_height (h);
+
+       ensure_xml_node ();
+
+       _view->set_height ((double) height);
+
+       switch (height_style) {
+       case Largest:
+               xml_node->add_property ("track_height", "largest");
+               break;
+
+       case Large:
+               xml_node->add_property ("track_height", "large");
+               break;
+
+       case Larger:
+               xml_node->add_property ("track_height", "larger");
+               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 ();
+
+               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:
+               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 ();
+               
+               if (is_track() && track()->mode() == ARDOUR::Normal) {
+                       playlist_button.hide ();
+               }
+               break;
+
+       case Small:
+               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;
+       }
+
+       if (height_changed) {
+               /* only emit the signal if the height really changed */
+                _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+       }
+}
+
+void
+RouteTimeAxisView::select_track_color ()
+{
+       if (RouteUI::choose_color ()) {
+
+               if (_view) {
+                       _view->apply_color (_color, StreamView::RegionColor);
+               }
+       }
+}
+
+void
+RouteTimeAxisView::reset_samples_per_unit ()
+{
+       set_samples_per_unit (editor.get_current_zoom());
+}
+
+void
+RouteTimeAxisView::set_samples_per_unit (double spu)
+{
+       double speed = 1.0;
+
+       if (get_diskstream() != 0) {
+               speed = get_diskstream()->speed();
+       }
+       
+       if (_view) {
+               _view->set_samples_per_unit (spu * speed);
+       }
+
+       TimeAxisView::set_samples_per_unit (spu * speed);
+}
+
+void
+RouteTimeAxisView::align_style_changed ()
+{
+       switch (get_diskstream()->alignment_style()) {
+       case ExistingMaterial:
+               if (!align_existing_item->get_active()) {
+                       align_existing_item->set_active();
+               }
+               break;
+       case CaptureTime:
+               if (!align_capture_item->get_active()) {
+                       align_capture_item->set_active();
+               }
+               break;
+       }
+}
+
+void
+RouteTimeAxisView::set_align_style (AlignStyle style)
+{
+       get_diskstream()->set_align_style (style);
+}
+
+void
+RouteTimeAxisView::rename_current_playlist ()
+{
+       ArdourPrompter prompter (true);
+       string name;
+
+       Diskstream *const ds = get_diskstream();
+       if (!ds || ds->destructive())
+               return;
+
+       Playlist *const pl = ds->playlist();
+       if (!pl)
+               return;
+
+       prompter.set_prompt (_("Name for playlist"));
+       prompter.set_initial_text (pl->name());
+       prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
+       prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
+
+       switch (prompter.run ()) {
+       case Gtk::RESPONSE_ACCEPT:
+               prompter.get_result (name);
+               if (name.length()) {
+                       pl->set_name (name);
+               }
+               break;
+
+       default:
+               break;
+       }
+}
+
+void
+RouteTimeAxisView::use_copy_playlist (bool prompt)
+{
+       string name;
+       
+       Diskstream *const ds = get_diskstream();
+       if (!ds || ds->destructive())
+               return;
+
+       Playlist *const pl = ds->playlist();
+       if (!pl)
+               return;
+
+       name = Playlist::bump_name (pl->name(), _session);
+
+       if (prompt) {
+
+               ArdourPrompter prompter (true);
+               
+               prompter.set_prompt (_("Name for Playlist"));
+               prompter.set_initial_text (name);
+               prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT);
+               prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
+               prompter.show_all ();
+               
+               switch (prompter.run ()) {
+               case Gtk::RESPONSE_ACCEPT:
+                       prompter.get_result (name);
+                       break;
+                       
+               default:
+                       return;
+               }
+       }
+
+       if (name.length()) {
+               ds->use_copy_playlist ();
+               pl->set_name (name);
+       }
+}
+
+void
+RouteTimeAxisView::use_new_playlist (bool prompt)
+{
+       string name;
+       
+       Diskstream *const ds = get_diskstream();
+       if (!ds || ds->destructive())
+               return;
+
+       Playlist *const pl = ds->playlist();
+       if (!pl)
+               return;
+
+       name = Playlist::bump_name (pl->name(), _session);
+
+       if (prompt) {
+               
+               ArdourPrompter prompter (true);
+               
+               prompter.set_prompt (_("Name for Playlist"));
+               prompter.set_initial_text (name);
+               prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT);
+               prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
+               
+               switch (prompter.run ()) {
+               case Gtk::RESPONSE_ACCEPT:
+                       prompter.get_result (name);
+                       break;
+                       
+               default:
+                       return;
+               }
+       }
+
+       if (name.length()) {
+               ds->use_new_playlist ();
+               pl->set_name (name);
+       }
+}
+
+void
+RouteTimeAxisView::clear_playlist ()
+{
+       Diskstream *const ds = get_diskstream();
+       if (!ds || ds->destructive())
+               return;
+
+       Playlist *const pl = ds->playlist();
+       if (!pl)
+               return;
+
+       editor.clear_playlist (*pl);
+}
+
+void
+RouteTimeAxisView::speed_changed ()
+{
+       Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &RouteTimeAxisView::reset_samples_per_unit));
+}
+
+void
+RouteTimeAxisView::diskstream_changed ()
+{
+       Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &RouteTimeAxisView::update_diskstream_display));
+}      
+
+void
+RouteTimeAxisView::update_diskstream_display ()
+{
+       if (!get_diskstream()) // bus
+               return;
+
+       set_playlist (get_diskstream()->playlist());
+       map_frozen ();
+}      
+
+void
+RouteTimeAxisView::selection_click (GdkEventButton* ev)
+{
+       PublicEditor::TrackViewList* tracks = editor.get_valid_views (this, _route->edit_group());
+
+       switch (Keyboard::selection_type (ev->state)) {
+       case Selection::Toggle:
+               /* XXX this is not right */
+               editor.get_selection().add (*tracks);
+               break;
+               
+       case Selection::Set:
+               editor.get_selection().set (*tracks);
+               break;
+
+       case Selection::Extend:
+               /* not defined yet */
+               break;
+       }
+
+       delete tracks;
+}
+
+void
+RouteTimeAxisView::set_selected_points (PointSelection& points)
+{
+       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+               (*i)->set_selected_points (points);
+       }
+}
+
+void
+RouteTimeAxisView::set_selected_regionviews (RegionSelection& regions)
+{
+       _view->set_selected_regionviews (regions);
+}
+
+void
+RouteTimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable*>& results)
+{
+       double speed = 1.0;
+       
+       if (get_diskstream() != 0) {
+               speed = get_diskstream()->speed();
+       }
+       
+       jack_nframes_t start_adjusted = session_frame_to_track_frame(start, speed);
+       jack_nframes_t end_adjusted   = session_frame_to_track_frame(end, speed);
+
+       if (_view && ((top < 0.0 && bot < 0.0)) || touched (top, bot)) {
+               _view->get_selectables (start_adjusted, end_adjusted, results);
+       }
+
+       /* pick up visible automation tracks */
+       
+       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+               if (!(*i)->hidden()) {
+                       (*i)->get_selectables (start_adjusted, end_adjusted, top, bot, results);
+               }
+       }
+}
+
+void
+RouteTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& results)
+{
+       if (_view) {
+               _view->get_inverted_selectables (sel, results);
+       }
+
+       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+               if (!(*i)->hidden()) {
+                       (*i)->get_inverted_selectables (sel, results);
+               }
+       }
+
+       return;
+}
+
+RouteGroup*
+RouteTimeAxisView::edit_group() const
+{
+       return _route->edit_group();
+}
+
+string
+RouteTimeAxisView::name() const
+{
+       return _route->name();
+}
+
+Playlist *
+RouteTimeAxisView::playlist () const 
+{
+       Diskstream *ds;
+
+       if ((ds = get_diskstream()) != 0) {
+               return ds->playlist(); 
+       } else {
+               return 0; 
+       }
+}
+
+void
+RouteTimeAxisView::name_entry_changed ()
+{
+       string x;
+
+       x = name_entry.get_text ();
+       
+       if (x == _route->name()) {
+               return;
+       }
+
+       if (x.length() == 0) {
+               name_entry.set_text (_route->name());
+               return;
+       }
+
+       strip_whitespace_edges(x);
+
+       if (_session.route_name_unique (x)) {
+               _route->set_name (x, this);
+       } else {
+               ARDOUR_UI::instance()->popup_error (_("a track already exists with that name"));
+               name_entry.set_text (_route->name());
+       }
+}
+
+void
+RouteTimeAxisView::visual_click ()
+{
+       popup_display_menu (0);
+}
+
+void
+RouteTimeAxisView::hide_click ()
+{
+       editor.hide_track_in_display (*this);
+}
+
+Region*
+RouteTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir)
+{
+       Diskstream *stream;
+       Playlist *playlist;
+
+       if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) {
+               return playlist->find_next_region (pos, point, dir);
+       }
+
+       return 0;
+}
+
+bool
+RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
+{
+       Playlist* what_we_got;
+       Diskstream* ds = get_diskstream();
+       Playlist* playlist;
+       bool ret = false;
+
+       if (ds == 0) {
+               /* route is a bus, not a track */
+               return false;
+       }
+
+       playlist = ds->playlist();
+
+
+       TimeSelection time (selection.time);
+       float speed = ds->speed();
+       if (speed != 1.0f) {
+               for (TimeSelection::iterator i = time.begin(); i != time.end(); ++i) {
+                       (*i).start = session_frame_to_track_frame((*i).start, speed);
+                       (*i).end   = session_frame_to_track_frame((*i).end,   speed);
+               }
+       }
+       
+       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());
+                       ret = true;
+               }
+               break;
+       case Copy:
+               if ((what_we_got = playlist->copy (time)) != 0) {
+                       editor.get_cut_buffer().add (what_we_got);
+               }
+               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());
+                       what_we_got->unref ();
+                       ret = true;
+               }
+               break;
+       }
+
+       return ret;
+}
+
+bool
+RouteTimeAxisView::paste (jack_nframes_t pos, float times, Selection& selection, size_t nth)
+{
+       if (!is_track()) {
+               return false;
+       }
+
+       Playlist* playlist = get_diskstream()->playlist();
+       PlaylistSelection::iterator p;
+       
+       for (p = selection.playlists.begin(); p != selection.playlists.end() && nth; ++p, --nth);
+
+       if (p == selection.playlists.end()) {
+               return false;
+       }
+
+       if (get_diskstream()->speed() != 1.0f)
+               pos = session_frame_to_track_frame(pos, get_diskstream()->speed() );
+       
+       _session.add_undo (playlist->get_memento());
+       playlist->paste (**p, pos, times);
+       _session.add_redo_no_execute (playlist->get_memento());
+
+       return true;
+}
+
+
+list<TimeAxisView*>
+RouteTimeAxisView::get_child_list()
+{
+  
+       list<TimeAxisView*>redirect_children;
+       
+       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+               if (!(*i)->hidden()) {
+                       redirect_children.push_back(*i);
+               }
+       }
+       return redirect_children;
+}
+
+
+void
+RouteTimeAxisView::build_playlist_menu (Gtk::Menu * menu)
+{
+       using namespace Menu_Helpers;
+
+       if (!menu || !is_track()) {
+               return;
+       }
+
+       MenuList& playlist_items = menu->items();
+       menu->set_name ("ArdourContextMenu");
+       playlist_items.clear();
+
+       if (playlist_menu) {
+               delete playlist_menu;
+       }
+       playlist_menu = new Menu;
+       playlist_menu->set_name ("ArdourContextMenu");
+
+       playlist_items.push_back (MenuElem (string_compose (_("Current: %1"), get_diskstream()->playlist()->name())));
+       playlist_items.push_back (SeparatorElem());
+       
+       playlist_items.push_back (MenuElem (_("Rename"), mem_fun(*this, &RouteTimeAxisView::rename_current_playlist)));
+       playlist_items.push_back (SeparatorElem());
+
+       playlist_items.push_back (MenuElem (_("New"), mem_fun(editor, &PublicEditor::new_playlists)));
+       playlist_items.push_back (MenuElem (_("New Copy"), mem_fun(editor, &PublicEditor::copy_playlists)));
+       playlist_items.push_back (SeparatorElem());
+       playlist_items.push_back (MenuElem (_("Clear Current"), mem_fun(editor, &PublicEditor::clear_playlists)));
+       playlist_items.push_back (SeparatorElem());
+       playlist_items.push_back (MenuElem(_("Select"), mem_fun(*this, &RouteTimeAxisView::show_playlist_selector)));
+
+}
+
+void
+RouteTimeAxisView::show_playlist_selector ()
+{
+       editor.playlist_selector().show_for (this);
+}
+
+void
+RouteTimeAxisView::map_frozen ()
+{
+       if (!is_track()) {
+               return;
+       }
+
+       ENSURE_GUI_THREAD (mem_fun(*this, &RouteTimeAxisView::map_frozen));
+
+       switch (track()->freeze_state()) {
+       case Track::Frozen:
+               playlist_button.set_sensitive (false);
+               rec_enable_button->set_sensitive (false);
+               break;
+       default:
+               playlist_button.set_sensitive (true);
+               rec_enable_button->set_sensitive (true);
+               break;
+       }
+}
+
+void
+RouteTimeAxisView::color_handler (ColorID id, uint32_t val)
+{
+       switch (id) {
+       case cTimeStretchOutline:
+               timestretch_rect->property_outline_color_rgba() = val;
+               break;
+       case cTimeStretchFill:
+               timestretch_rect->property_fill_color_rgba() = val;
+               break;
+       default:
+               break;
+       }
+}
+
+bool
+RouteTimeAxisView::select_me (GdkEventButton* ev)
+{
+       editor.get_selection().add (this);
+       return false;
+}
+
+void
+RouteTimeAxisView::show_all_automation ()
+{
+       no_redraw = true;
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+                       if ((*ii)->view == 0) {
+                               add_redirect_automation_curve ((*i)->redirect, (*ii)->what);
+                       } 
+
+                       (*ii)->menu_item->set_active (true);
+               }
+       }
+
+       no_redraw = false;
+
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+void
+RouteTimeAxisView::show_existing_automation ()
+{
+       no_redraw = true;
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+                       if ((*ii)->view != 0) {
+                               (*ii)->menu_item->set_active (true);
+                       }
+               }
+       }
+
+       no_redraw = false;
+
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+void
+RouteTimeAxisView::hide_all_automation ()
+{
+       no_redraw = true;
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+                       (*ii)->menu_item->set_active (false);
+               }
+       }
+
+       no_redraw = false;
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+
+void
+RouteTimeAxisView::region_view_added (RegionView* rv)
+{
+       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+               AutomationTimeAxisView* atv;
+
+               if ((atv = dynamic_cast<AutomationTimeAxisView*> (*i)) != 0) {
+                       rv->add_ghost (*atv);
+               }
+       }
+}
+
+void
+RouteTimeAxisView::add_ghost_to_redirect (RegionView* rv, AutomationTimeAxisView* atv)
+{
+       rv->add_ghost (*atv);
+}
+
+RouteTimeAxisView::RedirectAutomationInfo::~RedirectAutomationInfo ()
+{
+       for (vector<RedirectAutomationNode*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+               delete *i;
+       }
+}
+
+
+RouteTimeAxisView::RedirectAutomationNode::~RedirectAutomationNode ()
+{
+       parent.remove_ran (this);
+
+       if (view) {
+               delete view;
+       }
+}
+
+void
+RouteTimeAxisView::remove_ran (RedirectAutomationNode* ran)
+{
+       if (ran->view) {
+               remove_child (ran->view);
+       }
+}
+
+RouteTimeAxisView::RedirectAutomationNode*
+RouteTimeAxisView::find_redirect_automation_node (boost::shared_ptr<Redirect> redirect, uint32_t what)
+{
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+
+               if ((*i)->redirect == redirect) {
+
+                       for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+                               if ((*ii)->what == what) {
+                                       return *ii;
+                               }
+                       }
+               }
+       }
+
+       return 0;
+}
+
+// FIXME: duplicated in midi_time_axis.cc
+static string 
+legalize_for_xml_node (string str)
+{
+       string::size_type pos;
+       string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=:";
+       string legal;
+
+       legal = str;
+       pos = 0;
+
+       while ((pos = legal.find_first_not_of (legal_chars, pos)) != string::npos) {
+               legal.replace (pos, 1, "_");
+               pos += 1;
+       }
+
+       return legal;
+}
+
+
+void
+RouteTimeAxisView::add_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what)
+{
+       RedirectAutomationLine* ral;
+       string name;
+       RedirectAutomationNode* ran;
+
+       if ((ran = find_redirect_automation_node (redirect, what)) == 0) {
+               fatal << _("programming error: ")
+                     << string_compose (X_("redirect automation curve for %1:%2 not registered with audio track!"),
+                                 redirect->name(), what)
+                     << endmsg;
+               /*NOTREACHED*/
+               return;
+       }
+
+       if (ran->view) {
+               return;
+       }
+
+       name = redirect->describe_parameter (what);
+
+       /* create a string that is a legal XML node name that can be used to refer to this redirect+port combination */
+
+       char state_name[256];
+       snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (redirect->name()).c_str(), what);
+
+       ran->view = new RedirectAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *redirect, state_name);
+
+       ral = new RedirectAutomationLine (name, 
+                                         *redirect, what, _session, *ran->view,
+                                         *ran->view->canvas_display, redirect->automation_list (what));
+       
+       ral->set_line_color (color_map[cRedirectAutomationLine]);
+       ral->queue_reset ();
+
+       ran->view->add_line (*ral);
+
+       ran->view->Hiding.connect (bind (mem_fun(*this, &RouteTimeAxisView::redirect_automation_track_hidden), ran, redirect));
+
+       if (!ran->view->marked_for_display()) {
+               ran->view->hide ();
+       } else {
+               ran->menu_item->set_active (true);
+       }
+
+       add_child (ran->view);
+
+       _view->foreach_regionview (bind (mem_fun(*this, &RouteTimeAxisView::add_ghost_to_redirect), ran->view));
+
+       redirect->mark_automation_visible (what, true);
+}
+
+void
+RouteTimeAxisView::redirect_automation_track_hidden (RouteTimeAxisView::RedirectAutomationNode* ran, boost::shared_ptr<Redirect> r)
+{
+       if (!_hidden) {
+               ran->menu_item->set_active (false);
+       }
+
+       r->mark_automation_visible (ran->what, false);
+
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+void
+RouteTimeAxisView::add_existing_redirect_automation_curves (boost::shared_ptr<Redirect> redirect)
+{
+       set<uint32_t> s;
+       RedirectAutomationLine *ral;
+
+       redirect->what_has_visible_automation (s);
+
+       for (set<uint32_t>::iterator i = s.begin(); i != s.end(); ++i) {
+               
+               if ((ral = find_redirect_automation_curve (redirect, *i)) != 0) {
+                       ral->queue_reset ();
+               } else {
+                       add_redirect_automation_curve (redirect, (*i));
+               }
+       }
+}
+
+void
+RouteTimeAxisView::add_redirect_to_subplugin_menu (boost::shared_ptr<Redirect> r)
+{
+       using namespace Menu_Helpers;
+       RedirectAutomationInfo *rai;
+       list<RedirectAutomationInfo*>::iterator x;
+       
+       const std::set<uint32_t>& automatable = r->what_can_be_automated ();
+       std::set<uint32_t> has_visible_automation;
+
+       r->what_has_visible_automation(has_visible_automation);
+
+       if (automatable.empty()) {
+               return;
+       }
+
+       for (x = redirect_automation.begin(); x != redirect_automation.end(); ++x) {
+               if ((*x)->redirect == r) {
+                       break;
+               }
+       }
+
+       if (x == redirect_automation.end()) {
+
+               rai = new RedirectAutomationInfo (r);
+               redirect_automation.push_back (rai);
+
+       } else {
+
+               rai = *x;
+
+       }
+
+       /* any older menu was deleted at the top of redirects_changed()
+          when we cleared the subplugin menu.
+       */
+
+       rai->menu = manage (new Menu);
+       MenuList& items = rai->menu->items();
+       rai->menu->set_name ("ArdourContextMenu");
+
+       items.clear ();
+
+       for (std::set<uint32_t>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) {
+
+               RedirectAutomationNode* ran;
+               CheckMenuItem* mitem;
+               
+               string name = r->describe_parameter (*i);
+               
+               items.push_back (CheckMenuElem (name));
+               mitem = dynamic_cast<CheckMenuItem*> (&items.back());
+
+               if (has_visible_automation.find((*i)) != has_visible_automation.end()) {
+                       mitem->set_active(true);
+               }
+
+               if ((ran = find_redirect_automation_node (r, *i)) == 0) {
+
+                       /* new item */
+                       
+                       ran = new RedirectAutomationNode (*i, mitem, *this);
+                       
+                       rai->lines.push_back (ran);
+
+               } else {
+
+                       ran->menu_item = mitem;
+
+               }
+
+               mitem->signal_toggled().connect (bind (mem_fun(*this, &RouteTimeAxisView::redirect_menu_item_toggled), rai, ran));
+       }
+
+       /* add the menu for this redirect, because the subplugin
+          menu is always cleared at the top of redirects_changed().
+          this is the result of some poor design in gtkmm and/or
+          GTK+.
+       */
+
+       subplugin_menu.items().push_back (MenuElem (r->name(), *rai->menu));
+       rai->valid = true;
+}
+
+void
+RouteTimeAxisView::redirect_menu_item_toggled (RouteTimeAxisView::RedirectAutomationInfo* rai,
+                                              RouteTimeAxisView::RedirectAutomationNode* ran)
+{
+       bool showit = ran->menu_item->get_active();
+       bool redraw = false;
+
+       if (ran->view == 0 && showit) {
+               add_redirect_automation_curve (rai->redirect, ran->what);
+               redraw = true;
+       }
+
+       if (showit != ran->view->marked_for_display()) {
+
+               if (showit) {
+                       ran->view->set_marked_for_display (true);
+                       ran->view->canvas_display->show();
+               } else {
+                       rai->redirect->mark_automation_visible (ran->what, true);
+                       ran->view->set_marked_for_display (false);
+                       ran->view->hide ();
+               }
+
+               redraw = true;
+
+       }
+
+       if (redraw && !no_redraw) {
+
+               /* now trigger a redisplay */
+               
+                _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+
+       }
+}
+
+void
+RouteTimeAxisView::redirects_changed (void *src)
+{
+       using namespace Menu_Helpers;
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               (*i)->valid = false;
+       }
+
+       subplugin_menu.items().clear ();
+
+       _route->foreach_redirect (this, &RouteTimeAxisView::add_redirect_to_subplugin_menu);
+       _route->foreach_redirect (this, &RouteTimeAxisView::add_existing_redirect_automation_curves);
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ) {
+
+               list<RedirectAutomationInfo*>::iterator tmp;
+
+               tmp = i;
+               ++tmp;
+
+               if (!(*i)->valid) {
+
+                       delete *i;
+                       redirect_automation.erase (i);
+
+               } 
+
+               i = tmp;
+       }
+
+       /* change in visibility was possible */
+
+       _route->gui_changed ("track_height", this);
+}
+
+RedirectAutomationLine *
+RouteTimeAxisView::find_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what)
+{
+       RedirectAutomationNode* ran;
+
+       if ((ran = find_redirect_automation_node (redirect, what)) != 0) {
+               if (ran->view) {
+                       return dynamic_cast<RedirectAutomationLine*> (ran->view->lines.front());
+               } 
+       }
+
+       return 0;
+}
+
+void
+RouteTimeAxisView::reset_redirect_automation_curves ()
+{
+       for (vector<RedirectAutomationLine*>::iterator i = redirect_automation_curves.begin(); i != redirect_automation_curves.end(); ++i) {
+               (*i)->reset();
+       }
+}
+
diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h
new file mode 100644 (file)
index 0000000..d305fd3
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+    Copyright (C) 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
+    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: audio_time_axis.h 664 2006-07-05 19:47:25Z drobilla $
+*/
+
+#ifndef __ardour_route_time_axis_h__
+#define __ardour_route_time_axis_h__
+
+#include <gtkmm/table.h>
+#include <gtkmm/button.h>
+#include <gtkmm/box.h>
+#include <gtkmm/menu.h>
+#include <gtkmm/menuitem.h>
+#include <gtkmm/radiomenuitem.h>
+#include <gtkmm/checkmenuitem.h>
+
+#include <gtkmm2ext/selector.h>
+#include <list>
+
+#include <ardour/types.h>
+
+#include "ardour_dialog.h"
+#include "route_ui.h"
+#include "enums.h"
+#include "time_axis_view.h"
+#include "canvas.h"
+#include "color.h"
+
+namespace ARDOUR {
+       class Session;
+       class Region;
+       class Diskstream;
+       class RouteGroup;
+       class Redirect;
+       class Insert;
+       class Location;
+       class Playlist;
+}
+
+class PublicEditor;
+class RegionView;
+class StreamView;
+class Selection;
+class RegionSelection;
+class Selectable;
+class AutomationTimeAxisView;
+class AutomationLine;
+class RedirectAutomationLine;
+class TimeSelection;
+
+class RouteTimeAxisView : public RouteUI, public TimeAxisView
+{
+public:
+       RouteTimeAxisView (PublicEditor&, ARDOUR::Session&, boost::shared_ptr<ARDOUR::Route>, ArdourCanvas::Canvas& canvas);
+       virtual ~RouteTimeAxisView ();
+
+       void show_selection (TimeSelection&);
+
+       void set_samples_per_unit (double);
+       void set_height (TimeAxisView::TrackHeight);
+       void show_timestretch (jack_nframes_t start, jack_nframes_t end);
+       void hide_timestretch ();
+       void selection_click (GdkEventButton*);
+       void set_selected_points (PointSelection&);
+       void set_selected_regionviews (RegionSelection&);
+       void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable *>&);
+       void get_inverted_selectables (Selection&, list<Selectable*>&);
+               
+       ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir);
+
+       /* Editing operations */
+       bool cut_copy_clear (Selection&, Editing::CutCopyOp);
+       bool paste (jack_nframes_t, float times, Selection&, size_t nth);
+
+       list<TimeAxisView*> get_child_list();
+
+       /* The editor calls these when mapping an operation across multiple tracks */
+       void use_new_playlist (bool prompt);
+       void use_copy_playlist (bool prompt);
+       void clear_playlist ();
+       
+       void build_playlist_menu (Gtk::Menu *);
+       
+       string              name() const;
+       StreamView*         view() const { return _view; }
+       ARDOUR::RouteGroup* edit_group() const;
+       ARDOUR::Playlist*   playlist() const;
+
+protected:
+       friend class StreamView;
+       
+       struct RedirectAutomationNode {
+           uint32_t                what;
+           Gtk::CheckMenuItem*     menu_item;
+           AutomationTimeAxisView* view;
+           RouteTimeAxisView&      parent;
+
+           RedirectAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, RouteTimeAxisView& p)
+                   : what (w), menu_item (mitem), view (0), parent (p) {}
+
+           ~RedirectAutomationNode ();
+       };
+
+       struct RedirectAutomationInfo {
+           boost::shared_ptr<ARDOUR::Redirect> redirect;
+           bool                                valid;
+           Gtk::Menu*                          menu;
+           vector<RedirectAutomationNode*>     lines;
+
+           RedirectAutomationInfo (boost::shared_ptr<ARDOUR::Redirect> r) 
+                   : redirect (r), valid (true), menu (0) {}
+
+           ~RedirectAutomationInfo ();
+       };
+       
+
+       void diskstream_changed ();
+       void update_diskstream_display ();
+       
+       gint edit_click  (GdkEventButton *);
+
+       void build_redirect_window ();
+       void redirect_click ();
+       void redirect_add ();
+       void redirect_remove ();
+       void redirect_edit ();
+       void redirect_relist ();
+       void redirect_row_selected (gint row, gint col, GdkEvent *ev);
+       void add_to_redirect_display (ARDOUR::Redirect *);
+       void redirects_changed (void *);
+       
+       void add_redirect_to_subplugin_menu (boost::shared_ptr<ARDOUR::Redirect>);
+       void remove_ran (RedirectAutomationNode* ran);
+
+       void redirect_menu_item_toggled (RouteTimeAxisView::RedirectAutomationInfo*,
+                                        RouteTimeAxisView::RedirectAutomationNode*);
+       
+       void redirect_automation_track_hidden (RedirectAutomationNode*,
+                                              boost::shared_ptr<ARDOUR::Redirect>);
+
+       RedirectAutomationNode*
+       find_redirect_automation_node (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
+       
+       RedirectAutomationLine*
+       find_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
+
+       void add_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
+       void add_existing_redirect_automation_curves (boost::shared_ptr<ARDOUR::Redirect>);
+       
+       void reset_redirect_automation_curves ();
+
+       void update_automation_view (ARDOUR::AutomationType);
+       
+       void take_name_changed (void *);
+       void route_name_changed (void *);
+       void name_entry_changed ();
+
+       void on_area_realize ();
+
+       virtual void label_view ();
+       
+       void add_edit_group_menu_item (ARDOUR::RouteGroup *, Gtk::RadioMenuItem::Group*);
+       void set_edit_group_from_menu (ARDOUR::RouteGroup *);
+
+       void reset_samples_per_unit ();
+
+       void select_track_color();
+       
+       virtual void build_automation_action_menu ();
+       virtual void append_extra_display_menu_items () {}
+       void         build_display_menu ();
+       
+       void align_style_changed ();
+       void set_align_style (ARDOUR::AlignStyle);
+       
+       virtual void set_playlist (ARDOUR::Playlist *);
+       void         playlist_click ();
+       void         show_playlist_selector ();
+       void         playlist_changed ();
+       void         playlist_state_changed (ARDOUR::Change);
+       void         playlist_modified ();
+
+       void add_playlist_to_playlist_menu (ARDOUR::Playlist*);
+       void rename_current_playlist ();
+       
+       void         automation_click ();
+       virtual void show_all_automation ();
+       virtual void show_existing_automation ();
+       virtual void hide_all_automation ();
+
+       void timestretch (jack_nframes_t start, jack_nframes_t end);
+
+       void visual_click ();
+       void hide_click ();
+       gint when_displayed (GdkEventAny*);
+
+       void speed_changed ();
+       
+       void map_frozen ();
+
+       void color_handler (ColorID, uint32_t);
+       bool select_me (GdkEventButton*);
+       
+       void region_view_added (RegionView*);
+       void add_ghost_to_redirect (RegionView*, AutomationTimeAxisView*);
+       
+       
+       StreamView*           _view;
+       ArdourCanvas::Canvas& parent_canvas;
+       bool                  no_redraw;
+  
+       Gtk::HBox   other_button_hbox;
+       Gtk::Table  button_table;
+       Gtk::Button redirect_button;
+       Gtk::Button edit_group_button;
+       Gtk::Button playlist_button;
+       Gtk::Button size_button;
+       Gtk::Button automation_button;
+       Gtk::Button hide_button;
+       Gtk::Button visual_button;
+       
+       Gtk::Menu           subplugin_menu;
+       Gtk::Menu*          automation_action_menu;
+       Gtk::Menu           edit_group_menu;
+       Gtk::RadioMenuItem* align_existing_item;
+       Gtk::RadioMenuItem* align_capture_item;
+       Gtk::Menu*          playlist_menu;
+       Gtk::Menu*          playlist_action_menu;
+       Gtk::MenuItem*      playlist_item;
+
+       ArdourCanvas::SimpleRect* timestretch_rect;
+       
+       list<RedirectAutomationInfo*>   redirect_automation;
+       vector<RedirectAutomationLine*> redirect_automation_curves;
+
+       sigc::connection modified_connection;
+       sigc::connection state_changed_connection;
+};
+
+#endif /* __ardour_route_time_axis_h__ */
+
index 988d6c8b196b542e9ee8e3c679c1d115399511cf..8a1fb1c21aecf813f53fa073e2cd07401de36aed 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2002 Paul Davis 
+    Copyright (C) 2002-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
@@ -21,8 +21,8 @@
 #include <gtkmm2ext/gtk_ui.h>
 #include <gtkmm2ext/stop_signal.h>
 #include <gtkmm2ext/choice.h>
-#include <gtkmm2ext/bindable_button.h>
 #include <gtkmm2ext/doi.h>
+#include <gtkmm2ext/bindable_button.h>
 
 #include <ardour/route_group.h>
 #include <pbd/memento_command.h>
@@ -45,9 +45,9 @@ using namespace ARDOUR;
 using namespace PBD;
 
 
-RouteUI::RouteUI (ARDOUR::Route& rt, ARDOUR::Session& sess, const char* m_name,
+RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, const char* m_name,
                  const char* s_name, const char* r_name)
-    : AxisView(sess),
+       : AxisView(sess),
          _route(rt),
          mute_button(0),
          solo_button(0),
@@ -65,35 +65,31 @@ RouteUI::RouteUI (ARDOUR::Route& rt, ARDOUR::Session& sess, const char* m_name,
                set_color (unique_random_color());
        }
 
-       _route.GoingAway.connect (mem_fun (*this, &RouteUI::route_removed));
-       _route.active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed));
+       _route->GoingAway.connect (mem_fun (*this, &RouteUI::route_removed));
+       _route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed));
 
-        mute_button = manage (new BindableToggleButton (& _route.midi_mute_control(), m_name ));
-       mute_button->set_bind_button_state (2, GDK_CONTROL_MASK);
-        solo_button = manage (new BindableToggleButton (& _route.midi_solo_control(), s_name ));
-       solo_button->set_bind_button_state (2, GDK_CONTROL_MASK);
-
-       if (is_audio_track()) {
-               AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
+        mute_button = manage (new BindableToggleButton (_route->mute_control(), m_name ));
+        solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name ));
+       
+       if (is_track()) {
+               boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
 
-               get_diskstream()->record_enable_changed.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
+               t->diskstream().RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
 
                _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
 
-               rec_enable_button = manage (new BindableToggleButton (& at->midi_rec_enable_control(), r_name ));
-               rec_enable_button->set_bind_button_state (2, GDK_CONTROL_MASK);
+               rec_enable_button = manage (new BindableToggleButton (t->rec_enable_control(), r_name ));
 
-       } else {
-               rec_enable_button = manage (new BindableToggleButton (0, r_name ));
-       }
+               rec_enable_button->unset_flags (Gtk::CAN_FOCUS);
+               
+               update_rec_display ();
+       } 
        
        mute_button->unset_flags (Gtk::CAN_FOCUS);
        solo_button->unset_flags (Gtk::CAN_FOCUS);
-       rec_enable_button->unset_flags (Gtk::CAN_FOCUS);
 
        /* map the current state */
 
-       update_rec_display ();
        map_frozen ();
 }
 
@@ -146,14 +142,14 @@ RouteUI::mute_press(GdkEventButton* ev)
                                        */
 
                                        if (ev->button == 1) {
-                                               set_mix_group_mute (_route, !_route.muted());
+                                               set_mix_group_mute (_route, !_route->muted());
                                        }
                                        
                                } else {
 
                                        /* plain click applies change to this route */
 
-                                       reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route.muted(), this);
+                                       reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
                                }
                        }
                }
@@ -231,7 +227,7 @@ RouteUI::solo_press(GdkEventButton* ev)
 
                                        // shift-click: set this route to solo safe
 
-                                       _route.set_solo_safe (!_route.solo_safe(), this);
+                                       _route->set_solo_safe (!_route->solo_safe(), this);
                                        wait_for_release = false;
 
                                } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
@@ -241,14 +237,14 @@ RouteUI::solo_press(GdkEventButton* ev)
                                        */
 
                                        if (ev->button == 1) {
-                                               set_mix_group_solo (_route, !_route.soloed());
+                                               set_mix_group_solo (_route, !_route->soloed());
                                        }
 
                                } else {
 
                                        /* click: solo this route */
 
-                                       reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route.soloed(), this);
+                                       reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
                                }
                        }
                }
@@ -276,7 +272,7 @@ RouteUI::solo_release(GdkEventButton* ev)
 gint
 RouteUI::rec_enable_press(GdkEventButton* ev)
 {
-       if (!ignore_toggle && is_audio_track()) {
+       if (!ignore_toggle && is_track() && rec_enable_button) {
 
                if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
                        // do nothing on midi bind event
@@ -298,7 +294,7 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
 
                } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
 
-                       set_mix_group_rec_enable (_route, !_route.record_enabled());
+                       set_mix_group_rec_enable (_route, !_route->record_enabled());
 
                } else {
 
@@ -326,7 +322,7 @@ RouteUI::update_solo_display ()
 {
        bool x;
 
-       if (solo_button->get_active() != (x = _route.soloed())){
+       if (solo_button->get_active() != (x = _route->soloed())){
                ignore_toggle = true;
                solo_button->set_active(x);
                ignore_toggle = false;
@@ -334,7 +330,7 @@ RouteUI::update_solo_display ()
        
        /* show solo safe */
 
-       if (_route.solo_safe()){
+       if (_route->solo_safe()){
                solo_button->set_name(safe_solo_button_name());
        } else {
                solo_button->set_name(solo_button_name());
@@ -352,7 +348,7 @@ RouteUI::update_mute_display ()
 {
        bool x;
 
-       if (mute_button->get_active() != (x = _route.muted())){
+       if (mute_button->get_active() != (x = _route->muted())){
                ignore_toggle = true;
                mute_button->set_active(x);
                ignore_toggle = false;
@@ -360,7 +356,7 @@ RouteUI::update_mute_display ()
 }
 
 void
-RouteUI::route_rec_enable_changed (void *src)
+RouteUI::route_rec_enable_changed ()
 {
        Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
 }
@@ -374,7 +370,7 @@ RouteUI::session_rec_enable_changed ()
 void
 RouteUI::update_rec_display ()
 {
-       bool model = _route.record_enabled();
+       bool model = _route->record_enabled();
        bool view = rec_enable_button->get_active();
 
        /* first make sure the button's "depressed" visual
@@ -440,7 +436,7 @@ RouteUI::refresh_remote_control_menu ()
        limit += 4; /* leave some breathing room */
        
        rc_items.push_back (RadioMenuElem (rc_group, _("None")));
-       if (_route.remote_control_id() == 0) {
+       if (_route->remote_control_id() == 0) {
                rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
                rc_active->set_active ();
        }
@@ -449,7 +445,7 @@ RouteUI::refresh_remote_control_menu ()
                snprintf (buf, sizeof (buf), "%u", i);
                rc_items.push_back (RadioMenuElem (rc_group, buf));
                rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
-               if (_route.remote_control_id() == i) {
+               if (_route->remote_control_id() == i) {
                        rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
                        rc_active->set_active ();
                }
@@ -467,7 +463,7 @@ RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
        */
 
        if (item->get_active()) {
-               _route.set_remote_control_id (id);
+               _route->set_remote_control_id (id);
        }
 }
 
@@ -482,14 +478,14 @@ RouteUI::build_solo_menu (void)
        CheckMenuItem* check;
 
        check = new CheckMenuItem(_("Solo-safe"));
-       check->set_active (_route.solo_safe());
+       check->set_active (_route->solo_safe());
        check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
-       _route.solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
+       _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
        items.push_back (CheckMenuElem(*check));
        check->show_all();
 
        items.push_back (SeparatorElem());
-       items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
+       // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
        
 }
 
@@ -506,39 +502,39 @@ RouteUI::build_mute_menu(void)
        check = new CheckMenuItem(_("Pre Fader"));
        init_mute_menu(PRE_FADER, check);
        check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
-       _route.pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
+       _route->pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
        items.push_back (CheckMenuElem(*check));
        check->show_all();
 
        check = new CheckMenuItem(_("Post Fader"));
        init_mute_menu(POST_FADER, check);
        check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
-       _route.post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
+       _route->post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
        items.push_back (CheckMenuElem(*check));
        check->show_all();
        
        check = new CheckMenuItem(_("Control Outs"));
        init_mute_menu(CONTROL_OUTS, check);
        check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
-       _route.control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
+       _route->control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
        items.push_back (CheckMenuElem(*check));
        check->show_all();
 
        check = new CheckMenuItem(_("Main Outs"));
        init_mute_menu(MAIN_OUTS, check);
        check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
-       _route.main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
+       _route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
        items.push_back (CheckMenuElem(*check));
        check->show_all();
 
        items.push_back (SeparatorElem());
-       items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
+       // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
 }
 
 void
 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
 {
-       if (_route.get_mute_config (type)) {
+       if (_route->get_mute_config (type)) {
                check->set_active (true);
        }
 }
@@ -546,21 +542,21 @@ RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
 void
 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
 {
-       _route.set_mute_config(type, check->get_active(), this);
+       _route->set_mute_config(type, check->get_active(), this);
 }
 
 void
 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
 {
-       _route.set_solo_safe (check->get_active(), this);
+       _route->set_solo_safe (check->get_active(), this);
 }
 
 void
-RouteUI::set_mix_group_solo(Route& route, bool yn)
+RouteUI::set_mix_group_solo(boost::shared_ptr<Route> route, bool yn)
 {
        RouteGroup* mix_group;
 
-       if((mix_group = route.mix_group()) != 0){
+       if((mix_group = route->mix_group()) != 0){
                _session.begin_reversible_command (_("mix group solo  change"));
                 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
                mix_group->apply(&Route::set_solo, yn, this);
@@ -568,7 +564,7 @@ RouteUI::set_mix_group_solo(Route& route, bool yn)
                _session.add_command (cmd);
                _session.commit_reversible_command ();
        } else {
-               reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route.soloed(), this);
+               reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
        }
 }
 
@@ -595,11 +591,11 @@ RouteUI::reversibly_apply_audio_track_boolean (string name, void (AudioTrack::*f
 }
 
 void
-RouteUI::set_mix_group_mute(Route& route, bool yn)
+RouteUI::set_mix_group_mute(boost::shared_ptr<Route> route, bool yn)
 {
        RouteGroup* mix_group;
 
-       if((mix_group = route.mix_group()) != 0){
+       if((mix_group = route->mix_group()) != 0){
                _session.begin_reversible_command (_("mix group mute change"));
                 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
                mix_group->apply(&Route::set_mute, yn, this);
@@ -607,16 +603,16 @@ RouteUI::set_mix_group_mute(Route& route, bool yn)
                _session.add_command(cmd);
                _session.commit_reversible_command ();
        } else {
-               reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route.muted(), this);
+               reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
        }
 }
 
 void
-RouteUI::set_mix_group_rec_enable(Route& route, bool yn)
+RouteUI::set_mix_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
 {
        RouteGroup* mix_group;
 
-       if((mix_group = route.mix_group()) != 0){
+       if((mix_group = route->mix_group()) != 0){
                _session.begin_reversible_command (_("mix group rec-enable change"));
                 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
                mix_group->apply (&Route::set_record_enable, yn, this);
@@ -624,7 +620,7 @@ RouteUI::set_mix_group_rec_enable(Route& route, bool yn)
                _session.add_command(cmd);
                _session.commit_reversible_command ();
        } else {
-               reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route.record_enabled(), this);
+               reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
        }
 }
 
@@ -655,7 +651,7 @@ RouteUI::set_color (const Gdk::Color & c)
        snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
        xml_node->add_property ("color", buf);
 
-        _route.gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
+        _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
 }
 
 
@@ -663,9 +659,9 @@ void
 RouteUI::ensure_xml_node ()
 {
        if (xml_node == 0) {
-               if ((xml_node = _route.extra_xml ("GUI")) == 0) {
+               if ((xml_node = _route->extra_xml ("GUI")) == 0) {
                        xml_node = new XMLNode ("GUI");
-                       _route.add_extra_xml (*xml_node);
+                       _route->add_extra_xml (*xml_node);
                }
        }
 }
@@ -710,10 +706,10 @@ RouteUI::remove_this_route ()
        vector<string> choices;
        string prompt;
 
-       if (is_audio_track()) {
-               prompt  = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n(cannot be undone)"), _route.name());
+       if (is_track()) {
+               prompt  = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n(cannot be undone)"), _route->name());
        } else {
-               prompt  = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route.name());
+               prompt  = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
        }
 
        choices.push_back (_("No, do nothing."));
@@ -747,7 +743,7 @@ RouteUI::route_rename ()
        ArdourPrompter name_prompter (true);
        string result;
        name_prompter.set_prompt (_("New Name: "));
-       name_prompter.set_initial_text (_route.name());
+       name_prompter.set_initial_text (_route->name());
        name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
        name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
        name_prompter.show_all ();
@@ -757,7 +753,7 @@ RouteUI::route_rename ()
        case Gtk::RESPONSE_ACCEPT:
         name_prompter.get_result (result);
         if (result.length()) {
-                       _route.set_name (result, this);
+                       _route->set_name (result, this);
                }       
                break;
        }
@@ -771,7 +767,7 @@ RouteUI::name_changed (void *src)
 {
        ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::name_changed), src));
 
-       name_label.set_text (_route.name());
+       name_label.set_text (_route->name());
 }
 
 void
@@ -780,8 +776,8 @@ RouteUI::toggle_route_active ()
        bool yn;
 
        if (route_active_menu_item) {
-               if (route_active_menu_item->get_active() != (yn = _route.active())) {
-                       _route.set_active (!yn);
+               if (route_active_menu_item->get_active() != (yn = _route->active())) {
+                       _route->set_active (!yn);
                }
        }
 }
@@ -790,7 +786,7 @@ void
 RouteUI::route_active_changed ()
 {
        if (route_active_menu_item) {
-               Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route.active()));
+               Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
        }
 }
 
@@ -803,12 +799,12 @@ RouteUI::toggle_polarity ()
 
                ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
                
-               if ((x = polarity_menu_item->get_active()) != _route.phase_invert()) {
-                       _route.set_phase_invert (x, this);
+               if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
+                       _route->set_phase_invert (x, this);
                        if (x) {
                                name_label.set_text (X_("Ø ") + name_label.get_text());
                        } else {
-                               name_label.set_text (_route.name());
+                               name_label.set_text (_route->name());
                        }
                }
        }
@@ -823,7 +819,7 @@ RouteUI::polarity_changed ()
 void
 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
 {
-       bool yn = _route.solo_safe ();
+       bool yn = _route->solo_safe ();
 
        if (check->get_active() != yn) {
                check->set_active (yn);
@@ -834,7 +830,7 @@ RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
 {
        ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
        
-       bool yn = _route.get_mute_config(PRE_FADER);
+       bool yn = _route->get_mute_config(PRE_FADER);
        if (check->get_active() != yn) {
                check->set_active (yn);
        }
@@ -845,7 +841,7 @@ RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
 {
        ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
        
-       bool yn = _route.get_mute_config(POST_FADER);
+       bool yn = _route->get_mute_config(POST_FADER);
        if (check->get_active() != yn) {
                check->set_active (yn);
        }
@@ -856,7 +852,7 @@ RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
 {
        ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
        
-       bool yn = _route.get_mute_config(CONTROL_OUTS);
+       bool yn = _route->get_mute_config(CONTROL_OUTS);
        if (check->get_active() != yn) {
                check->set_active (yn);
        }
@@ -867,7 +863,7 @@ RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
 {
        ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
        
-       bool yn = _route.get_mute_config(MAIN_OUTS);
+       bool yn = _route->get_mute_config(MAIN_OUTS);
        if (check->get_active() != yn) {
                check->set_active (yn);
        }
@@ -876,42 +872,55 @@ RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
 void
 RouteUI::disconnect_input ()
 {
-       _route.disconnect_inputs (this);
+       _route->disconnect_inputs (this);
 }
 
 void
 RouteUI::disconnect_output ()
 {
-       _route.disconnect_outputs (this);
+       _route->disconnect_outputs (this);
+}
+
+bool
+RouteUI::is_track () const
+{
+       return dynamic_cast<Track*>(_route.get()) != 0;
+}
+
+Track*
+RouteUI::track() const
+{
+       return dynamic_cast<Track*>(_route.get());
 }
 
 bool
 RouteUI::is_audio_track () const
 {
-       return dynamic_cast<AudioTrack*>(&_route) != 0;
+       return dynamic_cast<AudioTrack*>(_route.get()) != 0;
+}
+
+AudioTrack*
+RouteUI::audio_track() const
+{
+       return dynamic_cast<AudioTrack*>(_route.get());
 }
 
-AudioDiskstream*
+Diskstream*
 RouteUI::get_diskstream () const
 {
-       AudioTrack *at;
+       boost::shared_ptr<Track> t;
 
-       if ((at = dynamic_cast<AudioTrack*>(&_route)) != 0) {
-               return &at->disk_stream();
+       if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
+               return &t->diskstream();
        } else {
                return 0;
        }
 }
 
-AudioTrack*
-RouteUI::audio_track() const
-{
-       return dynamic_cast<AudioTrack*>(&_route);
-}
 string
 RouteUI::name() const
 {
-       return _route.name();
+       return _route->name();
 }
 
 void
@@ -919,7 +928,7 @@ RouteUI::map_frozen ()
 {
        ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
 
-       AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
+       AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
 
        if (at) {
                switch (at->freeze_state()) {
@@ -932,3 +941,4 @@ RouteUI::map_frozen ()
                }
        }
 }
+
index 69c9b7f5a9ac92f0788e2f4183fb028517774c99..7415eddad6b58367eb13217da207e515c4e91a4e 100644 (file)
 #include <pbd/xml++.h>
 #include <ardour/ardour.h>
 #include <ardour/route.h>
+#include <ardour/track.h>
 
 #include "axis_view.h"
 
-namespace Gtkmm2ext {
-       class BindableToggleButton;
-}
-
 namespace ARDOUR {
        class AudioTrack;
 }
@@ -43,21 +40,30 @@ namespace Gtk {
        class Widget;
 }
 
+class BindableToggleButton;
+
 class RouteUI : public virtual AxisView
 {
   public:
-       RouteUI(ARDOUR::Route&, ARDOUR::Session&, const char*, const char*, const char*);
+       RouteUI(boost::shared_ptr<ARDOUR::Route>, ARDOUR::Session&, const char*, const char*, const char*);
        virtual ~RouteUI();
 
+       bool is_track() const;
        bool is_audio_track() const;
-       ARDOUR::AudioDiskstream* get_diskstream() const;
 
-       ARDOUR::Route& route() const { return _route; }
+       boost::shared_ptr<ARDOUR::Route> route() const { return _route; }
+       
+       // FIXME: make these return shared_ptr
+       ARDOUR::Track*      track() const;
        ARDOUR::AudioTrack* audio_track() const;
+       
+       ARDOUR::Diskstream* get_diskstream() const;
 
        string name() const;
-       
-       ARDOUR::Route& _route;
+
+       // protected: XXX sigh this should be here
+
+       boost::shared_ptr<ARDOUR::Route> _route;
        
        void set_color (const Gdk::Color & c);
        bool choose_color ();
@@ -65,9 +71,9 @@ class RouteUI : public virtual AxisView
        bool ignore_toggle;
        bool wait_for_release;
 
-       Gtkmm2ext::BindableToggleButton * mute_button;
-       Gtkmm2ext::BindableToggleButton * solo_button;
-       Gtkmm2ext::BindableToggleButton * rec_enable_button;
+       BindableToggleButton* mute_button;
+       BindableToggleButton* solo_button;
+       BindableToggleButton* rec_enable_button;
        
        virtual string solo_button_name () const { return "SoloButton"; }
        virtual string safe_solo_button_name () const { return "SafeSoloButton"; }
@@ -89,7 +95,8 @@ class RouteUI : public virtual AxisView
 
        void solo_changed(void*);
        void mute_changed(void*);
-       void route_rec_enable_changed(void*);
+       virtual void redirects_changed (void *) {}
+       void route_rec_enable_changed();
        void session_rec_enable_changed();
 
        void build_solo_menu (void);
@@ -108,9 +115,9 @@ class RouteUI : public virtual AxisView
        void build_mute_menu(void);
        void init_mute_menu(ARDOUR::mute_type, Gtk::CheckMenuItem*);
        
-       void set_mix_group_solo(ARDOUR::Route&, bool);
-       void set_mix_group_mute(ARDOUR::Route&, bool);
-       void set_mix_group_rec_enable(ARDOUR::Route&, bool);
+       void set_mix_group_solo(boost::shared_ptr<ARDOUR::Route>, bool);
+       void set_mix_group_mute(boost::shared_ptr<ARDOUR::Route>, bool);
+       void set_mix_group_rec_enable(boost::shared_ptr<ARDOUR::Route>, bool);
 
        int  set_color_from_route ();
 
index b4be7090e25609b695398244033607630d9a7694..b52214c9c9610e14e5f4257f5ccd2bf2e09dc1db 100644 (file)
@@ -34,7 +34,7 @@ class Selectable : public virtual sigc::trackable
 
        virtual void set_selected (bool yn) {
                if (yn != _selected) {
-                       _selected = true;
+                       _selected = yn;
                        Selected (_selected); /* EMIT_SIGNAL */
                }
        }
index 2e4ed8a1176caba4287e60b7d9f78199ba21ac8c..086d878994813f56ce96e2faa98cbfd7b15b46da 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <ardour/playlist.h>
 
-#include "regionview.h"
+#include "region_view.h"
 #include "selection.h"
 #include "selection_templates.h"
 #include "time_axis_view.h"
@@ -46,7 +46,7 @@ Selection&
 Selection::operator= (const Selection& other)
 {
        if (&other != this) {
-               audio_regions = other.audio_regions;
+               regions = other.regions;
                tracks = other.tracks;
                time = other.time;
                lines = other.lines;
@@ -57,7 +57,7 @@ Selection::operator= (const Selection& other)
 bool
 operator== (const Selection& a, const Selection& b)
 {
-       return a.audio_regions == b.audio_regions &&
+       return a.regions == b.regions &&
                a.tracks == b.tracks &&
                a.time.track == b.time.track &&
                a.time.group == b.time.group && 
@@ -71,7 +71,7 @@ void
 Selection::clear ()
 {
        clear_tracks ();
-       clear_audio_regions ();
+       clear_regions ();
        clear_points ();
        clear_lines();
        clear_time ();
@@ -83,8 +83,8 @@ void
 Selection::dump_region_layers()
 {
        cerr << "region selection layer dump" << endl;
-       for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
-               cerr << "layer: " << (int)(*i)->region.layer() << endl;
+       for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
+               cerr << "layer: " << (int)(*i)->region().layer() << endl;
        }
 }
 
@@ -99,10 +99,10 @@ Selection::clear_redirects ()
 }
 
 void
-Selection::clear_audio_regions ()
+Selection::clear_regions ()
 {
-       if (!audio_regions.empty()) {
-               audio_regions.clear_all ();
+       if (!regions.empty()) {
+               regions.clear_all ();
                RegionsChanged();
        }
 }
@@ -151,7 +151,7 @@ Selection::clear_lines ()
 }
 
 void
-Selection::toggle (Redirect* r)
+Selection::toggle (boost::shared_ptr<Redirect> r)
 {
        RedirectSelection::iterator i;
 
@@ -196,29 +196,29 @@ Selection::toggle (TimeAxisView* track)
 }
 
 void
-Selection::toggle (AudioRegionView* r)
+Selection::toggle (RegionView* r)
 {
-       AudioRegionSelection::iterator i;
+       RegionSelection::iterator i;
 
-       if ((i = find (audio_regions.begin(), audio_regions.end(), r)) == audio_regions.end()) {
-               audio_regions.add (r);
+       if ((i = find (regions.begin(), regions.end(), r)) == regions.end()) {
+               regions.add (r);
        } else {
-               audio_regions.erase (i);
+               regions.erase (i);
        }
 
        RegionsChanged ();
 }
 
 void
-Selection::toggle (vector<AudioRegionView*>& r)
+Selection::toggle (vector<RegionView*>& r)
 {
-       AudioRegionSelection::iterator i;
+       RegionSelection::iterator i;
 
-       for (vector<AudioRegionView*>::iterator x = r.begin(); x != r.end(); ++x) {
-               if ((i = find (audio_regions.begin(), audio_regions.end(), (*x))) == audio_regions.end()) {
-                       audio_regions.add ((*x));
+       for (vector<RegionView*>::iterator x = r.begin(); x != r.end(); ++x) {
+               if ((i = find (regions.begin(), regions.end(), (*x))) == regions.end()) {
+                       regions.add ((*x));
                } else {
-                       audio_regions.erase (i);
+                       regions.erase (i);
                }
        }
 
@@ -243,7 +243,7 @@ Selection::toggle (jack_nframes_t start, jack_nframes_t end)
 
 
 void
-Selection::add (Redirect* r)
+Selection::add (boost::shared_ptr<Redirect> r)
 {
        if (find (redirects.begin(), redirects.end(), r) == redirects.end()) {
                redirects.push_back (r);
@@ -310,22 +310,22 @@ Selection::add (TimeAxisView* track)
 }
 
 void
-Selection::add (AudioRegionView* r)
+Selection::add (RegionView* r)
 {
-       if (find (audio_regions.begin(), audio_regions.end(), r) == audio_regions.end()) {
-               audio_regions.add (r);
+       if (find (regions.begin(), regions.end(), r) == regions.end()) {
+               regions.add (r);
                RegionsChanged ();
        }
 }
 
 void
-Selection::add (vector<AudioRegionView*>& v)
+Selection::add (vector<RegionView*>& v)
 {
        bool changed = false;
 
-       for (vector<AudioRegionView*>::iterator i = v.begin(); i != v.end(); ++i) {
-               if (find (audio_regions.begin(), audio_regions.end(), (*i)) == audio_regions.end()) {
-                       audio_regions.add ((*i));
+       for (vector<RegionView*>::iterator i = v.begin(); i != v.end(); ++i) {
+               if (find (regions.begin(), regions.end(), (*i)) == regions.end()) {
+                       regions.add ((*i));
                        changed = true;
                }
        }
@@ -381,9 +381,9 @@ Selection::add (AutomationList* ac)
 }
 
 void
-Selection::remove (Redirect* r)
+Selection::remove (boost::shared_ptr<Redirect> r)
 {
-       list<Redirect*>::iterator i;
+       RedirectSelection::iterator i;
        if ((i = find (redirects.begin(), redirects.end(), r)) != redirects.end()) {
                redirects.erase (i);
                RedirectsChanged ();
@@ -451,9 +451,9 @@ Selection::remove (const list<Playlist*>& pllist)
 }
 
 void
-Selection::remove (AudioRegionView* r)
+Selection::remove (RegionView* r)
 {
-       audio_regions.remove (r);
+       regions.remove (r);
        RegionsChanged ();
 }
 
@@ -491,7 +491,7 @@ Selection::remove (AutomationList *ac)
 }
 
 void
-Selection::set (Redirect *r)
+Selection::set (boost::shared_ptr<Redirect> r)
 {
        clear_redirects ();
        add (r);
@@ -526,17 +526,16 @@ Selection::set (const list<Playlist*>& pllist)
 }
 
 void
-Selection::set (AudioRegionView* r)
+Selection::set (RegionView* r)
 {
-       clear_audio_regions ();
+       clear_regions ();
        add (r);
 }
 
 void
-Selection::set (vector<AudioRegionView*>& v)
+Selection::set (vector<RegionView*>& v)
 {
-
-       clear_audio_regions ();
+       clear_regions ();
        // make sure to deselect any automation selections
        clear_points();
        add (v);
@@ -590,15 +589,15 @@ Selection::selected (TimeAxisView* tv)
 }
 
 bool
-Selection::selected (AudioRegionView* arv)
+Selection::selected (RegionView* rv)
 {
-       return find (audio_regions.begin(), audio_regions.end(), arv) != audio_regions.end();
+       return find (regions.begin(), regions.end(), rv) != regions.end();
 }
 
 bool
 Selection::empty ()
 {
-       return audio_regions.empty () &&
+       return regions.empty () &&
                tracks.empty () &&
                points.empty () && 
                playlists.empty () && 
@@ -612,7 +611,7 @@ Selection::empty ()
 void
 Selection::set (list<Selectable*>& selectables)
 {
-       clear_audio_regions();
+       clear_regions();
        clear_points ();
        add (selectables);
 }
@@ -620,14 +619,14 @@ Selection::set (list<Selectable*>& selectables)
 void
 Selection::add (list<Selectable*>& selectables)
 {
-       AudioRegionView* arv;
+       RegionView* rv;
        AutomationSelectable* as;
-       vector<AudioRegionView*> arvs;
+       vector<RegionView*> rvs;
        vector<AutomationSelectable*> autos;
 
        for (std::list<Selectable*>::iterator i = selectables.begin(); i != selectables.end(); ++i) {
-               if ((arv = dynamic_cast<AudioRegionView*> (*i)) != 0) {
-                       arvs.push_back (arv);
+               if ((rv = dynamic_cast<RegionView*> (*i)) != 0) {
+                       rvs.push_back (rv);
                } else if ((as = dynamic_cast<AutomationSelectable*> (*i)) != 0) {
                        autos.push_back (as);
                } else {
@@ -638,8 +637,8 @@ Selection::add (list<Selectable*>& selectables)
                }
        }
 
-       if (!arvs.empty()) {
-               add (arvs);
+       if (!rvs.empty()) {
+               add (rvs);
        } 
 
        if (!autos.empty()) {
index ebeda1aea72b839f15051a30296d5543909d9801..7b503a5e63ef0f0dca17c583e8011cf5cac5d2d6 100644 (file)
@@ -22,6 +22,7 @@
 #define __ardour_gtk_selection_h__
 
 #include <vector>
+#include <boost/shared_ptr.hpp>
 
 #include <sigc++/signal.h>
 
@@ -34,7 +35,7 @@
 #include "point_selection.h"
 
 class TimeAxisView;
-class AudioRegionView;
+class RegionView;
 class Selectable;
 
 namespace ARDOUR {
@@ -60,7 +61,7 @@ class Selection : public sigc::trackable
        };
 
        TrackSelection       tracks;
-       AudioRegionSelection audio_regions;
+       RegionSelection      regions;
        TimeSelection        time;
        AutomationSelection  lines;
        PlaylistSelection    playlists;
@@ -88,55 +89,55 @@ class Selection : public sigc::trackable
        void dump_region_layers();
 
        bool selected (TimeAxisView*);
-       bool selected (AudioRegionView*);
+       bool selected (RegionView*);
 
        void set (list<Selectable*>&);
        void add (list<Selectable*>&);
        
        void set (TimeAxisView*);
        void set (const list<TimeAxisView*>&);
-       void set (AudioRegionView*);
-       void set (std::vector<AudioRegionView*>&);
+       void set (RegionView*);
+       void set (std::vector<RegionView*>&);
        long set (TimeAxisView*, jack_nframes_t, jack_nframes_t);
        void set (ARDOUR::AutomationList*);
        void set (ARDOUR::Playlist*);
        void set (const list<ARDOUR::Playlist*>&);
-       void set (ARDOUR::Redirect*);
+       void set (boost::shared_ptr<ARDOUR::Redirect>);
        void set (AutomationSelectable*);
 
        void toggle (TimeAxisView*);
        void toggle (const list<TimeAxisView*>&);
-       void toggle (AudioRegionView*);
-       void toggle (std::vector<AudioRegionView*>&);
+       void toggle (RegionView*);
+       void toggle (std::vector<RegionView*>&);
        long toggle (jack_nframes_t, jack_nframes_t);
        void toggle (ARDOUR::AutomationList*);
        void toggle (ARDOUR::Playlist*);
        void toggle (const list<ARDOUR::Playlist*>&);
-       void toggle (ARDOUR::Redirect*);
+       void toggle (boost::shared_ptr<ARDOUR::Redirect>);
 
        void add (TimeAxisView*);
        void add (const list<TimeAxisView*>&);
-       void add (AudioRegionView*);
-       void add (std::vector<AudioRegionView*>&);
+       void add (RegionView*);
+       void add (std::vector<RegionView*>&);
        long add (jack_nframes_t, jack_nframes_t);
        void add (ARDOUR::AutomationList*);
        void add (ARDOUR::Playlist*);
        void add (const list<ARDOUR::Playlist*>&);
-       void add (ARDOUR::Redirect*);
+       void add (boost::shared_ptr<ARDOUR::Redirect>);
        
        void remove (TimeAxisView*);
        void remove (const list<TimeAxisView*>&);
-       void remove (AudioRegionView*);
+       void remove (RegionView*);
        void remove (uint32_t selection_id);
        void remove (jack_nframes_t, jack_nframes_t);
        void remove (ARDOUR::AutomationList*);
        void remove (ARDOUR::Playlist*);
        void remove (const list<ARDOUR::Playlist*>&);
-       void remove (ARDOUR::Redirect*);
+       void remove (boost::shared_ptr<ARDOUR::Redirect>);
 
        void replace (uint32_t time_index, jack_nframes_t start, jack_nframes_t end);
        
-       void clear_audio_regions();
+       void clear_regions();
        void clear_tracks ();
        void clear_time();
        void clear_lines ();
@@ -144,10 +145,8 @@ class Selection : public sigc::trackable
        void clear_redirects ();
        void clear_points ();
 
-       void foreach_audio_region (void (ARDOUR::AudioRegion::*method)(void));
-       void foreach_audio_region (void (ARDOUR::Region::*method)(void));
-       template<class A> void foreach_audio_region (void (ARDOUR::AudioRegion::*method)(A), A arg);
-       template<class A> void foreach_audio_region (void (ARDOUR::Region::*method)(A), A arg);
+       void foreach_region (void (ARDOUR::Region::*method)(void));
+       template<class A> void foreach_region (void (ARDOUR::Region::*method)(A), A arg);
 
   private:
        uint32_t next_time_id;
index c2ca70b526583e5bd4d34df15497e31c27d4d72a..9511db7d618b0d840c8e3d75399cca5178f445c8 100644 (file)
 */
 
 #include <ardour/region.h>
-#include <ardour/audioregion.h>
 
 #include "selection.h"
+#include "region_view.h"
 
 inline void
-Selection::foreach_audio_region (void (ARDOUR::AudioRegion::*method)(void)) {
-       for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
-               ((*i)->region.*(method))();
-       }
-}
-
-inline void
-Selection::foreach_audio_region (void (ARDOUR::Region::*method)(void)) {
-       for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
-               ((*i)->region.*(method))();
-       }
-}
-
-template<class A> inline void 
-Selection::foreach_audio_region (void (ARDOUR::AudioRegion::*method)(A), A arg) {
-       for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
-               ((*i)->region.*(method))(arg);
+Selection::foreach_region (void (ARDOUR::Region::*method)(void)) {
+       for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
+               ((*i)->region().*(method))();
        }
 }
 
 template<class A> inline void 
-Selection::foreach_audio_region (void (ARDOUR::Region::*method)(A), A arg) {
-       for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
-               ((*i)->region.*(method))(arg);
+Selection::foreach_region (void (ARDOUR::Region::*method)(A), A arg) {
+       for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
+               ((*i)->region().*(method))(arg);
        }
 }
 
@@ -64,14 +50,14 @@ Selection::foreach_audio_region (void (ARDOUR::Region::*method)(A), A arg) {
 template<class A> inline void 
 Selection::foreach_route (void (ARDOUR::Route::*method)(A), A arg) {
        for (list<ARDOUR::Route*>::iterator i = routes.begin(); i != routes.end(); ++i) {
-               ((*i)->region.*(method))(arg);
+               ((*i)->region().*(method))(arg);
        }
 }
 
 template<class A1, class A2> inline void 
 Selection::foreach_route (void (ARDOUR::Route::*method)(A1,A2), A1 arg1, A2 arg2) {
        for (list<ARDOUR::Route*>::iterator i = routes.begin(); i != routes.end(); ++i) {
-               ((*i)->region.*(method))(arg1, arg2);
+               ((*i)->region().*(method))(arg1, arg2);
        }
 }
 
index be95f753e74b134edaf1c5a3167d3e460fd3387c..9925ff51d4331caf405f79a8ab3cf2d751d445dd 100644 (file)
@@ -30,7 +30,7 @@
 using namespace ARDOUR;
 using namespace PBD;
 
-SendUI::SendUI (Send& s, Session& se)
+SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
        : _send (s),
          _session (se),
          gpm (s, se),
@@ -53,10 +53,10 @@ SendUI::SendUI (Send& s, Session& se)
 
        show_all ();
 
-       _send.set_metering (true);
+       _send->set_metering (true);
 
-       _send.output_changed.connect (mem_fun (*this, &SendUI::ins_changed));
-       _send.output_changed.connect (mem_fun (*this, &SendUI::outs_changed));
+       _send->output_changed.connect (mem_fun (*this, &SendUI::ins_changed));
+       _send->output_changed.connect (mem_fun (*this, &SendUI::outs_changed));
        
        panners.set_width (Wide);
        panners.setup_pan ();
@@ -70,7 +70,7 @@ SendUI::SendUI (Send& s, Session& se)
 
 SendUI::~SendUI ()
 {
-       _send.set_metering (false);
+       _send->set_metering (false);
        
        /* XXX not clear that we need to do this */
 
@@ -118,7 +118,7 @@ SendUI::fast_update ()
        }
 }
        
-SendUIWindow::SendUIWindow (Send& s, Session& ss)
+SendUIWindow::SendUIWindow (boost::shared_ptr<Send> s, Session& ss)
 {
        ui = new SendUI (s, ss);
 
@@ -131,7 +131,7 @@ SendUIWindow::SendUIWindow (Send& s, Session& ss)
        add (vpacker);
        set_name ("SendUIWindow");
 
-       s.GoingAway.connect (mem_fun (*this, &SendUIWindow::send_going_away));
+       s->GoingAway.connect (mem_fun (*this, &SendUIWindow::send_going_away));
 
        signal_delete_event().connect (bind (ptr_fun (just_hide_it), reinterpret_cast<Window *> (this)));
 
index d1a49930eae9b24f40bd4fba90944b5cb59c3b55..1d5a74e1020ca80ce7d1a3d41b9d2bad95cdf83a 100644 (file)
@@ -35,7 +35,7 @@ class IOSelector;
 class SendUI : public Gtk::HBox
 {
   public:
-       SendUI (ARDOUR::Send&, ARDOUR::Session&);
+       SendUI (boost::shared_ptr<ARDOUR::Send>, ARDOUR::Session&);
        ~SendUI();
 
        void update ();
@@ -44,7 +44,7 @@ class SendUI : public Gtk::HBox
        IOSelector* io;
 
   private:
-       ARDOUR::Send&    _send;
+       boost::shared_ptr<ARDOUR::Send> _send;
        ARDOUR::Session& _session;
        GainMeter gpm;
        PannerUI  panners;
@@ -62,7 +62,7 @@ class SendUI : public Gtk::HBox
 class SendUIWindow : public Gtk::Window
 {
   public:
-       SendUIWindow(ARDOUR::Send&, ARDOUR::Session&);
+       SendUIWindow(boost::shared_ptr<ARDOUR::Send>, ARDOUR::Session&);
        ~SendUIWindow();
 
        SendUI*     ui;
index 79546880de0644c3f04719b48ed4831bf2d69c0f..d9ded04d2b063a934e85ef6a25dfc6994c472223 100644 (file)
@@ -97,6 +97,9 @@ SoundFileBox::SoundFileBox ()
                        (mem_fun (*this, &SoundFileBox::add_field_clicked));
        remove_field_btn.signal_clicked().connect
                        (mem_fun (*this, &SoundFileBox::remove_field_clicked));
+       
+       Gtk::CellRendererText* cell(dynamic_cast<Gtk::CellRendererText*>(field_view.get_column_cell_renderer(1)));
+       cell->signal_edited().connect (mem_fun (*this, &SoundFileBox::field_edited));
 
        field_view.get_selection()->signal_changed().connect (mem_fun (*this, &SoundFileBox::field_selected));
        Library->fields_changed.connect (mem_fun (*this, &SoundFileBox::setup_fields));
@@ -259,6 +262,13 @@ SoundFileBox::remove_field_clicked ()
        Library->save_changes ();
 }
 
+void
+SoundFileBox::field_edited (const Glib::ustring& str1, const Glib::ustring& str2)
+{
+       cout << "field_edited" << endl;
+       Library->save_changes ();
+}
+
 void
 SoundFileBox::delete_row (const Gtk::TreeModel::iterator& iter)
 {
@@ -394,6 +404,9 @@ SoundFileOmega::set_mode (Editing::ImportMode mode)
        case Editing::ImportToTrack:
                split_check.set_sensitive (false);
                break;
+       case Editing::ImportAsTapeTrack:
+               split_check.set_sensitive (true);
+               break;
        }
 }
 
@@ -433,5 +446,8 @@ SoundFileOmega::mode_changed ()
        case Editing::ImportToTrack:
                split_check.set_sensitive (false);
                break;
+       case Editing::ImportAsTapeTrack:
+               split_check.set_sensitive (true);
+               break;
        }
 }
index 79c73b97ac9b5f800bbe7701e304488289f17b17..8ef57d7b9f8539bce5ab024271fa01c7756435a7 100644 (file)
@@ -100,6 +100,7 @@ class SoundFileBox : public Gtk::VBox
     void stop_btn_clicked ();
     void add_field_clicked ();
     void remove_field_clicked ();
+       void field_edited (const Glib::ustring&, const Glib::ustring&);
        void delete_row (const Gtk::TreeModel::iterator& iter);
 
     void field_selected ();
index a60e0d59e78fd9c474b49c7d19f4621052981ed4..d1d163d7a2ed746032a42f80b3ed39a180c1d4aa 100644 (file)
@@ -1,28 +1,42 @@
+/*
+    Copyright (C) 2001, 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
+    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 <cmath>
 
 #include <gtkmm.h>
 
 #include <gtkmm2ext/gtk_ui.h>
 
-#include <ardour/audioplaylist.h>
-#include <ardour/audioregion.h>
-#include <ardour/audiosource.h>
-#include <ardour/audio_diskstream.h>
-#include <ardour/audio_track.h>
-#include <ardour/playlist_templates.h>
+#include <ardour/playlist.h>
+#include <ardour/region.h>
 #include <ardour/source.h>
+#include <ardour/diskstream.h>
+#include <ardour/track.h>
 
 #include "streamview.h"
-#include "regionview.h"
-#include "taperegionview.h"
-#include "audio_time_axis.h"
+#include "region_view.h"
+#include "route_time_axis.h"
 #include "canvas-waveview.h"
 #include "canvas-simplerect.h"
 #include "region_selection.h"
 #include "selection.h"
 #include "public_editor.h"
 #include "ardour_ui.h"
-#include "crossfade_view.h"
 #include "rgb_macros.h"
 #include "gui_thread.h"
 #include "utils.h"
@@ -32,52 +46,36 @@ using namespace ARDOUR;
 using namespace PBD;
 using namespace Editing;
 
-StreamView::StreamView (AudioTimeAxisView& tv)
+StreamView::StreamView (RouteTimeAxisView& tv)
        : _trackview (tv)
+       , canvas_group(new ArdourCanvas::Group(*_trackview.canvas_display))
+       , canvas_rect(new ArdourCanvas::SimpleRect (*canvas_group))
+       , _samples_per_unit(_trackview.editor.get_current_zoom())
+       , rec_updating(false)
+       , rec_active(false)
+       , use_rec_regions(tv.editor.show_waveforms_recording())
+       , region_color(_trackview.color())
+       , stream_base_color(0xFFFFFFFF)
 {
-       region_color = _trackview.color();
-       crossfades_visible = true;
-
-       if (tv.is_audio_track()) {
-               /* TRACK */
-               //stream_base_color = RGBA_TO_UINT (222,223,218,255);
-               stream_base_color = color_map[cAudioTrackBase];
-       } else {
-               /* BUS */
-               //stream_base_color = RGBA_TO_UINT (230,226,238,255);
-               stream_base_color = color_map[cAudioBusBase];
-       }
-
        /* set_position() will position the group */
 
-       canvas_group = new ArdourCanvas::Group(*_trackview.canvas_display);
-
        canvas_rect = new ArdourCanvas::SimpleRect (*canvas_group);
        canvas_rect->property_x1() = 0.0;
        canvas_rect->property_y1() = 0.0;
        canvas_rect->property_x2() = 1000000.0;
        canvas_rect->property_y2() = (double) tv.height;
-       canvas_rect->property_outline_color_rgba() = color_map[cAudioTrackOutline];
        canvas_rect->property_outline_what() = (guint32) (0x1|0x2|0x8);  // outline ends and bottom 
-       canvas_rect->property_fill_color_rgba() = stream_base_color;
+       // (Fill/Outline colours set in derived classes)
 
        canvas_rect->signal_event().connect (bind (mem_fun (_trackview.editor, &PublicEditor::canvas_stream_view_event), canvas_rect, &_trackview));
 
-       _samples_per_unit = _trackview.editor.get_current_zoom();
-       _amplitude_above_axis = 1.0;
-
-       if (_trackview.is_audio_track()) {
-               _trackview.audio_track()->diskstream_changed.connect (mem_fun (*this, &StreamView::diskstream_changed));
+       if (_trackview.is_track()) {
+               _trackview.track()->DiskstreamChanged.connect (mem_fun (*this, &StreamView::diskstream_changed));
                _trackview.session().TransportStateChange.connect (mem_fun (*this, &StreamView::transport_changed));
-               _trackview.get_diskstream()->record_enable_changed.connect (mem_fun (*this, &StreamView::rec_enable_changed));
+               _trackview.get_diskstream()->RecordEnableChanged.connect (mem_fun (*this, &StreamView::rec_enable_changed));
                _trackview.session().RecordStateChanged.connect (mem_fun (*this, &StreamView::sess_rec_enable_changed));
        } 
 
-       rec_updating = false;
-       rec_active = false;
-       use_rec_regions = tv.editor.show_waveforms_recording ();
-       last_rec_peak_frame = 0;
-
        ColorChanged.connect (mem_fun (*this, &StreamView::color_handler));
 }
 
@@ -90,7 +88,7 @@ StreamView::~StreamView ()
 void
 StreamView::attach ()
 {
-       if (_trackview.is_audio_track()) {
+       if (_trackview.is_track()) {
                display_diskstream (_trackview.get_diskstream());
        }
 }
@@ -115,13 +113,13 @@ StreamView::set_height (gdouble h)
 
        canvas_rect->property_y2() = h;
 
-       for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+       for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
                (*i)->set_height (h);
        }
 
-       for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+       /*for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
                (*i)->set_height (h);
-       }
+       }*/
 
        for (vector<RecBoxInfo>::iterator i = rec_rects.begin(); i != rec_rects.end(); ++i) {
                RecBoxInfo &recbox = (*i);
@@ -134,7 +132,7 @@ StreamView::set_height (gdouble h)
 int 
 StreamView::set_samples_per_unit (gdouble spp)
 {
-       AudioRegionViewList::iterator i;
+       RegionViewList::iterator i;
 
        if (spp < 1.0) {
                return -1;
@@ -146,10 +144,6 @@ StreamView::set_samples_per_unit (gdouble spp)
                (*i)->set_samples_per_unit (spp);
        }
 
-       for (CrossfadeViewList::iterator xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) {
-               (*xi)->set_samples_per_unit (spp);
-       }
-
        for (vector<RecBoxInfo>::iterator xi = rec_rects.begin(); xi != rec_rects.end(); ++xi) {
                RecBoxInfo &recbox = (*xi);
                
@@ -163,113 +157,24 @@ StreamView::set_samples_per_unit (gdouble spp)
        return 0;
 }
 
-int 
-StreamView::set_amplitude_above_axis (gdouble app)
-
-{
-       AudioRegionViewList::iterator i;
-
-       if (app < 1.0) {
-               return -1;
-       }
-
-       _amplitude_above_axis = app;
-
-       for (i = region_views.begin(); i != region_views.end(); ++i) {
-               (*i)->set_amplitude_above_axis (app);
-       }
-
-       return 0;
-}
-
 void
 StreamView::add_region_view (Region *r)
 {
        add_region_view_internal (r, true);
 }
 
-void
-StreamView::add_region_view_internal (Region *r, bool wait_for_waves)
-{
-       ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::add_region_view), r));
-
-       AudioRegion* region = dynamic_cast<AudioRegion*> (r);
-
-       if (region == 0) {
-               return;
-       }
-
-       AudioRegionView *region_view;
-       list<AudioRegionView *>::iterator i;
-
-       for (i = region_views.begin(); i != region_views.end(); ++i) {
-               if (&(*i)->region == region) {
-                       
-                       /* great. we already have a AudioRegionView for this Region. use it again.
-                        */
-
-                       (*i)->set_valid (true);
-                       return;
-               }
-       }
-       
-       switch (_trackview.audio_track()->mode()) {
-       case Normal:
-               region_view = new AudioRegionView (canvas_group, _trackview, *region, 
-                                                  _samples_per_unit, region_color);
-               break;
-       case Destructive:
-               region_view = new TapeAudioRegionView (canvas_group, _trackview, *region, 
-                                                      _samples_per_unit, region_color);
-               break;
-       }
-
-       region_view->init (_amplitude_above_axis, region_color, wait_for_waves);
-       region_views.push_front (region_view);
-       
-       /* follow global waveform setting */
-
-       region_view->set_waveform_visible(_trackview.editor.show_waveforms());
-
-       /* catch regionview going away */
-
-       region->GoingAway.connect (mem_fun (*this, &StreamView::remove_region_view));
-       
-       AudioRegionViewAdded (region_view);
-}
-
 void
 StreamView::remove_region_view (Region *r)
 {
        ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::remove_region_view), r));
 
-       AudioRegion* ar = dynamic_cast<AudioRegion*> (r);
-
-       if (ar == 0) {
-               return;
-       }
-
-       for (list<AudioRegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
-               if (&((*i)->region) == ar) {
+       for (list<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+               if (&((*i)->region()) == r) {
                        delete *i;
                        region_views.erase (i);
                        break;
                }
        }
-
-       for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end();) {
-               list<CrossfadeView*>::iterator tmp;
-               
-               tmp = i;
-               ++tmp;
-               
-               if ((*i)->crossfade.involves (*ar)) {
-                       delete *i;
-                       crossfade_views.erase (i);
-               }
-               
-               i = tmp;
-       }
 }
 
 void
@@ -282,14 +187,8 @@ StreamView::remove_rec_region (Region *r)
                /*NOTREACHED*/
        } 
 
-       AudioRegion* ar = dynamic_cast<AudioRegion*> (r);
-
-       if (ar == 0) {
-               return;
-       }
-
-       for (list<AudioRegion *>::iterator i = rec_regions.begin(); i != rec_regions.end(); ++i) {
-               if (*i == ar) {
+       for (list<Region *>::iterator i = rec_regions.begin(); i != rec_regions.end(); ++i) {
+               if (*i == r) {
                        rec_regions.erase (i);
                        break;
                }
@@ -299,21 +198,15 @@ StreamView::remove_rec_region (Region *r)
 void
 StreamView::undisplay_diskstream ()
 {
-       
-       for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
-               delete *i;
-       }
-
-       for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+       for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
                delete *i;
        }
 
        region_views.clear();
-       crossfade_views.clear ();
 }
 
 void
-StreamView::display_diskstream (AudioDiskstream *ds)
+StreamView::display_diskstream (Diskstream *ds)
 {
        playlist_change_connection.disconnect();
        playlist_changed (ds);
@@ -325,21 +218,13 @@ StreamView::playlist_modified ()
 {
        ENSURE_GUI_THREAD (mem_fun (*this, &StreamView::playlist_modified));
 
-       /* if the playlist is modified, make sure xfades are on top and all the regionviews are stacked 
-          correctly.
-       */
-
-       for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+       for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
                region_layered (*i);
        }
-
-       for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
-               (*i)->get_canvas_group()->raise_to_top();
-       }
 }
 
 void
-StreamView::playlist_changed (AudioDiskstream *ds)
+StreamView::playlist_changed (Diskstream *ds)
 {
        ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::playlist_changed), ds));
 
@@ -362,69 +247,6 @@ StreamView::playlist_changed (AudioDiskstream *ds)
        playlist_connections.push_back (ds->playlist()->RegionRemoved.connect (mem_fun (*this, &StreamView::remove_region_view)));
        playlist_connections.push_back (ds->playlist()->StateChanged.connect (mem_fun (*this, &StreamView::playlist_state_changed)));
        playlist_connections.push_back (ds->playlist()->Modified.connect (mem_fun (*this, &StreamView::playlist_modified)));
-       playlist_connections.push_back (ds->playlist()->NewCrossfade.connect (mem_fun (*this, &StreamView::add_crossfade)));
-}
-
-void
-StreamView::add_crossfade (Crossfade *crossfade)
-{
-       AudioRegionView* lview = 0;
-       AudioRegionView* rview = 0;
-
-       ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::add_crossfade), crossfade));
-
-       /* first see if we already have a CrossfadeView for this Crossfade */
-
-       for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
-               if (&(*i)->crossfade == crossfade) {
-                       if (!crossfades_visible) {
-                               (*i)->hide();
-                       } else {
-                               (*i)->show ();
-                       }
-                       (*i)->set_valid (true);
-                       return;
-               }
-       }
-
-       /* create a new one */
-
-       for (list<AudioRegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
-               if (!lview && &((*i)->region) == &crossfade->out()) {
-                       lview = *i;
-               }
-               if (!rview && &((*i)->region) == &crossfade->in()) {
-                       rview = *i;
-               }
-       }
-
-       CrossfadeView *cv = new CrossfadeView (_trackview.canvas_display,
-                                              _trackview,
-                                              *crossfade,
-                                              _samples_per_unit,
-                                              region_color,
-                                              *lview, *rview);
-
-       crossfade->Invalidated.connect (mem_fun (*this, &StreamView::remove_crossfade));
-       crossfade_views.push_back (cv);
-
-       if (!crossfades_visible) {
-               cv->hide ();
-       }
-}
-
-void
-StreamView::remove_crossfade (Crossfade *xfade)
-{
-       ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::remove_crossfade), xfade));
-
-       for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
-               if (&(*i)->crossfade == xfade) {
-                       delete *i;
-                       crossfade_views.erase (i);
-                       break;
-               }
-       }
 }
 
 void
@@ -436,64 +258,12 @@ StreamView::playlist_state_changed (Change ignored)
 }
 
 void
-StreamView::redisplay_diskstream ()
-{
-       list<AudioRegionView *>::iterator i, tmp;
-       list<CrossfadeView*>::iterator xi, tmpx;
-
-       
-       for (i = region_views.begin(); i != region_views.end(); ++i) {
-               (*i)->set_valid (false);
-       }
-
-       for (xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) {
-               (*xi)->set_valid (false);
-               if ((*xi)->visible()) {
-                       (*xi)->show ();
-               }
-       }
-
-       if (_trackview.is_audio_track()) {
-               _trackview.get_diskstream()->playlist()->foreach_region (this, &StreamView::add_region_view);
-               _trackview.get_diskstream()->playlist()->foreach_crossfade (this, &StreamView::add_crossfade);
-       }
-
-       for (i = region_views.begin(); i != region_views.end(); ) {
-               tmp = i;
-               tmp++;
-
-               if (!(*i)->is_valid()) {
-                       delete *i;
-                       region_views.erase (i);
-               } 
-
-               i = tmp;
-       }
-
-       for (xi = crossfade_views.begin(); xi != crossfade_views.end();) {
-               tmpx = xi;
-               tmpx++;
-
-               if (!(*xi)->valid()) {
-                       delete *xi;
-                       crossfade_views.erase (xi);
-               }
-
-               xi = tmpx;
-       }
-
-       /* now fix layering */
-
-       playlist_modified ();
-}
-
-void
-StreamView::diskstream_changed (void *src_ignored)
+StreamView::diskstream_changed ()
 {
-       AudioTrack *at;
+       Track *t;
 
-       if ((at = _trackview.audio_track()) != 0) {
-               AudioDiskstream& ds = at->disk_stream();
+       if ((t = _trackview.track()) != 0) {
+               Diskstream& ds = t->diskstream();
                /* XXX grrr: when will SigC++ allow me to bind references? */
                Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*this, &StreamView::display_diskstream), &ds));
        } else {
@@ -505,7 +275,7 @@ void
 StreamView::apply_color (Gdk::Color& color, ColorTarget target)
 
 {
-       list<AudioRegionView *>::iterator i;
+       list<RegionView *>::iterator i;
 
        switch (target) {
        case RegionColor:
@@ -513,76 +283,18 @@ StreamView::apply_color (Gdk::Color& color, ColorTarget target)
                for (i = region_views.begin(); i != region_views.end(); ++i) {
                        (*i)->set_color (region_color);
                }
-               // stream_base_color = RGBA_TO_UINT (color.red/256, color.green/256, color.blue/256, 255);
-               // gnome_canvas_item_set (canvas_rect, "fill_color_rgba", stream_base_color, NULL);
                break;
                
        case StreamBaseColor:
-               // stream_base_color = RGBA_TO_UINT (color.red/256, color.green/256, color.blue/256, 255);
-               // gnome_canvas_item_set (canvas_rect, "fill_color_rgba", stream_base_color, NULL);
+               stream_base_color = RGBA_TO_UINT (
+                       color.get_red_p(), color.get_green_p(), color.get_blue_p(), 255);
+               canvas_rect->property_fill_color_rgba() = stream_base_color;
                break;
        }
 }
 
 void
-StreamView::set_show_waveforms (bool yn)
-{
-       for (list<AudioRegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
-                       (*i)->set_waveform_visible (yn);
-       }
-}
-
-void
-StreamView::set_selected_regionviews (AudioRegionSelection& regions)
-{
-       bool selected;
-
-       // cerr << _trackview.name() << " (selected = " << regions.size() << ")" << endl;
-       for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
-               
-               selected = false;
-               
-               for (AudioRegionSelection::iterator ii = regions.begin(); ii != regions.end(); ++ii) {
-                       if (*i == *ii) {
-                               selected = true;
-                       }
-               }
-               
-               // cerr << "\tregion " << (*i)->region.name() << " selected = " << selected << endl;
-               (*i)->set_selected (selected);
-       }
-}
-
-void
-StreamView::get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable*>& results)
-{
-       for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
-               if ((*i)->region.coverage(start, end) != OverlapNone) {
-                       results.push_back (*i);
-               }
-       }
-}
-
-void
-StreamView::get_inverted_selectables (Selection& sel, list<Selectable*>& results)
-{
-       for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
-               if (!sel.audio_regions.contains (*i)) {
-                       results.push_back (*i);
-               }
-       }
-}
-
-void
-StreamView::set_waveform_shape (WaveformShape shape)
-{
-       for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
-               (*i)->set_waveform_shape (shape);
-       }
-}              
-               
-void
-StreamView::region_layered (AudioRegionView* rv)
+StreamView::region_layered (RegionView* rv)
 {
        rv->get_canvas_group()->lower_to_bottom();
 
@@ -590,11 +302,14 @@ StreamView::region_layered (AudioRegionView* rv)
           get events - the  parent group does instead ...
        */
        
-       rv->get_canvas_group()->raise (rv->region.layer() + 1);
+       /* this used to be + 1, but regions to the left ended up below
+         ..something.. and couldn't receive events.  why?  good question.
+       */
+       rv->get_canvas_group()->raise (rv->region().layer() + 2);
 }
 
 void
-StreamView::rec_enable_changed (void *src)
+StreamView::rec_enable_changed ()
 {
        Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::setup_rec_box));
 }
@@ -611,161 +326,6 @@ StreamView::transport_changed()
        Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::setup_rec_box));
 }
 
-void
-StreamView::setup_rec_box ()
-{
-       // cerr << _trackview.name() << " streamview SRB\n";
-
-       if (_trackview.session().transport_rolling()) {
-
-               // cerr << "\trolling\n";
-
-               if (!rec_active && 
-                   _trackview.session().record_status() == Session::Recording && 
-                   _trackview.get_diskstream()->record_enabled()) {
-
-                       if (_trackview.audio_track()->mode() == Normal && use_rec_regions && rec_regions.size() == rec_rects.size()) {
-
-                               /* add a new region, but don't bother if they set use_rec_regions mid-record */
-
-                               AudioRegion::SourceList sources;
-
-                               for (list<sigc::connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) {
-                                       (*prc).disconnect();
-                               }
-                               peak_ready_connections.clear();
-                                       
-                               for (uint32_t n=0; n < _trackview.get_diskstream()->n_channels(); ++n) {
-                                       AudioSource *src = (AudioSource *) _trackview.get_diskstream()->write_source (n);
-                                       if (src) {
-                                               sources.push_back (src);
-                                               peak_ready_connections.push_back (src->PeakRangeReady.connect (bind (mem_fun (*this, &StreamView::rec_peak_range_ready), src))); 
-                                       }
-                               }
-
-                               // handle multi
-                               
-                               jack_nframes_t start = 0;
-                               if (rec_regions.size() > 0) {
-                                       start = rec_regions.back()->start() + _trackview.get_diskstream()->get_captured_frames(rec_regions.size()-1);
-                               }
-                               
-                               AudioRegion * region = new AudioRegion(sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false);
-                               region->set_position (_trackview.session().transport_frame(), this);
-                               rec_regions.push_back (region);
-                               /* catch it if it goes away */
-                               region->GoingAway.connect (mem_fun (*this, &StreamView::remove_rec_region));
-
-                               /* we add the region later */
-                       }
-                       
-                       /* start a new rec box */
-
-                       AudioTrack* at;
-
-                       at = _trackview.audio_track(); /* we know what it is already */
-                       AudioDiskstream& ds = at->disk_stream();
-                       jack_nframes_t frame_pos = ds.current_capture_start ();
-                       gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos);
-                       gdouble xend;
-                       uint32_t fill_color;
-
-                       switch (_trackview.audio_track()->mode()) {
-                       case Normal:
-                               xend = xstart;
-                               fill_color = color_map[cRecordingRectFill];
-                               break;
-
-                       case Destructive:
-                               xend = xstart + 2;
-                               fill_color = color_map[cRecordingRectFill];
-                               /* make the recording rect translucent to allow
-                                  the user to see the peak data coming in, etc.
-                               */
-                               fill_color = UINT_RGBA_CHANGE_A (fill_color, 120);
-                               break;
-                       }
-                       
-                       ArdourCanvas::SimpleRect * rec_rect = new Gnome::Canvas::SimpleRect (*canvas_group);
-                       rec_rect->property_x1() = xstart;
-                       rec_rect->property_y1() = 1.0;
-                       rec_rect->property_x2() = xend;
-                       rec_rect->property_y2() = (double) _trackview.height - 1;
-                       rec_rect->property_outline_color_rgba() = color_map[cRecordingRectOutline];
-                       rec_rect->property_fill_color_rgba() = fill_color;
-                       
-                       RecBoxInfo recbox;
-                       recbox.rectangle = rec_rect;
-                       recbox.start = _trackview.session().transport_frame();
-                       recbox.length = 0;
-                       
-                       rec_rects.push_back (recbox);
-                       
-                       screen_update_connection.disconnect();
-                       screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &StreamView::update_rec_box));        
-                       rec_updating = true;
-                       rec_active = true;
-
-               } else if (rec_active &&
-                          (_trackview.session().record_status() != Session::Recording ||
-                           !_trackview.get_diskstream()->record_enabled())) {
-
-                       screen_update_connection.disconnect();
-                       rec_active = false;
-                       rec_updating = false;
-
-               }
-               
-       } else {
-
-               // cerr << "\tNOT rolling, rec_rects = " << rec_rects.size() << " rec_regions = " << rec_regions.size() << endl;
-
-               if (!rec_rects.empty() || !rec_regions.empty()) {
-
-                       /* disconnect rapid update */
-                       screen_update_connection.disconnect();
-
-                       for (list<sigc::connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) {
-                               (*prc).disconnect();
-                       }
-                       peak_ready_connections.clear();
-
-                       rec_updating = false;
-                       rec_active = false;
-                       last_rec_peak_frame = 0;
-                       
-                       /* remove temp regions */
-                       for (list<AudioRegion*>::iterator iter=rec_regions.begin(); iter != rec_regions.end(); )
-                       {
-                               list<AudioRegion*>::iterator tmp;
-
-                               tmp = iter;
-                               ++tmp;
-
-                               /* this will trigger the remove_region_view */
-                               delete *iter;
-
-                               iter = tmp;
-                       }
-                       
-                       rec_regions.clear();
-
-                       // cerr << "\tclear " << rec_rects.size() << " rec rects\n";
-               
-
-                       /* transport stopped, clear boxes */
-                       for (vector<RecBoxInfo>::iterator iter=rec_rects.begin(); iter != rec_rects.end(); ++iter) {
-                               RecBoxInfo &rect = (*iter);
-                               delete rect.rectangle;
-                       }
-                       
-                       rec_rects.clear();
-                       
-               }
-       }
-}
-
-
 void
 StreamView::update_rec_box ()
 {
@@ -776,7 +336,7 @@ StreamView::update_rec_box ()
                double xstart;
                double xend;
                
-               switch (_trackview.audio_track()->mode()) {
+               switch (_trackview.track()->mode()) {
                case Normal:
                        rect.length = at - rect.start;
                        xstart = _trackview.editor.frame_to_pixel (rect.start);
@@ -795,12 +355,12 @@ StreamView::update_rec_box ()
        }
 }
        
-AudioRegionView*
-StreamView::find_view (const AudioRegion& region)
+RegionView*
+StreamView::find_view (const Region& region)
 {
-       for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+       for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
 
-               if (&(*i)->region == &region) {
+               if (&(*i)->region() == &region) {
                        return *i;
                }
        }
@@ -808,172 +368,51 @@ StreamView::find_view (const AudioRegion& region)
 }
        
 void
-StreamView::foreach_regionview (sigc::slot<void,AudioRegionView*> slot)
+StreamView::foreach_regionview (sigc::slot<void,RegionView*> slot)
 {
-       for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+       for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
                slot (*i);
        }
 }
 
 void
-StreamView::foreach_crossfadeview (void (CrossfadeView::*pmf)(void))
-{
-       for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
-               ((*i)->*pmf) ();
-       }
-}
-
-void
-StreamView::rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, Source * src)
-{
-       // this is called from the peak building thread
-
-       ENSURE_GUI_THREAD(bind (mem_fun (*this, &StreamView::rec_peak_range_ready), start, cnt, src));
-       
-       if (rec_peak_ready_map.size() == 0 || start+cnt > last_rec_peak_frame) {
-               last_rec_peak_frame = start + cnt;
-       }
-
-       rec_peak_ready_map[src] = true;
-
-       if (rec_peak_ready_map.size() == _trackview.get_diskstream()->n_channels()) {
-               this->update_rec_regions ();
-               rec_peak_ready_map.clear();
-       }
-}
-
-void
-StreamView::update_rec_regions ()
+StreamView::set_selected_regionviews (RegionSelection& regions)
 {
-       if (use_rec_regions) {
-
-               uint32_t n = 0;
-
-               for (list<AudioRegion*>::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) {
-
-                       list<AudioRegion*>::iterator tmp;
-
-                       tmp = iter;
-                       ++tmp;
-
-                       if (!canvas_item_visible (rec_rects[n].rectangle)) {
-                               /* rect already hidden, this region is done */
-                               iter = tmp;
-                               continue;
-                       }
-                       
-                       AudioRegion * region = (*iter);
-                       jack_nframes_t origlen = region->length();
-
-                       if (region == rec_regions.back() && rec_active) {
-
-                               if (last_rec_peak_frame > region->start()) {
-
-                                       jack_nframes_t nlen = last_rec_peak_frame - region->start();
-
-                                       if (nlen != region->length()) {
-
-                                               region->freeze ();
-                                               region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
-                                               region->set_length (nlen, this);
-                                               region->thaw ("updated");
-
-                                               if (origlen == 1) {
-                                                       /* our special initial length */
-                                                       add_region_view_internal (region, false);
-                                               }
-
-                                               /* also update rect */
-                                               ArdourCanvas::SimpleRect * rect = rec_rects[n].rectangle;
-                                               gdouble xend = _trackview.editor.frame_to_pixel (region->position() + region->length());
-                                               rect->property_x2() = xend;
-                                       }
-                               }
-
-                       } else {
-
-                               jack_nframes_t nlen = _trackview.get_diskstream()->get_captured_frames(n);
-
-                               if (nlen != region->length()) {
-
-                                       if (region->source(0).length() >= region->start() + nlen) {
-
-                                               region->freeze ();
-                                               region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
-                                               region->set_length (nlen, this);
-                                               region->thaw ("updated");
-                                               
-                                               if (origlen == 1) {
-                                                       /* our special initial length */
-                                                       add_region_view_internal (region, false);
-                                               }
-                                               
-                                               /* also hide rect */
-                                               ArdourCanvas::Item * rect = rec_rects[n].rectangle;
-                                               rect->hide();
+       bool selected;
 
-                                       }
-                               }
+       // cerr << _trackview.name() << " (selected = " << regions.size() << ")" << endl;
+       for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+               
+               selected = false;
+               
+               for (RegionSelection::iterator ii = regions.begin(); ii != regions.end(); ++ii) {
+                       if (*i == *ii) {
+                               selected = true;
                        }
-
-                       iter = tmp;
                }
+               
+               // cerr << "\tregion " << (*i)->region().name() << " selected = " << selected << endl;
+               (*i)->set_selected (selected);
        }
 }
 
 void
-StreamView::show_all_xfades ()
-{
-       foreach_crossfadeview (&CrossfadeView::show);
-       crossfades_visible = true;
-}
-
-void
-StreamView::hide_all_xfades ()
-{
-       foreach_crossfadeview (&CrossfadeView::hide);
-       crossfades_visible = false;
-}
-
-void
-StreamView::hide_xfades_involving (AudioRegionView& rv)
+StreamView::get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable*>& results)
 {
-       for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
-               if ((*i)->crossfade.involves (rv.region)) {
-                       (*i)->fake_hide ();
+       for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+               if ((*i)->region().coverage(start, end) != OverlapNone) {
+                       results.push_back (*i);
                }
        }
 }
 
 void
-StreamView::reveal_xfades_involving (AudioRegionView& rv)
+StreamView::get_inverted_selectables (Selection& sel, list<Selectable*>& results)
 {
-       for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
-               if ((*i)->crossfade.involves (rv.region) && (*i)->visible()) {
-                       (*i)->show ();
+       for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+               if (!sel.regions.contains (*i)) {
+                       results.push_back (*i);
                }
        }
 }
 
-void
-StreamView::color_handler (ColorID id, uint32_t val)
-{
-       switch (id) {
-       case cAudioTrackBase:
-               if (_trackview.is_audio_track()) {
-                       canvas_rect->property_fill_color_rgba() = val;
-               } 
-               break;
-       case cAudioBusBase:
-               if (!_trackview.is_audio_track()) {
-                       canvas_rect->property_fill_color_rgba() = val;
-               }
-               break;
-       case cAudioTrackOutline:
-               canvas_rect->property_outline_color_rgba() = val;
-               break;
-
-       default:
-               break;
-       }
-}
index 00ec2d93f2a8a13b52a52fd10f935b805caaf87f..5a0e10974f9a8c3f472c9123629c24ca403aad99 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2001 Paul Davis 
+    Copyright (C) 2001, 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
@@ -14,8 +14,6 @@
     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$
 */
 
 #ifndef __ardour_streamview_h__
@@ -37,141 +35,116 @@ namespace Gdk {
 
 namespace ARDOUR {
        class Route;
-       class AudioDiskstream;
+       class Diskstream;
        class Crossfade;
        class PeakData;
-       class AudioRegion;
+       class Region;
        class Source;
 }
 
 struct RecBoxInfo {
-        ArdourCanvas::SimpleRect* rectangle;
-       jack_nframes_t start;
-       jack_nframes_t length;
+       ArdourCanvas::SimpleRect* rectangle;
+       jack_nframes_t            start;
+       jack_nframes_t            length;
 };
 
 class PublicEditor;
 class Selectable;
-class AudioTimeAxisView;
-class AudioRegionView;
-class AudioRegionSelection;
+class RouteTimeAxisView;
+class RegionView;
+class RegionSelection;
 class CrossfadeView;
 class Selection;
 
 class StreamView : public sigc::trackable
 {
-  public:
-       StreamView (AudioTimeAxisView&);
-       ~StreamView ();
+public:
+       virtual ~StreamView ();
 
-       void set_waveform_shape (WaveformShape);
+       RouteTimeAxisView& trackview() { return _trackview; }
 
-       AudioTimeAxisView& trackview() { return _trackview; }
+       void attach ();
 
        void set_zoom_all();
 
-       int set_height (gdouble);
        int set_position (gdouble x, gdouble y);
+       virtual int set_height (gdouble);
 
-       int set_samples_per_unit (gdouble spp);
-       gdouble get_samples_per_unit () { return _samples_per_unit; }
-
-       int set_amplitude_above_axis (gdouble app);
-       gdouble get_amplitude_above_axis () { return _amplitude_above_axis; }
-
-       void set_show_waveforms (bool yn);
-       void set_show_waveforms_recording (bool yn) { use_rec_regions = yn; }
+       virtual int set_samples_per_unit (gdouble spp);
+       gdouble     get_samples_per_unit () { return _samples_per_unit; }
 
        ArdourCanvas::Item* canvas_item() { return canvas_group; }
 
-       sigc::signal<void,AudioRegionView*> AudioRegionViewAdded;
-
        enum ColorTarget {
                RegionColor,
                StreamBaseColor
        };
 
-       void apply_color (Gdk::Color&, ColorTarget t);
-       void set_selected_regionviews (AudioRegionSelection&);
+       Gdk::Color get_region_color () const { return region_color; }
+       void       apply_color (Gdk::Color&, ColorTarget t);
+
+       RegionView*  find_view (const ARDOUR::Region&);
+       void         foreach_regionview (sigc::slot<void,RegionView*> slot);
+
+       void set_selected_regionviews (RegionSelection&);
        void get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable* >&);
        void get_inverted_selectables (Selection&, list<Selectable* >& results);
-       Gdk::Color get_region_color () const { return region_color; }
 
-       void foreach_regionview (sigc::slot<void,AudioRegionView*> slot);
-       void foreach_crossfadeview (void (CrossfadeView::*pmf)(void));
+       void add_region_view (ARDOUR::Region*);
+       void region_layered (RegionView*);
+       
+       sigc::signal<void,RegionView*> RegionViewAdded;
 
-       void attach ();
+protected:
+       StreamView (RouteTimeAxisView&);
        
-       void region_layered (AudioRegionView*);
+//private: (FIXME?)
+
+       void         transport_changed();
+       void         rec_enable_changed();
+       void         sess_rec_enable_changed();
+       virtual void setup_rec_box () = 0;
+       void         update_rec_box ();
+       virtual void update_rec_regions () = 0;
        
-       AudioRegionView* find_view (const ARDOUR::AudioRegion&);
-
-       void show_all_xfades ();
-       void hide_all_xfades ();
-       void hide_xfades_involving (AudioRegionView&);
-       void reveal_xfades_involving (AudioRegionView&);
+       virtual void add_region_view_internal (ARDOUR::Region*, bool wait_for_waves) = 0;
+       virtual void remove_region_view (ARDOUR::Region* );
+       void         remove_rec_region (ARDOUR::Region*);
+
+       void         display_diskstream (ARDOUR::Diskstream* );
+       virtual void undisplay_diskstream ();
+       virtual void redisplay_diskstream () = 0;
+       void         diskstream_changed ();
+       
+       void         playlist_state_changed (ARDOUR::Change);
+       virtual void playlist_changed (ARDOUR::Diskstream* );
+       virtual void playlist_modified ();
+       
+       virtual void color_handler (ColorID, uint32_t) = 0;
 
-  private:
-       AudioTimeAxisView& _trackview;
 
-       ArdourCanvas::Group* canvas_group;
+       RouteTimeAxisView&        _trackview;
+       ArdourCanvas::Group*      canvas_group;
        ArdourCanvas::SimpleRect* canvas_rect; /* frame around the whole thing */
 
-       typedef list<AudioRegionView* > AudioRegionViewList;
-       AudioRegionViewList region_views;
-
-       typedef list<CrossfadeView*> CrossfadeViewList;
-       CrossfadeViewList crossfade_views;
+       typedef list<RegionView* > RegionViewList;
+       RegionViewList  region_views;
 
        double _samples_per_unit;
-       double _amplitude_above_axis;
-
-       sigc::connection screen_update_connection;
-       vector<RecBoxInfo> rec_rects;
-       list<ARDOUR::AudioRegion* > rec_regions;
-       bool rec_updating;
-       bool rec_active;
-       bool use_rec_regions;
-       list<sigc::connection> peak_ready_connections;
-       jack_nframes_t last_rec_peak_frame;
-       map<ARDOUR::Source*, bool> rec_peak_ready_map;
-       
-       void update_rec_box ();
-       void transport_changed();
-       void rec_enable_changed(void*  src = 0);
-       void sess_rec_enable_changed();
-       void setup_rec_box ();
-       void rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, ARDOUR::Source* src); 
-       void update_rec_regions ();
-       
-       void add_region_view (ARDOUR::Region*);
-       void add_region_view_internal (ARDOUR::Region*, bool wait_for_waves);
-       void remove_region_view (ARDOUR::Region* );
-       void remove_rec_region (ARDOUR::Region*);
-       void remove_audio_region_view (ARDOUR::AudioRegion* );
-       void remove_audio_rec_region (ARDOUR::AudioRegion*);
-
-       void display_diskstream (ARDOUR::AudioDiskstream* );
-       void undisplay_diskstream ();
-       void redisplay_diskstream ();
-       void diskstream_changed (void* );
-       void playlist_state_changed (ARDOUR::Change);
-       void playlist_changed (ARDOUR::AudioDiskstream* );
-       void playlist_modified ();
-
-       bool crossfades_visible;
-       void add_crossfade (ARDOUR::Crossfade*);
-       void remove_crossfade (ARDOUR::Crossfade*);
-
-       /* XXX why are these different? */
-       
-       Gdk::Color region_color;
-       uint32_t stream_base_color;
 
-       void color_handler (ColorID, uint32_t);
+       sigc::connection       screen_update_connection;
+       vector<RecBoxInfo>     rec_rects;
+       list<ARDOUR::Region* > rec_regions;
+       bool                   rec_updating;
+       bool                   rec_active;
+       bool                   use_rec_regions;
+       
+       Gdk::Color region_color;      ///< Contained region color
+       uint32_t   stream_base_color; ///< Background color
 
        vector<sigc::connection> playlist_connections;
-       sigc::connection playlist_change_connection;
+       sigc::connection         playlist_change_connection;
 };
 
 #endif /* __ardour_streamview_h__ */
+
diff --git a/gtk2_ardour/tape_region_view.cc b/gtk2_ardour/tape_region_view.cc
new file mode 100644 (file)
index 0000000..bd5ce8a
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+    Copyright (C) 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
+    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$
+*/
+
+#include <cmath>
+#include <algorithm>
+
+#include <gtkmm.h>
+
+#include <gtkmm2ext/gtk_ui.h>
+
+#include <ardour/playlist.h>
+#include <ardour/audioregion.h>
+#include <ardour/audiosource.h>
+#include <ardour/audio_diskstream.h>
+
+#include "tape_region_view.h"
+#include "audio_time_axis.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace sigc;
+using namespace ARDOUR;
+using namespace PBD;
+using namespace Editing;
+using namespace ArdourCanvas;
+
+const TimeAxisViewItem::Visibility TapeAudioRegionView::default_tape_visibility
+       = TimeAxisViewItem::Visibility (
+               TimeAxisViewItem::ShowNameHighlight |
+               TimeAxisViewItem::ShowFrame |
+               TimeAxisViewItem::HideFrameRight |
+               TimeAxisViewItem::FullWidthNameHighlight);
+
+TapeAudioRegionView::TapeAudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, 
+                                         AudioRegion& r, 
+                                         double spu, 
+                                         Gdk::Color& basic_color)
+
+       : AudioRegionView (parent, tv, r, spu, basic_color, 
+                          TimeAxisViewItem::Visibility ((r.position() != 0) ? default_tape_visibility : 
+                                                        TimeAxisViewItem::Visibility (default_tape_visibility|TimeAxisViewItem::HideFrameLeft)))
+{
+}
+
+void
+TapeAudioRegionView::init (Gdk::Color& basic_color, bool wfw)
+{
+       AudioRegionView::init(basic_color, wfw);
+
+       /* every time the wave data changes and peaks are ready, redraw */
+       
+       for (uint32_t n = 0; n < audio_region().n_channels(); ++n) {
+               audio_region().source(n).PeaksReady.connect (bind (mem_fun(*this, &TapeAudioRegionView::update), n));
+       }
+       
+}
+
+TapeAudioRegionView::~TapeAudioRegionView()
+{
+}
+
+void
+TapeAudioRegionView::update (uint32_t n)
+{
+       /* check that all waves are build and ready */
+
+       if (!tmp_waves.empty()) {
+               return;
+       }
+
+       ENSURE_GUI_THREAD (bind (mem_fun(*this, &TapeAudioRegionView::update), n));
+
+       /* this triggers a cache invalidation and redraw in the waveview */
+
+       waves[n]->property_data_src() = &_region;
+}
+
+void
+TapeAudioRegionView::set_frame_color ()
+{
+       fill_opacity = 255;
+       TimeAxisViewItem::set_frame_color ();
+}
diff --git a/gtk2_ardour/tape_region_view.h b/gtk2_ardour/tape_region_view.h
new file mode 100644 (file)
index 0000000..ed3852e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+    Copyright (C) 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
+    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$
+*/
+
+#ifndef __gtk_ardour_tape_audio_region_view_h__
+#define __gtk_ardour_tape_audio_region_view_h__
+
+#include <vector>
+
+#include "audio_region_view.h"
+
+class TapeAudioRegionView : public AudioRegionView
+{
+  public:
+       TapeAudioRegionView (ArdourCanvas::Group *, 
+                            RouteTimeAxisView&,
+                            ARDOUR::AudioRegion&,
+                            double initial_samples_per_unit,
+                            Gdk::Color& base_color);
+       ~TapeAudioRegionView ();
+
+  protected:
+       void init (Gdk::Color& base_color, bool wait_for_waves);
+
+       void set_frame_color ();
+       void update (uint32_t n);
+
+       static const TimeAxisViewItem::Visibility default_tape_visibility;
+};
+
+#endif /* __gtk_ardour_tape_audio_region_view_h__ */
diff --git a/gtk2_ardour/taperegionview.cc b/gtk2_ardour/taperegionview.cc
deleted file mode 100644 (file)
index 641d067..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
-    Copyright (C) 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
-    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$
-*/
-
-#include <cmath>
-#include <algorithm>
-
-#include <gtkmm.h>
-
-#include <gtkmm2ext/gtk_ui.h>
-
-#include <ardour/playlist.h>
-#include <ardour/audioregion.h>
-#include <ardour/audiosource.h>
-#include <ardour/audio_diskstream.h>
-
-#include "taperegionview.h"
-#include "audio_time_axis.h"
-#include "gui_thread.h"
-
-#include "i18n.h"
-
-using namespace sigc;
-using namespace ARDOUR;
-using namespace PBD;
-using namespace Editing;
-using namespace ArdourCanvas;
-
-TapeAudioRegionView::TapeAudioRegionView (ArdourCanvas::Group *parent, AudioTimeAxisView &tv, 
-                                         AudioRegion& r, 
-                                         double spu, 
-                                         Gdk::Color& basic_color)
-
-       : AudioRegionView (parent, tv, r, spu, basic_color, 
-                          TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameHighlight|
-                                                        TimeAxisViewItem::ShowFrame|
-                                                        TimeAxisViewItem::HideFrameLR|
-                                                        TimeAxisViewItem::FullWidthNameHighlight))
-{
-}
-
-void
-TapeAudioRegionView::init (double amplitude_above_axis, Gdk::Color& basic_color, bool wfw)
-{
-       XMLNode *node;
-
-       editor = 0;
-       valid = true;
-       in_destructor = false;
-       _amplitude_above_axis = amplitude_above_axis;
-       zero_line = 0;
-       wait_for_waves = wfw;
-       _height = 0;
-
-       _flags = 0;
-
-       if ((node = region.extra_xml ("GUI")) != 0) {
-               set_flags (node);
-       } else {
-               _flags = WaveformVisible;
-               store_flags ();
-       }
-
-       fade_in_handle = 0;
-       fade_out_handle = 0;
-       gain_line = 0;
-       sync_mark = 0;
-
-       compute_colors (basic_color);
-
-       create_waves ();
-
-       name_highlight->set_data ("regionview", this);
-
-       reset_width_dependent_items ((double) region.length() / samples_per_unit);
-
-       set_height (trackview.height);
-
-       region_muted ();
-       region_resized (BoundsChanged);
-       set_waveview_data_src();
-       region_locked ();
-
-       /* no events, no state changes */
-
-       set_colors ();
-
-       // ColorChanged.connect (mem_fun (*this, &AudioRegionView::color_handler));
-
-       /* every time the wave data changes and peaks are ready, redraw */
-
-       
-       for (uint32_t n = 0; n < region.n_channels(); ++n) {
-               region.source(n).PeaksReady.connect (bind (mem_fun(*this, &TapeAudioRegionView::update), n));
-       }
-       
-}
-
-TapeAudioRegionView::~TapeAudioRegionView()
-{
-}
-
-void
-TapeAudioRegionView::update (uint32_t n)
-{
-       /* check that all waves are build and ready */
-
-       if (!tmp_waves.empty()) {
-               return;
-       }
-
-       ENSURE_GUI_THREAD (bind (mem_fun(*this, &TapeAudioRegionView::update), n));
-
-       /* this triggers a cache invalidation and redraw in the waveview */
-
-       waves[n]->property_data_src() = &region;
-}
-
-void
-TapeAudioRegionView::set_frame_color ()
-{
-       fill_opacity = 255;
-       TimeAxisViewItem::set_frame_color ();
-}
diff --git a/gtk2_ardour/taperegionview.h b/gtk2_ardour/taperegionview.h
deleted file mode 100644 (file)
index 3e23e0f..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-    Copyright (C) 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
-    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$
-*/
-
-#ifndef __gtk_ardour_tape_audio_region_view_h__
-#define __gtk_ardour_tape_audio_region_view_h__
-
-#include <vector>
-
-#include "regionview.h"
-
-class TapeAudioRegionView : public AudioRegionView
-{
-  public:
-       TapeAudioRegionView (ArdourCanvas::Group *, 
-                            AudioTimeAxisView&,
-                            ARDOUR::AudioRegion&,
-                            double initial_samples_per_unit,
-                            Gdk::Color& base_color);
-       ~TapeAudioRegionView ();
-
-  protected:
-       void init (double amplitude_above_axis, Gdk::Color& base_color, bool wait_for_waves);
-
-       void set_frame_color ();
-       void update (uint32_t n);
-};
-
-#endif /* __gtk_ardour_tape_audio_region_view_h__ */
index b5ab5baa1098a6868cacc0ffda3ef24dc2558400..6261241139cfe25cd15e26f99149a59233acbbe6 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 ();
@@ -661,8 +662,6 @@ TimeAxisView::show_selection (TimeSelection& ts)
 void
 TimeAxisView::reshow_selection (TimeSelection& ts)
 {
-       cerr << name() << ": reshow selection" << endl;
-
        show_selection (ts);
 
        for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
@@ -882,7 +881,7 @@ TimeAxisView::reset_height()
        set_height_pixels (height);
 
        for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
-               (*i)->set_height ((TrackHeight)(*i)->height);
+               (*i)->set_height_pixels ((TrackHeight)(*i)->height);
        }
 }
        
index c607c781664a43acd0761cf8c0fff5760b9d919e..31ff3d84eefc40f06c604396b28965d979d8be16 100644 (file)
@@ -54,7 +54,7 @@ namespace Gtk {
 }
 
 class PublicEditor;
-class AudioRegionSelection;
+class RegionSelection;
 class TimeSelection;
 class PointSelection;
 class TimeAxisViewItem;
@@ -183,7 +183,7 @@ class TimeAxisView : public virtual AxisView
        virtual bool cut_copy_clear (Selection&, Editing::CutCopyOp) { return false; }
        virtual bool paste (jack_nframes_t, float times, Selection&, size_t nth) { return false; }
        
-       virtual void set_selected_regionviews (AudioRegionSelection&) {}
+       virtual void set_selected_regionviews (RegionSelection&) {}
        virtual void set_selected_points (PointSelection&) {}
 
        virtual ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir) {
index abab306a84d548044c3ea11b58c746895e42aa93..28fafcaa09e43f17ca12b40b9b08d9974d277f82 100644 (file)
@@ -137,8 +137,12 @@ TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group&
 
                uint32_t outline_what = 0x1|0x2|0x4|0x8;
 
-               if (visibility & HideFrameLR) {
-                       outline_what &= ~(0x1 | 0x2);
+               if (visibility & HideFrameLeft) {
+                       outline_what &= ~(0x1);
+               }
+
+               if (visibility & HideFrameRight) {
+                       outline_what &= ~(0x2);
                }
 
                if (visibility & HideFrameTB) {
index b23350eef721f6fa4b1d7053d73436524c7c17cc..9ddb06876a1c37100b24657fb1d6a75e5bad0367 100644 (file)
@@ -316,9 +316,10 @@ class TimeAxisViewItem : public Selectable
            ShowNameHighlight = 0x2,
            ShowNameText = 0x4,
            ShowHandles = 0x8,
-           HideFrameLR = 0x10,
-           HideFrameTB = 0x20,
-           FullWidthNameHighlight = 0x40
+           HideFrameLeft = 0x10,
+           HideFrameRight = 0x20,
+           HideFrameTB = 0x40,
+           FullWidthNameHighlight = 0x80
     };
 
     /**
index 91cb7ad58b21bf30c595cfbe9d3710b05428d326..ef90c347550edd8980c30288eac27a773fc64a1f 100644 (file)
@@ -215,7 +215,7 @@ get_font_for_style (string widgetname)
 {
        Gtk::Window window (WINDOW_TOPLEVEL);
        Gtk::Label foobar;
-       Glib::RefPtr<Style> style;
+       Glib::RefPtr<Gtk::Style> style;
 
        window.add (foobar);
        foobar.set_name (widgetname);
@@ -435,12 +435,10 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
                
        if (!special_handling_of_unmodified_accelerators ||
            ev->state & (Gdk::MOD1_MASK|
-                        Gdk::MOD2_MASK|
                         Gdk::MOD3_MASK|
                         Gdk::MOD4_MASK|
                         Gdk::MOD5_MASK|
-                        Gdk::CONTROL_MASK|
-                        Gdk::LOCK_MASK)) {
+                        Gdk::CONTROL_MASK)) {
 
                /* no special handling or modifiers in effect: accelerate first */
 
index c27ed33089bdab3ee2ce10ea3eb5c257ff7f80d2..e44ea4011e2d3fdcac138371f03e7198dd999cb0 100644 (file)
@@ -255,7 +255,7 @@ VisualTimeAxis::set_time_axis_color(Gdk::Color c)
 }
 
 void
-VisualTimeAxis::set_selected_regionviews (AudioRegionSelection& regions)
+VisualTimeAxis::set_selected_regionviews (RegionSelection& regions)
 {
        // Not handled by purely visual TimeAxis
 }
index 4be2da3b9a495eeb7ec12d64ac15ac02728a3347..c68ce8da1c63e97ed54d5642a18843cb17a5e9d5 100644 (file)
@@ -42,7 +42,7 @@ class ImageFrameView;
 class ImageFrameTimeAxisView;
 class MarkersTimeAxisView;
 class TimeSelection;
-class AudioRegionSelection;
+class RegionSelection;
 class MarkerTimeAxis;
 class TimeAxisViewStrip;
 
@@ -105,7 +105,7 @@ class VisualTimeAxis : public TimeAxisView
                /**
                 * Not implemented
                 */
-               virtual void set_selected_regionviews(AudioRegionSelection&) ;
+               virtual void set_selected_regionviews(RegionSelection&) ;
        
 
                //---------------------------------------------------------------------------------//
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 a1bed7aeefe9015825894e0a65b0999f2f474b5b..44cec8638c1bfd3873e358b8c5a525533ebd5337 100644 (file)
@@ -27,9 +27,11 @@ ardour.Append(POTFILE = domain + '.pot')
 ardour.Append(CPPPATH = '#libs/surfaces/control_protocol')
 
 ardour_files=Split("""
+diskstream.cc
 audio_diskstream.cc
 audio_library.cc
 audio_playlist.cc
+track.cc
 audio_track.cc
 audioengine.cc
 audiofilesource.cc
@@ -88,7 +90,6 @@ sndfile_helpers.cc
 sndfilesource.cc
 source.cc
 state_manager.cc
-stateful.cc
 tempo.cc
 utils.cc
 version.cc
@@ -99,7 +100,7 @@ arch_specific_objects = [ ]
 
 osc_files = [ 'osc.cc' ]
 vst_files = [ 'vst_plugin.cc', 'session_vst.cc' ]
-coreaudio_files = [ 'coreaudiosource.cc' ]
+coreaudio_files = [ 'audio_unit.cc', 'coreaudiosource.cc' ]
 extra_sources = [ ]
 
 if ardour['VST']:
@@ -199,7 +200,7 @@ ardour.Merge ([
             libraries['lrdf'],
             libraries['samplerate'],
             libraries['sigc2'],
-            libraries['pbd3'],
+            libraries['pbd'],
             libraries['soundtouch'],
             libraries['midi++2'],
             libraries['glib2'],
@@ -209,6 +210,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 c0dfea9a950e9edccc885a363dcbdc933feaf728..e3b7cf2313ebac18012588801d8bcddd84bdc405 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 (bool with_vst, bool try_optimization);
        int cleanup ();
 
        
@@ -58,7 +58,7 @@ namespace ARDOUR {
 
        const layer_t max_layer = UCHAR_MAX;
 
-       id_t new_id();
+       microseconds_t get_microseconds ();
 
        Change new_change ();
 
@@ -74,7 +74,7 @@ namespace ARDOUR {
            const char* old;
        };
 
-};
+}
 
 /* how do we make these be within the Ardour namespace? */
 
index 9355a3fccbf7a815aa5d2e8eb7f446382c24efb3..e2dfc5fd0c92051300162059667ff37097cd9ab9 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
     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: diskstream.h 579 2006-06-12 19:56:37Z essej $
 */
 
-#ifndef __ardour_diskstream_h__
-#define __ardour_diskstream_h__
+#ifndef __ardour_audio_diskstream_h__
+#define __ardour_audio_diskstream_h__
 
 #include <sigc++/signal.h>
 
@@ -33,7 +31,7 @@
 
 #include <pbd/fastlog.h>
 #include <pbd/ringbufferNPT.h>
+#include <pbd/stateful.h> 
 
 #include <ardour/ardour.h>
 #include <ardour/configuration.h>
@@ -42,7 +40,8 @@
 #include <ardour/route.h>
 #include <ardour/port.h>
 #include <ardour/utils.h>
-#include <ardour/stateful.h>
+#include <ardour/diskstream.h>
+#include <ardour/audioplaylist.h>
 
 struct tm;
 
@@ -55,53 +54,20 @@ class AudioPlaylist;
 class AudioFileSource;
 class IO;
 
-class AudioDiskstream : public Stateful, public sigc::trackable
+class AudioDiskstream : public Diskstream
 {      
   public:
-       enum Flag {
-               Recordable = 0x1,
-               Hidden = 0x2,
-               Destructive = 0x4
-       };
-
-       AudioDiskstream (Session &, const string& name, Flag f = Recordable);
+       AudioDiskstream (Session &, const string& name, Diskstream::Flag f = Recordable);
        AudioDiskstream (Session &, const XMLNode&);
 
-       string name() const { return _name; }
-
-       ARDOUR::IO* io() const { return _io; }
-       void set_io (ARDOUR::IO& io);
+       const PBD::ID& id() const { return _id; }
 
+       // FIXME
        AudioDiskstream& ref() { _refcnt++; return *this; }
-       void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
-       uint32_t refcnt() const { return _refcnt; }
 
        float playback_buffer_load() const;
        float capture_buffer_load() const;
 
-       void set_flag (Flag f) {
-               _flags |= f;
-       }
-
-       void unset_flag (Flag f) {
-               _flags &= ~f;
-       }
-
-       AlignStyle alignment_style() const { return _alignment_style; }
-       void set_align_style (AlignStyle);
-       void set_persistent_align_style (AlignStyle);
-
-       bool hidden() const { return _flags & Hidden; }
-       bool recordable() const { return _flags & Recordable; }
-       bool destructive() const { return _flags & Destructive; }
-
-       void set_destructive (bool yn);
-
-       jack_nframes_t roll_delay() const { return _roll_delay; }
-       void set_roll_delay (jack_nframes_t);
-
-       int set_name (string str, void* src);
-
        string input_source (uint32_t n=0) const {
                if (n < channels.size()) {
                        return channels[n].source ? channels[n].source->name() : "";
@@ -114,14 +80,7 @@ class AudioDiskstream : public Stateful, public sigc::trackable
                if (n < channels.size()) return channels[n].source; return 0; 
        }
 
-       void set_record_enabled (bool yn, void *src);
-       bool record_enabled() const { return g_atomic_int_get (&_record_enabled); }
-       void punch_in ();
-       void punch_out ();
-
-       bool  reversed() const { return _actual_speed < 0.0f; }
-       double speed() const { return _visible_speed; }
-       void set_speed (double);
+       void set_record_enabled (bool yn);
 
        float peak_power(uint32_t n=0) { 
                float x = channels[n].peak_power;
@@ -132,14 +91,13 @@ class AudioDiskstream : public Stateful, public sigc::trackable
                        return minus_infinity();
                }
        }
+       
+       AudioPlaylist* audio_playlist () { return dynamic_cast<AudioPlaylist*>(_playlist); }
 
-       int  use_playlist (AudioPlaylist *);
+       int use_playlist (Playlist *);
        int use_new_playlist ();
        int use_copy_playlist ();
 
-       void start_scrub (jack_nframes_t where);
-       void end_scrub ();
-
        Sample *playback_buffer (uint32_t n=0) {
                if (n < channels.size())
                        return channels[n].current_playback_buffer;
@@ -152,51 +110,23 @@ class AudioDiskstream : public Stateful, public sigc::trackable
                return 0;
        }
 
-       AudioPlaylist *playlist () { return _playlist; }
-
        AudioFileSource *write_source (uint32_t n=0) {
                if (n < channels.size())
                        return channels[n].write_source;
                return 0;
        }
 
-       jack_nframes_t current_capture_start() const { return capture_start_frame; }
-       jack_nframes_t current_capture_end() const { return capture_start_frame + capture_captured; }
-       jack_nframes_t get_capture_start_frame (uint32_t n=0);
-       jack_nframes_t get_captured_frames (uint32_t n=0);
-       
-       uint32_t n_channels() { return _n_channels; }
-
        int add_channel ();
        int remove_channel ();
        
-       static void set_disk_io_chunk_frames (uint32_t n) {
-               disk_io_chunk_frames = n;
-       }
-
-       static jack_nframes_t disk_io_frames() { return disk_io_chunk_frames; }
        
-       sigc::signal<void,void*> record_enable_changed;
-       sigc::signal<void>       speed_changed;
-       sigc::signal<void,void*> reverse_changed;
-       sigc::signal<void>       PlaylistChanged;
-       sigc::signal<void>       AlignmentStyleChanged;
-
-       static sigc::signal<void> DiskOverrun;
-       static sigc::signal<void> DiskUnderrun;
-       static sigc::signal<void,AudioDiskstream*> AudioDiskstreamCreated;   // XXX use a ref with sigc2
-       static sigc::signal<void,list<AudioFileSource*>*> DeleteSources;
-
        /* stateful */
 
        XMLNode& get_state(void);
-       int set_state(const XMLNode& node);
+       int      set_state(const XMLNode& node);
 
        void monitor_input (bool);
 
-       jack_nframes_t capture_offset() const { return _capture_offset; }
-       void           set_capture_offset ();
-
        static void swap_by_ptr (Sample *first, Sample *last) {
                while (first < last) {
                        Sample tmp = *first;
@@ -213,19 +143,7 @@ class AudioDiskstream : public Stateful, public sigc::trackable
                }
        }
 
-       bool slaved() const { return _slaved; }
-       void set_slaved(bool yn) { _slaved = yn; }
-
-       int set_loop (Location *loc);
-       sigc::signal<void,Location *> LoopSet;
-
-       std::list<Region*>& last_capture_regions () {
-               return _last_capture_regions;
-       }
-
-       void handle_input_change (IOChange, void *src);
-
-       id_t id() const { return _id; }
+       std::list<Region*>& last_capture_regions () { return _last_capture_regions; }
 
        XMLNode* deprecated_io_node;
 
@@ -237,9 +155,8 @@ class AudioDiskstream : public Stateful, public sigc::trackable
           while they are called.
        */
 
-       void set_pending_overwrite (bool);
+       void set_pending_overwrite(bool);
        int  overwrite_existing_buffers ();
-       void reverse_scrub_buffer (bool to_forward);
        void set_block_size (jack_nframes_t);
        int  internal_playback_seek (jack_nframes_t distance);
        int  can_internal_playback_seek (jack_nframes_t distance);
@@ -247,9 +164,6 @@ class AudioDiskstream : public Stateful, public sigc::trackable
        void reset_write_sources (bool, bool force = false);
        void non_realtime_input_change ();
 
-       uint32_t read_data_count() const { return _read_data_count; }
-       uint32_t write_data_count() const { return _write_data_count; }
-
   protected:
        friend class Auditioner;
        int  seek (jack_nframes_t which_sample, bool complete_refill = false);
@@ -257,38 +171,23 @@ class AudioDiskstream : public Stateful, public sigc::trackable
   protected:
        friend class AudioTrack;
 
-       void prepare ();
        int  process (jack_nframes_t transport_frame, jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input);
        bool commit  (jack_nframes_t nframes);
-       void recover (); /* called if commit will not be called, but process was */
 
   private:
 
        /* use unref() to destroy a diskstream */
-
        ~AudioDiskstream();
 
-       enum TransitionType {
-               CaptureStart = 0,
-               CaptureEnd
-       };
-       
-       struct CaptureTransition {
-
-               TransitionType   type;
-               // the start or end file frame pos
-               jack_nframes_t   capture_val;
-       };
-       
        struct ChannelInfo {
 
                Sample     *playback_wrap_buffer;
                Sample     *capture_wrap_buffer;
                Sample     *speed_buffer;
 
-               float       peak_power;
+               float       peak_power;
 
-               AudioFileSource   *fades_source;
+               AudioFileSource   *fades_source;
                AudioFileSource   *write_source;
 
                Port         *source;
@@ -310,129 +209,30 @@ class AudioDiskstream : public Stateful, public sigc::trackable
                jack_nframes_t                     curr_capture_cnt;
        };
 
-       typedef vector<ChannelInfo> ChannelList;
-
-
-       string            _name;
-       ARDOUR::Session&  _session;
-       ARDOUR::IO*       _io;
-       ChannelList        channels;
-       uint32_t      _n_channels;
-       id_t              _id;
-
-       mutable gint             _record_enabled;
-       AudioPlaylist*           _playlist;
-       double                   _visible_speed;
-       double                   _actual_speed;
-       /* items needed for speed change logic */
-       bool                     _buffer_reallocation_required;
-       bool                     _seek_required;
+       /* The two central butler operations */
+       int do_flush (Session::RunContext context, bool force = false);
+       int do_refill () { return _do_refill(_mixdown_buffer, _gain_buffer, _conversion_buffer); }
        
-       bool                      force_refill;
-       jack_nframes_t            capture_start_frame;
-       jack_nframes_t            capture_captured;
-       bool                      was_recording;
-       jack_nframes_t            adjust_capture_position;
-       jack_nframes_t           _capture_offset;
-       jack_nframes_t           _roll_delay;
-       jack_nframes_t            first_recordable_frame;
-       jack_nframes_t            last_recordable_frame;
-       int                       last_possibly_recording;
-       AlignStyle               _alignment_style;
-       bool                     _scrubbing;
-       bool                     _slaved;
-       bool                     _processed;
-       Location*                 loop_location;
-       jack_nframes_t            overwrite_frame;
-       off_t                     overwrite_offset;
-       bool                      pending_overwrite;
-       bool                      overwrite_queued;
-       IOChange                  input_change_pending;
-       jack_nframes_t            wrap_buffer_size;
-       jack_nframes_t            speed_buffer_size;
-
-       uint64_t                  last_phase;
-       uint64_t                  phi;
-       
-       jack_nframes_t            file_frame;           
-       jack_nframes_t            playback_sample;
-       jack_nframes_t            playback_distance;
-
-       uint32_t                 _read_data_count;
-       uint32_t                 _write_data_count;
-
-       bool                      in_set_state;
-       AlignStyle               _persistent_alignment_style;
-       bool                      first_input_change;
-
-       Glib::Mutex  state_lock;
+       int do_refill_with_alloc();
 
-       jack_nframes_t scrub_start;
-       jack_nframes_t scrub_buffer_size;
-       jack_nframes_t scrub_offset;
-       uint32_t _refcnt;
-
-       sigc::connection ports_created_c;
-       sigc::connection plmod_connection;
-       sigc::connection plstate_connection;
-       sigc::connection plgone_connection;
-
-       /* the two central butler operations */
-
-       int do_flush (char * workbuf, bool force = false);
-       int do_refill (Sample *mixdown_buffer, float *gain_buffer, char *workbuf);
-
-       int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf, jack_nframes_t& start, jack_nframes_t cnt, 
-                 ChannelInfo& channel_info, int channel, bool reversed);
-
-       uint32_t i_am_the_modifier;
-       
-       /* XXX fix this redundancy ... */
-
-       void playlist_changed (Change);
-       void playlist_modified ();
-       void playlist_deleted (Playlist*);
-       void session_controls_changed (Session::ControlType);
+       int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf,
+               jack_nframes_t& start, jack_nframes_t cnt, 
+               ChannelInfo& channel_info, int channel, bool reversed);
 
        void finish_capture (bool rec_monitors_input);
-       void clean_up_capture (struct tm&, time_t, bool abort);
        void transport_stopped (struct tm&, time_t, bool abort);
 
-       struct CaptureInfo {
-           uint32_t start;
-           uint32_t frames;
-       };
-
-       vector<CaptureInfo*> capture_info;
-       Glib::Mutex  capture_info_lock;
-       
-       void init (Flag);
+       void init (Diskstream::Flag);
 
        void init_channel (ChannelInfo &chan);
        void destroy_channel (ChannelInfo &chan);
        
-       static jack_nframes_t disk_io_chunk_frames;
-
        int use_new_write_source (uint32_t n=0);
-       int use_new_fade_source (uint32_t n=0);
 
        int find_and_use_playlist (const string&);
 
        void allocate_temporary_buffers ();
 
-       unsigned char _flags;
-
-       int  create_input_port ();
-       int  connect_input_port ();
-       int  seek_unlocked (jack_nframes_t which_sample);
-
-       int ports_created ();
-
-       bool realtime_set_speed (double, bool global_change);
-       void non_realtime_set_speed ();
-
-       std::list<Region*> _last_capture_regions;
-       std::vector<AudioFileSource*> capturing_sources;
        int use_pending_capture_data (XMLNode& node);
 
        void get_input_sources ();
@@ -440,8 +240,29 @@ class AudioDiskstream : public Stateful, public sigc::trackable
        void set_align_style_from_io();
        void setup_destructive_playlist ();
        void use_destructive_playlist ();
+
+       void engage_record_enable ();
+       void disengage_record_enable ();
+
+       // Working buffers for do_refill (butler thread)
+       static void allocate_working_buffers();
+       static void free_working_buffers();
+
+       static size_t  _working_buffers_size;
+       static Sample* _mixdown_buffer;
+       static gain_t* _gain_buffer;
+       static char*   _conversion_buffer;
+
+       // Uh, /really/ private?  (death to friend classes)
+       int _do_refill (Sample *mixdown_buffer, float *gain_buffer, char *workbuf);
+       
+       
+       std::vector<AudioFileSource*> capturing_sources;
+       
+       typedef vector<ChannelInfo> ChannelList;
+       ChannelList channels;
 };
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
-#endif /* __ardour_diskstream_h__ */
+#endif /* __ardour_audio_diskstream_h__ */
index 2f9e84551b5c523ac0779a70a178e31414e5f253..f5ac6da65497683fdb979b38677736d25e57ccc5 100644 (file)
 
 #include <sigc++/signal.h>
 
+#include <pbd/stateful.h>
+
 using std::vector;
 using std::string;
 using std::map;
 
 namespace ARDOUR {
 
-class AudioLibrary
+class AudioLibrary : public Stateful
 {
   public:
        AudioLibrary ();
        ~AudioLibrary ();
 
+       static string state_node_name;
+       
+       XMLNode& get_state (void);
+       int set_state (const XMLNode&);
+
        void set_paths (vector<string> paths);
        vector<string> get_paths ();
        void scan_paths ();
index 1c17cbc85991e91e8356211d6ef0a954ce3d0d7b..15b99297c883b42dd5e9de0de1d65f2c9ad4523c 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef __ardour_audio_track_h__
 #define __ardour_audio_track_h__
 
-#include <ardour/route.h>
+#include <ardour/track.h>
 
 namespace ARDOUR {
 
@@ -30,79 +30,38 @@ class AudioDiskstream;
 class AudioPlaylist;
 class RouteGroup;
 
-class AudioTrack : public Route
+class AudioTrack : public Track
 {
   public:
        AudioTrack (Session&, string name, Route::Flag f = Route::Flag (0), TrackMode m = Normal);
        AudioTrack (Session&, const XMLNode&);
        ~AudioTrack ();
-       
-       int set_name (string str, void *src);
-
-       int  roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
 
-                  jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input);
-       int  no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
-                     jack_nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input);
-       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);
-
-       void toggle_monitor_input ();
+       int roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
+               jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input);
+       
+       int no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
+               jack_nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input);
+       
+       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);
 
-       bool can_record() const { return true; }
-       void set_record_enable (bool yn, void *src);
+       AudioDiskstream& audio_diskstream() const;
 
-       AudioDiskstream& disk_stream() const { return *diskstream; }
-       int set_diskstream (AudioDiskstream&, void *);
        int use_diskstream (string name);
-       int use_diskstream (id_t id);
-
-       TrackMode mode() const { return _mode; }
-       void set_mode (TrackMode m);
-       sigc::signal<void> ModeChanged;
-
-       jack_nframes_t update_total_latency();
-       void set_latency_delay (jack_nframes_t);
+       int use_diskstream (const PBD::ID& id);
        
        int export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t end_frame);
 
-       sigc::signal<void,void*> diskstream_changed;
-
-       enum FreezeState {
-               NoFreeze,
-               Frozen,
-               UnFrozen
-       };
-
-       FreezeState freeze_state() const;
-
-       sigc::signal<void> FreezeChange;
        void freeze (InterThreadInfo&);
        void unfreeze ();
 
        void bounce (InterThreadInfo&);
        void bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo&);
 
-       XMLNode& get_state();
-       XMLNode& get_template();
        int set_state(const XMLNode& node);
 
-       MIDI::Controllable& midi_rec_enable_control() {
-               return _midi_rec_enable_control;
-       }
-
-       void reset_midi_control (MIDI::Port*, bool);
-       void send_all_midi_feedback ();
-
-       bool record_enabled() const;
-       void set_meter_point (MeterPoint, void* src);
-
   protected:
-       AudioDiskstream *diskstream;
-       MeterPoint _saved_meter_point;
-       TrackMode _mode;
-
        XMLNode& state (bool full);
 
        void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, 
@@ -110,62 +69,14 @@ class AudioTrack : public Route
                               bool meter);
 
        uint32_t n_process_buffers ();
-
+       
   private:
-       struct FreezeRecordInsertInfo {
-           FreezeRecordInsertInfo(XMLNode& st) 
-                   : state (st), insert (0) {}
-
-           XMLNode  state;
-           Insert*  insert;
-           id_t     id;
-           UndoAction memento;
-       };
-
-       struct FreezeRecord {
-           FreezeRecord() {
-                   playlist = 0;
-                   have_mementos = false;
-           }
-
-           ~FreezeRecord();
-
-           AudioPlaylist* playlist;
-           vector<FreezeRecordInsertInfo*> insert_info;
-           bool have_mementos;
-           FreezeState state;
-       };
-
-       FreezeRecord _freeze_record;
-       XMLNode* pending_state;
-
-       void diskstream_record_enable_changed (void *src);
-       void diskstream_input_channel_changed (void *src);
-
-       void input_change_handler (void *src);
-
-       sigc::connection recenable_connection;
-       sigc::connection ic_connection;
-
-       int deprecated_use_diskstream_connections ();
+       int  set_diskstream (AudioDiskstream&, void *);
+       int  deprecated_use_diskstream_connections ();
        void set_state_part_two ();
        void set_state_part_three ();
-
-       struct MIDIRecEnableControl : public MIDI::Controllable {
-               MIDIRecEnableControl (AudioTrack&, MIDI::Port *);
-               void set_value (float);
-               void send_feedback (bool);
-               MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force = false);
-               AudioTrack& track;
-               bool setting;
-               bool last_written;
-       };
-
-       MIDIRecEnableControl _midi_rec_enable_control;
-
-       bool _destructive;
 };
 
-}; /* namespace ARDOUR*/
+} // namespace ARDOUR
 
 #endif /* __ardour_audio_track_h__ */
diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h
new file mode 100644 (file)
index 0000000..f437ae0
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+    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.
+
+*/
+
+#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>
+
+class CAComponent;
+class CAAudioUnit;
+class CAComponentDescription;
+
+namespace ARDOUR {
+
+class AudioEngine;
+class Session;
+
+class AUPlugin : public ARDOUR::Plugin
+{
+  public:
+       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;
+};
+
+class AUPluginInfo : public PluginInfo {
+  public:      
+       AUPluginInfo () { };
+       ~AUPluginInfo ();
+
+       CAComponentDescription* desc;
+
+       static PluginInfoList discover ();
+       PluginPtr load (Session& session);
+
+  private:
+       static std::string get_name (CAComponentDescription&);
+};
+
+typedef boost::shared_ptr<AUPluginInfo> AUPluginInfoPtr;
+
+} // namespace ARDOUR
+
+#endif // __ardour_audio_unit_h__
index 50bf7dddcceb2b68eb35df0d63d135608ed56f56..e7500fc7a2e2d17c7f7dd7d0ac545aedec4f9727 100644 (file)
@@ -34,6 +34,8 @@
 #include <ardour/ardour.h>
 #include <jack/jack.h>
 #include <jack/transport.h>
+#include <ardour/types.h>
+#include <ardour/data_type.h>
 
 namespace ARDOUR {
 
@@ -104,8 +106,8 @@ class AudioEngine : public sigc::trackable
                virtual const char *what() const throw() { return "could not connect to engine backend"; }
        };
 
-       Port *register_audio_input_port (const std::string& portname);
-       Port *register_audio_output_port (const std::string& portname);
+       Port *register_input_port (DataType type, const std::string& portname);
+       Port *register_output_port (DataType type, const std::string& portname);
        int   unregister_port (Port *);
        
        int connect (const std::string& source, const std::string& destination);
@@ -243,6 +245,6 @@ class AudioEngine : public sigc::trackable
     mutable gint     m_meter_exit;
 };
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 #endif /* __ardour_audioengine_h__ */
index 36251c07ffc5f9f017eb74a2ec8a4cc3e8728903..eb3fd750d4941aabb0ced9a07a0771f090ae13a5 100644 (file)
@@ -42,7 +42,8 @@ class AudioFileSource : public AudioSource {
                Removable = 0x8,
                RemovableIfEmpty = 0x10,
                RemoveAtDestroy = 0x20,
-               NoPeakFile = 0x40
+               NoPeakFile = 0x40,
+               Destructive = 0x80
        };
 
        virtual ~AudioFileSource ();
@@ -95,7 +96,7 @@ class AudioFileSource : public AudioSource {
        static void set_bwf_serial_number (int);
        
        static void set_search_path (string);
-       static void set_header_position_offset (jack_nframes_t offset, bool negative);
+       static void set_header_position_offset (jack_nframes_t offset );
 
        static sigc::signal<void> HeaderPositionOffsetChanged;
 
@@ -107,7 +108,7 @@ class AudioFileSource : public AudioSource {
           to cause issues.
        */
 
-       void handle_header_position_change ();
+       virtual void handle_header_position_change () {}
 
   protected:
        
@@ -141,7 +142,6 @@ class AudioFileSource : public AudioSource {
        static char bwf_serial_number[13];
 
        static uint64_t header_position_offset;
-       static bool     header_position_negative;
 
        virtual void set_timeline_position (jack_nframes_t pos);
        virtual void set_header_timeline_position () = 0;
@@ -151,7 +151,7 @@ class AudioFileSource : public AudioSource {
        bool writable() const { return _flags & Writable; }
 };
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 #endif /* __ardour_audiofilesource_h__ */
 
index 1b60cf185d2a0dd31bccc2b72169eb23247316fe..5a77067f8fd76f95b2d127bae9e120ffb9e9f127 100644 (file)
@@ -77,9 +77,6 @@ class AudioPlaylist : public ARDOUR::Playlist
 
        bool destroy_region (Region*);
 
-       void get_equivalent_regions (const AudioRegion&, std::vector<AudioRegion*>&);
-       void get_region_list_equivalent_regions (const AudioRegion&, std::vector<AudioRegion*>&);
-
        void drop_all_states ();
 
     protected:
index 009aa4b5b0da34b3f1acf55cba17dfa5025c3d1e..683e946713029d31ecd9986554e270f16c8dc7a3 100644 (file)
@@ -27,8 +27,9 @@
 #include <pbd/undo.h>
 
 #include <ardour/ardour.h>
-#include <ardour/gain.h>
 #include <ardour/region.h>
+#include <ardour/gain.h>
+#include <ardour/logcurve.h>
 #include <ardour/export.h>
 
 class XMLNode;
@@ -43,14 +44,14 @@ class AudioSource;
 
 struct AudioRegionState : public RegionState 
 {
-    AudioRegionState (std::string why);
-
-    Curve _fade_in;
-    Curve _fade_out;
-    Curve _envelope;
-    gain_t _scale_amplitude;
-    uint32_t _fade_in_disabled;
-    uint32_t _fade_out_disabled;
+       AudioRegionState (std::string why);
+
+       Curve    _fade_in;
+       Curve    _fade_out;
+       Curve    _envelope;
+       gain_t   _scale_amplitude;
+       uint32_t _fade_in_disabled;
+       uint32_t _fade_out_disabled;
 };
 
 class AudioRegion : public Region
@@ -75,11 +76,7 @@ class AudioRegion : public Region
        AudioRegion (SourceList &, const XMLNode&);
        ~AudioRegion();
 
-       bool region_list_equivalent (const AudioRegion&) const ;
-       bool source_equivalent (const AudioRegion&) const;
-       bool equivalent (const AudioRegion&) const;
-       bool size_equivalent (const AudioRegion&) const;
-       bool overlap_equivalent (const AudioRegion&) const;
+       bool source_equivalent (const Region&) const;
 
        bool speed_mismatch (float) const;
 
@@ -96,7 +93,7 @@ class AudioRegion : public Region
        vector<string> master_source_names();
        
        bool envelope_active () const { return _flags & Region::EnvelopeActive; }
-       bool fade_in_active () const { return _flags & Region::FadeIn; }
+       bool fade_in_active ()  const { return _flags & Region::FadeIn; }
        bool fade_out_active () const { return _flags & Region::FadeOut; }
        bool captured() const { return !(_flags & (Region::Flag (Region::Import|Region::External))); }
 
@@ -104,20 +101,21 @@ class AudioRegion : public Region
        Curve& fade_out() { return _fade_out; }
        Curve& envelope() { return _envelope; }
 
-       jack_nframes_t read_peaks (PeakData *buf, jack_nframes_t npeaks, jack_nframes_t offset, jack_nframes_t cnt, uint32_t chan_n=0, double samples_per_unit= 1.0) const;
-
-       virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, 
-                                       float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, 
-                                       uint32_t chan_n = 0,
-                                       jack_nframes_t read_frames = 0,
-                                       jack_nframes_t skip_frames = 0) const;
+       jack_nframes_t read_peaks (PeakData *buf, jack_nframes_t npeaks,
+                       jack_nframes_t offset, jack_nframes_t cnt,
+                       uint32_t chan_n=0, double samples_per_unit= 1.0) const;
 
-       jack_nframes_t master_read_at (Sample *buf, Sample *mixdown_buffer, 
-                                      float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n=0) const;
+       virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buf,
+                       float *gain_buf, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, 
+                       uint32_t       chan_n      = 0,
+                       jack_nframes_t read_frames = 0,
+                       jack_nframes_t skip_frames = 0) const;
 
+       jack_nframes_t master_read_at (Sample *buf, Sample *mixdown_buf, 
+                       float *gain_buf, char * workbuf,
+                       jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n=0) const;
 
        XMLNode& state (bool);
-       XMLNode& get_state ();
        int      set_state (const XMLNode&);
 
        static void set_default_fade (float steepness, jack_nframes_t len);
@@ -127,8 +125,7 @@ class AudioRegion : public Region
                Fast,
                Slow,
                LogA,
-               LogB,
-
+               LogB
        };
 
        void set_fade_in_active (bool yn);
@@ -145,10 +142,6 @@ class AudioRegion : public Region
 
        int separate_by_channel (ARDOUR::Session&, vector<AudioRegion*>&) const;
 
-       uint32_t read_data_count() const { return _read_data_count; }
-
-       ARDOUR::Playlist* playlist() const { return _playlist; }
-
        UndoAction get_memento() const;
 
        /* filter */
@@ -172,20 +165,6 @@ class AudioRegion : public Region
        friend class Playlist;
 
   private:
-       SourceList        sources;
-       SourceList        master_sources; /* used when timefx are applied, so 
-                                            we can always use the original
-                                            source.
-                                         */
-       mutable Curve     _fade_in;
-       FadeShape         _fade_in_shape;
-       mutable Curve     _fade_out;
-       FadeShape         _fade_out_shape;
-       mutable Curve     _envelope;
-       gain_t            _scale_amplitude;
-       uint32_t          _fade_in_disabled;
-       uint32_t          _fade_out_disabled;
-
        void set_default_fades ();
        void set_default_fade_in ();
        void set_default_fade_out ();
@@ -197,10 +176,6 @@ class AudioRegion : public Region
        void recompute_gain_at_end ();
        void recompute_gain_at_start ();
 
-       bool copied() const { return _flags & Copied; }
-       void maybe_uncopy ();
-       void rename_after_first_edit ();
-
        jack_nframes_t _read_at (const SourceList&, Sample *buf, Sample *mixdown_buffer, 
                                 float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, 
                                 uint32_t chan_n = 0,
@@ -217,6 +192,21 @@ class AudioRegion : public Region
        void envelope_changed (Change);
 
        void source_deleted (Source*);
+       
+       
+       SourceList        sources;
+       
+       /** Used when timefx are applied, so we can always use the original source. */
+       SourceList        master_sources; 
+
+       mutable Curve     _fade_in;
+       FadeShape         _fade_in_shape;
+       mutable Curve     _fade_out;
+       FadeShape         _fade_out_shape;
+       mutable Curve     _envelope;
+       gain_t            _scale_amplitude;
+       uint32_t          _fade_in_disabled;
+       uint32_t          _fade_out_disabled;
 };
 
 } /* namespace ARDOUR */
index 1dcf5b42f3e50c13e4da0560051802aaa92e3b85..35158a24e7c1439d041d7e513f8f8a0d4d6369d7 100644 (file)
@@ -33,7 +33,7 @@
 
 #include <ardour/source.h>
 #include <ardour/ardour.h>
-#include <ardour/stateful.h>
+#include <pbd/stateful.h> 
 #include <pbd/xml++.h>
 
 using std::list;
@@ -51,6 +51,13 @@ class AudioSource : public Source
        AudioSource (const XMLNode&);
        virtual ~AudioSource ();
 
+       /* one could argue that this should belong to Source, but other data types
+          generally do not come with a model of "offset along an audio timeline"
+          so its here in AudioSource for now.
+       */
+
+       virtual jack_nframes_t natural_position() const { return 0; }
+       
        /* returns the number of items in this `audio_source' */
 
        virtual jack_nframes_t length() const {
diff --git a/libs/ardour/ardour/buffer.h b/libs/ardour/ardour/buffer.h
new file mode 100644 (file)
index 0000000..8a88802
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+    Copyright (C) 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 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.
+*/
+
+#ifndef __ardour_buffer_h__
+#define __ardour_buffer_h__
+
+#define _XOPEN_SOURCE 600
+#include <cstdlib> // for posix_memalign
+#include <cassert>
+#include <ardour/types.h>
+#include <ardour/data_type.h>
+
+namespace ARDOUR {
+
+
+/* Yes, this is a bit of a mess right now.  I'll clean it up when everything
+ * using it works out.. */
+
+
+/** A buffer of recordable/playable data.
+ *
+ * This is a datatype-agnostic base class for all buffers (there are no
+ * methods to actually access the data).  This provides a way for code that
+ * doesn't care about the data type to still deal with buffers (which is
+ * why the base class can't be a template).
+ * 
+ * To actually read/write buffer contents, use the appropriate derived class.
+ */
+class Buffer
+{
+public:
+       Buffer(DataType type, size_t capacity)
+       : _type(type), _capacity(capacity), _size(0) 
+       {}
+
+       virtual ~Buffer() {}
+
+       /** Maximum capacity of buffer.
+        * Note in some cases the entire buffer may not contain valid data, use size. */
+       size_t capacity() const { return _capacity; }
+
+       /** Amount of valid data in buffer.  Use this over capacity almost always. */
+       size_t size() const { return _size; }
+
+       /** Type of this buffer.
+        * Based on this you can static cast a Buffer* to the desired type. */
+       DataType type() const { return _type; }
+
+protected:
+       DataType _type;
+       size_t   _capacity;
+       size_t   _size;
+};
+
+
+/* Inside every class with a type in it's name is a template waiting to get out... */
+
+
+/** Buffer containing 32-bit floating point (audio) data. */
+class AudioBuffer : public Buffer
+{
+public:
+       AudioBuffer(size_t capacity)
+               : Buffer(DataType::AUDIO, capacity)
+               , _data(NULL)
+       {
+               _size = capacity; // For audio buffers, size = capacity (always)
+#ifdef NO_POSIX_MEMALIGN
+               _data =  (Sample *) malloc(sizeof(Sample) * capacity);
+#else
+               posix_memalign((void**)_data, 16, sizeof(Sample) * capacity);
+#endif 
+               assert(_data);
+               memset(_data, 0, sizeof(Sample) * capacity);
+       }
+
+       const Sample* data() const { return _data; }
+       Sample*       data()       { return _data; }
+
+private:
+       // These are undefined (prevent copies)
+       AudioBuffer(const AudioBuffer& copy);            
+       AudioBuffer& operator=(const AudioBuffer& copy);
+
+       Sample* _data; ///< Actual buffer contents
+};
+
+
+} // namespace ARDOUR
+
+#endif // __ardour_buffer_h__
index 60b5e8a2c3d8efa1eba5a627e8b5fc330b158756..dd689e9a2d350dae6823a419c313a7977aadd17f 100644 (file)
@@ -27,8 +27,9 @@
 #include <sys/types.h>
 #include <string>
 
+#include <pbd/stateful.h> 
+
 #include <ardour/types.h>
-#include <ardour/stateful.h>
 #include <ardour/utils.h>
 #include <ardour/configuration_variable.h>
 
@@ -98,6 +99,6 @@ class Configuration : public Stateful
 extern Configuration *Config;
 extern gain_t speed_quietning; /* see comment in configuration.cc */
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 #endif /* __ardour_configuration_h__ */
index 899bffc06ab1e027605d5c745afe5c307d3f6ef5..da4d4e26840524c8988a8c9afd7a47bf42058cc1 100644 (file)
@@ -25,7 +25,7 @@
 #include <string>
 #include <sigc++/signal.h>
 #include <glibmm/thread.h>
-#include <ardour/stateful.h>
+#include <pbd/stateful.h> 
 
 using std::vector;
 using std::string;
index 03b21a299cdb5e54f81f6920373dc7183bcf2602..8eda7a4555b83a648faa3b1aa3f68f3f40dada50 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <glibmm/thread.h>
 
-#include <ardour/stateful.h>
+#include <pbd/stateful.h> 
 
 namespace ARDOUR {
 
@@ -23,6 +23,7 @@ struct ControlProtocolInfo {
     std::string path;
     bool requested;
     bool mandatory;
+    XMLNode* state;
 };
 
  class ControlProtocolManager : public sigc::trackable, public Stateful
index ede060e1cb361b9407f3777e6ee29b010e7dcc4f..7f8a43cfe1aa76822059c78e46b7ca345dec9af8 100644 (file)
@@ -76,7 +76,7 @@ class Curve : public AutomationList
 
 };
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 extern "C" {
        void curve_get_vector_from_c (void *arg, double, double, float*, int32_t);
diff --git a/libs/ardour/ardour/data_type.h b/libs/ardour/ardour/data_type.h
new file mode 100644 (file)
index 0000000..d49ed10
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+    Copyright (C) 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 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.
+*/
+
+#ifndef __ardour_data_type_h__
+#define __ardour_data_type_h__
+
+#include <jack/jack.h>
+
+namespace ARDOUR {
+
+class DataType
+{
+public:
+       enum Symbol {
+               NIL = 0,
+               AUDIO,
+               MIDI
+       };
+
+       DataType(const Symbol& symbol)
+       : _symbol(symbol)
+       {}
+
+       /** Construct from a string (Used for loading from XML) */
+       DataType(const string& str) {
+               if (str == "audio")
+                       _symbol = AUDIO;
+               //else if (str == "midi")
+               //      _symbol = MIDI;
+               else
+                       _symbol = NIL;
+       }
+
+       bool operator==(const Symbol symbol) { return _symbol == symbol; }
+       bool operator!=(const Symbol symbol) { return _symbol != symbol; }
+
+       /** Get the Jack type this DataType corresponds to */
+       const char* to_jack_type() {
+               switch (_symbol) {
+                       case AUDIO: return JACK_DEFAULT_AUDIO_TYPE;
+                       //case MIDI:  return JACK_DEFAULT_MIDI_TYPE;
+                       default:    return "";
+               }
+       }
+       
+       /** Inverse of the from-string constructor */
+       const char* to_string() {
+               switch (_symbol) {
+                       case AUDIO: return "audio";
+                       //case MIDI:  return "midi";
+                       default:    return "unknown"; // reeeally shouldn't ever happen
+               }
+       }
+
+private:
+       Symbol _symbol;
+};
+
+
+
+} // namespace ARDOUR
+
+#endif // __ardour_data_type_h__
+
index 2d10528ac888b5f61c0b301681e8a657c572c3f8..5b773898c35c004de70ec2b820e2add008f3fc93 100644 (file)
@@ -34,6 +34,8 @@ class DestructiveFileSource : public SndFileSource {
        DestructiveFileSource (std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
                               Flag flags = AudioFileSource::Flag (AudioFileSource::Writable));
 
+       DestructiveFileSource (std::string path, Flag flags);
+
        DestructiveFileSource (const XMLNode&);
        ~DestructiveFileSource ();
 
@@ -49,6 +51,8 @@ class DestructiveFileSource : public SndFileSource {
   protected:
        jack_nframes_t write_unlocked (Sample *src, jack_nframes_t cnt, char * workbuf);
 
+       virtual void handle_header_position_change ();
+
   private:
        static jack_nframes_t xfade_frames;
        static gain_t* out_coefficient;
@@ -60,6 +64,7 @@ class DestructiveFileSource : public SndFileSource {
        jack_nframes_t file_pos; // unit is frames
        Sample*        xfade_buf;
 
+       void init ();
        jack_nframes_t crossfade (Sample* data, jack_nframes_t cnt, int dir, char * workbuf);
        void set_timeline_position (jack_nframes_t);
 };
diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h
new file mode 100644 (file)
index 0000000..ebce516
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+    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
+    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: diskstream.h 579 2006-06-12 19:56:37Z essej $
+*/
+
+#ifndef __ardour_diskstream_h__
+#define __ardour_diskstream_h__
+
+#include <sigc++/signal.h>
+
+#include <cmath>
+#include <string>
+#include <queue>
+#include <map>
+#include <vector>
+
+#include <time.h>
+
+#include <pbd/fastlog.h>
+#include <pbd/ringbufferNPT.h>
+#include <pbd/stateful.h>
+
+#include <ardour/ardour.h>
+#include <ardour/configuration.h>
+#include <ardour/session.h>
+#include <ardour/route_group.h>
+#include <ardour/route.h>
+#include <ardour/port.h>
+#include <ardour/utils.h>
+
+
+struct tm;
+
+namespace ARDOUR {
+
+class AudioEngine;
+class Send;
+class Session;
+class Playlist;
+class IO;
+
+class Diskstream : public Stateful, public sigc::trackable
+{      
+  public:
+       enum Flag {
+               Recordable = 0x1,
+               Hidden = 0x2,
+               Destructive = 0x4
+       };
+
+       string      name () const { return _name; }
+       virtual int set_name (string str);
+
+       ARDOUR::IO* io() const { return _io; }
+       void set_io (ARDOUR::IO& io);
+
+       virtual Diskstream& ref() { _refcnt++; return *this; }
+       void     unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
+       uint32_t refcnt() const { return _refcnt; }
+
+       virtual float playback_buffer_load() const = 0;
+       virtual float capture_buffer_load() const = 0;
+
+       void set_flag (Flag f)   { _flags |= f; }
+       void unset_flag (Flag f) { _flags &= ~f; }
+
+       AlignStyle alignment_style() const { return _alignment_style; }
+       void       set_align_style (AlignStyle);
+       void       set_persistent_align_style (AlignStyle a) { _persistent_alignment_style = a; }
+       
+       jack_nframes_t roll_delay() const { return _roll_delay; }
+       void           set_roll_delay (jack_nframes_t);
+
+       bool         record_enabled() const { return g_atomic_int_get (&_record_enabled); }
+       virtual void set_record_enabled (bool yn) = 0;
+
+       bool destructive() const { return _flags & Destructive; }
+       virtual void set_destructive (bool yn);
+
+       const PBD::ID& id()          const { return _id; }
+       bool           hidden()      const { return _flags & Hidden; }
+       bool           recordable()  const { return _flags & Recordable; }
+       bool           reversed()    const { return _actual_speed < 0.0f; }
+       double         speed()       const { return _visible_speed; }
+       
+       virtual void punch_in()  {}
+       virtual void punch_out() {}
+
+       void set_speed (double);
+       void non_realtime_set_speed ();
+
+       Playlist* playlist () { return _playlist; }
+
+       virtual int use_playlist (Playlist *);
+       virtual int use_new_playlist () = 0;
+       virtual int use_copy_playlist () = 0;
+
+       jack_nframes_t current_capture_start() const { return capture_start_frame; }
+       jack_nframes_t current_capture_end()   const { return capture_start_frame + capture_captured; }
+       jack_nframes_t get_capture_start_frame (uint32_t n=0);
+       jack_nframes_t get_captured_frames (uint32_t n=0);
+       
+       uint32_t n_channels() { return _n_channels; }
+
+       static jack_nframes_t disk_io_frames()                      { return disk_io_chunk_frames; }
+       static void           set_disk_io_chunk_frames (uint32_t n) { disk_io_chunk_frames = n; }
+
+       /* Stateful */
+       virtual XMLNode& get_state(void) = 0;
+       virtual int      set_state(const XMLNode& node) = 0;
+       
+       // FIXME: makes sense for all diskstream types?
+       virtual void monitor_input (bool) {}
+
+       jack_nframes_t capture_offset() const { return _capture_offset; }
+       virtual void   set_capture_offset ();
+
+       bool slaved() const      { return _slaved; }
+       void set_slaved(bool yn) { _slaved = yn; }
+
+       int set_loop (Location *loc);
+
+       std::list<Region*>& last_capture_regions () { return _last_capture_regions; }
+
+       void handle_input_change (IOChange, void *src);
+
+       sigc::signal<void>            RecordEnableChanged;
+       sigc::signal<void>            SpeedChanged;
+       sigc::signal<void>            ReverseChanged;
+       sigc::signal<void>            PlaylistChanged;
+       sigc::signal<void>            AlignmentStyleChanged;
+       sigc::signal<void,Location *> LoopSet;
+
+       static sigc::signal<void>                DiskOverrun;
+       static sigc::signal<void>                DiskUnderrun;
+       static sigc::signal<void,Diskstream*>    DiskstreamCreated; // XXX use a ref with sigc2
+       static sigc::signal<void,list<Source*>*> DeleteSources;
+
+  protected:
+       friend class Session;
+
+       Diskstream (Session &, const string& name, Flag f = Recordable);
+       Diskstream (Session &, const XMLNode&);
+
+       /* the Session is the only point of access for these because they require
+        * that the Session is "inactive" while they are called.
+        */
+
+       virtual void set_pending_overwrite (bool) = 0;
+       virtual int  overwrite_existing_buffers () = 0;
+       virtual void set_block_size (jack_nframes_t) = 0;
+       virtual int  internal_playback_seek (jack_nframes_t distance) = 0;
+       virtual int  can_internal_playback_seek (jack_nframes_t distance) = 0;
+       virtual int  rename_write_sources () = 0;
+       virtual void reset_write_sources (bool, bool force = false) = 0;
+       virtual void non_realtime_input_change () = 0;
+
+       uint32_t read_data_count() const { return _read_data_count; }
+       uint32_t write_data_count() const { return _write_data_count; }
+
+  protected:
+       friend class Auditioner;
+       virtual int  seek (jack_nframes_t which_sample, bool complete_refill = false) = 0;
+
+  protected:
+       friend class Track;
+
+       virtual void prepare ();
+       virtual int  process (jack_nframes_t transport_frame, jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input) = 0;
+       virtual bool commit  (jack_nframes_t nframes) = 0;
+       virtual void recover (); /* called if commit will not be called, but process was */
+
+       //private:
+       
+       /** Use unref() to destroy a diskstream */
+       virtual ~Diskstream();
+
+       enum TransitionType {
+               CaptureStart = 0,
+               CaptureEnd
+       };
+       
+       struct CaptureTransition {
+               TransitionType   type;
+               jack_nframes_t   capture_val; ///< The start or end file frame position
+       };
+
+       /* The two central butler operations */
+       virtual int do_flush (Session::RunContext context, bool force = false) = 0;
+       virtual int do_refill () = 0;
+       
+       /** For non-butler contexts (allocates temporary working buffers) */
+       virtual int do_refill_with_alloc() = 0;
+
+       
+       /* XXX fix this redundancy ... */
+
+       virtual void playlist_changed (Change);
+       virtual void playlist_modified ();
+       virtual void playlist_deleted (Playlist*);
+
+       virtual void finish_capture (bool rec_monitors_input) = 0;
+       virtual void transport_stopped (struct tm&, time_t, bool abort) = 0;
+
+       struct CaptureInfo {
+           uint32_t start;
+           uint32_t frames;
+       };
+
+       virtual void init (Flag);
+
+       virtual int use_new_write_source (uint32_t n=0) = 0;
+
+       virtual int find_and_use_playlist (const string&) = 0;
+
+       virtual void allocate_temporary_buffers () = 0;
+
+       virtual bool realtime_set_speed (double, bool global_change);
+
+       std::list<Region*> _last_capture_regions;
+       virtual int use_pending_capture_data (XMLNode& node) = 0;
+
+       virtual void get_input_sources () = 0;
+       virtual void check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record) = 0;
+       virtual void set_align_style_from_io() {}
+       virtual void setup_destructive_playlist () = 0;
+       virtual void use_destructive_playlist () = 0;
+
+       static jack_nframes_t disk_io_chunk_frames;
+       vector<CaptureInfo*>  capture_info;
+       Glib::Mutex           capture_info_lock;
+
+       uint32_t i_am_the_modifier;
+
+       string            _name;
+       ARDOUR::Session&  _session;
+       ARDOUR::IO*       _io;
+       uint32_t          _n_channels;
+       PBD::ID           _id;
+       Playlist*         _playlist;
+
+       mutable gint             _record_enabled;
+       double                   _visible_speed;
+       double                   _actual_speed;
+       /* items needed for speed change logic */
+       bool                     _buffer_reallocation_required;
+       bool                     _seek_required;
+       
+       bool                      force_refill;
+       jack_nframes_t            capture_start_frame;
+       jack_nframes_t            capture_captured;
+       bool                      was_recording;
+       jack_nframes_t            adjust_capture_position;
+       jack_nframes_t           _capture_offset;
+       jack_nframes_t           _roll_delay;
+       jack_nframes_t            first_recordable_frame;
+       jack_nframes_t            last_recordable_frame;
+       int                       last_possibly_recording;
+       AlignStyle               _alignment_style;
+       bool                     _scrubbing;
+       bool                     _slaved;
+       bool                     _processed;
+       Location*                 loop_location;
+       jack_nframes_t            overwrite_frame;
+       off_t                     overwrite_offset;
+       bool                      pending_overwrite;
+       bool                      overwrite_queued;
+       IOChange                  input_change_pending;
+       jack_nframes_t            wrap_buffer_size;
+       jack_nframes_t            speed_buffer_size;
+
+       uint64_t                  last_phase;
+       uint64_t                  phi;
+       
+       jack_nframes_t            file_frame;           
+       jack_nframes_t            playback_sample;
+       jack_nframes_t            playback_distance;
+
+       uint32_t                 _read_data_count;
+       uint32_t                 _write_data_count;
+
+       bool                      in_set_state;
+       AlignStyle               _persistent_alignment_style;
+       bool                      first_input_change;
+
+       Glib::Mutex  state_lock;
+
+       jack_nframes_t scrub_start;
+       jack_nframes_t scrub_buffer_size;
+       jack_nframes_t scrub_offset;
+
+       uint32_t _refcnt;
+
+       sigc::connection ports_created_c;
+       sigc::connection plmod_connection;
+       sigc::connection plstate_connection;
+       sigc::connection plgone_connection;
+       
+       unsigned char _flags;
+};
+
+}; /* namespace ARDOUR */
+
+#endif /* __ardour_diskstream_h__ */
index 9a6da1592bfeb64c3945e257e74ed3fcc05f80e5..075464767e3a7f1f0acd1bdedf5a288c4014f185 100644 (file)
@@ -83,6 +83,6 @@ namespace ARDOUR
            int   status;
 
        };
-};
+} // namespace ARDOUR
 
 #endif /* __ardour_export_h__ */
index 803e16497dd6722eecadb0bd36dc17ea779ac484..a4c4439942ab0b32894331c755510104aab8c32b 100644 (file)
@@ -98,7 +98,7 @@ struct PluginInsertState : public RedirectState
 class PluginInsert : public Insert
 {
   public:
-       PluginInsert (Session&, Plugin&, Placement);
+       PluginInsert (Session&, boost::shared_ptr<Plugin>, Placement);
        PluginInsert (Session&, const XMLNode&);
        PluginInsert (const PluginInsert&);
        ~PluginInsert ();
@@ -133,9 +133,6 @@ class PluginInsert : public Insert
 
        bool is_generator() const;
 
-       void reset_midi_control (MIDI::Port*, bool);
-       void send_all_midi_feedback ();
-
        void set_parameter (uint32_t port, float val);
 
        AutoState get_port_automation_state (uint32_t port);
@@ -144,11 +141,11 @@ class PluginInsert : public Insert
 
        float default_parameter_value (uint32_t which);
 
-       Plugin& plugin(uint32_t num=0) const {
+       boost::shared_ptr<Plugin> plugin(uint32_t num=0) const {
                if (num < _plugins.size()) { 
-                       return *_plugins[num];
+                       return _plugins[num];
                } else {
-                       return *_plugins[0]; // we always have one
+                       return _plugins[0]; // we always have one
                }
        }
 
@@ -166,7 +163,7 @@ class PluginInsert : public Insert
 
        void parameter_changed (uint32_t, float);
        
-       vector<Plugin*> _plugins;
+       vector<boost::shared_ptr<Plugin> > _plugins;
        void automation_run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
        void connect_and_run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset, bool with_auto, jack_nframes_t now = 0);
 
@@ -175,9 +172,9 @@ class PluginInsert : public Insert
        void auto_state_changed (uint32_t which);
        void automation_list_creation_callback (uint32_t, AutomationList&);
 
-       Plugin* plugin_factory (Plugin&);
+       boost::shared_ptr<Plugin> plugin_factory (boost::shared_ptr<Plugin>);
 };
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 #endif /* __ardour_insert_h__ */
index 8ae45fe65c1b42fa28bf1ef931e955f512828f0f..b116a58b97bbd6a32e63be0f0a5cecb56b812b59 100644 (file)
 
 #include <pbd/fastlog.h>
 #include <pbd/undo.h>
-
-#include <midi++/controllable.h>
+#include <pbd/stateful.h> 
+#include <pbd/controllable.h>
 
 #include <ardour/ardour.h>
-#include <ardour/stateful.h>
 #include <ardour/utils.h>
 #include <ardour/state_manager.h>
 #include <ardour/curve.h>
+#include <ardour/types.h>
+#include <ardour/data_type.h>
 
 using std::string;
 using std::vector;
@@ -53,6 +54,11 @@ class Port;
 class Connection;
 class Panner;
 
+/** A collection of input and output ports with connections.
+ *
+ * An IO can contain ports of varying types, making routes/inserts/etc with
+ * varied combinations of types (eg MIDI and audio) possible.
+ */
 class IO : public Stateful, public ARDOUR::StateManager
 {
 
@@ -61,7 +67,8 @@ class IO : public Stateful, public ARDOUR::StateManager
 
        IO (Session&, string name, 
            int input_min = -1, int input_max = -1, 
-           int output_min = -1, int output_max = -1);
+           int output_min = -1, int output_max = -1,
+               DataType default_type = DataType::AUDIO);
 
        virtual ~IO();
 
@@ -75,25 +82,29 @@ class IO : public Stateful, public ARDOUR::StateManager
        void set_output_minimum (int n);
        void set_output_maximum (int n);
 
+       DataType default_type() const { return _default_type; }
+
        const string& name() const { return _name; }
        virtual int set_name (string str, void *src);
        
        virtual void silence  (jack_nframes_t, jack_nframes_t offset);
 
+       // These should be moved in to a separate object that manipulates an IO
+       
        void pan (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset, gain_t gain_coeff);
        void pan_automated (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t start_frame, jack_nframes_t end_frame, 
                            jack_nframes_t nframes, jack_nframes_t offset);
        void collect_input  (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
-       void deliver_output (vector<Sample *>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
-       void deliver_output_no_pan (vector<Sample *>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
+       void deliver_output (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
+       void deliver_output_no_pan (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
        void just_meter_input (jack_nframes_t start_frame, jack_nframes_t end_frame, 
                               jack_nframes_t nframes, jack_nframes_t offset);
 
        virtual uint32_t n_process_buffers () { return 0; }
 
        virtual void   set_gain (gain_t g, void *src);
-       void   inc_gain (gain_t delta, void *src);
-       gain_t         gain () const                      { return _desired_gain; }
+       void           inc_gain (gain_t delta, void *src);
+       gain_t         gain () const { return _desired_gain; }
        virtual gain_t effective_gain () const;
 
        Panner& panner() { return *_panner; }
@@ -106,8 +117,8 @@ class IO : public Stateful, public ARDOUR::StateManager
        Connection *input_connection() const { return _input_connection; }
        Connection *output_connection() const { return _output_connection; }
 
-       int add_input_port (string source, void *src);
-       int add_output_port (string destination, void *src);
+       int add_input_port (string source, void *src, DataType type = DataType::NIL);
+       int add_output_port (string destination, void *src, DataType type = DataType::NIL);
 
        int remove_input_port (Port *, void *src);
        int remove_output_port (Port *, void *src);
@@ -177,25 +188,10 @@ class IO : public Stateful, public ARDOUR::StateManager
        static sigc::signal<void,uint32_t> MoreOutputs;
        static sigc::signal<int> PortsCreated;
 
-       /* MIDI control */
-
-       void set_midi_to_gain_function (gain_t (*function)(double val)) {
-               _midi_gain_control.midi_to_gain = function;
-       }
-
-       void set_gain_to_midi_function (double (*function)(gain_t gain)) {
-               _midi_gain_control.gain_to_midi = function;
-       }
-
-       MIDI::Controllable& midi_gain_control() {
-               return _midi_gain_control;
+       PBD::Controllable& gain_control() {
+               return _gain_control;
        }
 
-       virtual void reset_midi_control (MIDI::Port*, bool on);
-
-       virtual void send_all_midi_feedback ();
-       virtual MIDI::byte* write_midi_feedback (MIDI::byte*, int32_t& bufsize);
-       
        /* Peak metering */
 
        float peak_input_power (uint32_t n) { 
@@ -257,7 +253,7 @@ public:
        void start_pan_touch (uint32_t which);
        void end_pan_touch (uint32_t which);
 
-       id_t id() const { return _id; }
+       const PBD::ID& id() const { return _id; }
 
        void defer_pan_reset ();
        void allow_pan_reset ();
@@ -286,9 +282,10 @@ public:
        string              _name;
        Connection*         _input_connection;
        Connection*         _output_connection;
-       id_t                _id;
+       PBD::ID             _id;
        bool                 no_panner_reset;
        XMLNode*             deferred_state;
+       DataType        _default_type;
 
        virtual void set_deferred_state() {}
 
@@ -300,31 +297,22 @@ public:
        static void apply_declick (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, 
                                   gain_t initial, gain_t target, bool invert_polarity);
 
-       struct MIDIGainControl : public MIDI::Controllable {
-           MIDIGainControl (IO&, MIDI::Port *);
-           void set_value (float);
-
-           void send_feedback (gain_t);
-           MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, gain_t val, bool force = false);
-
+       struct GainControllable : public PBD::Controllable {
+           GainControllable (IO& i) : io (i) {}
+        
+           void set_value (float val);
+           float get_value (void) const;
+   
            IO& io;
-           bool setting;
-           MIDI::byte last_written;
-
-           gain_t (*midi_to_gain) (double val);
-           double (*gain_to_midi) (gain_t gain);
        };
 
-       MIDIGainControl _midi_gain_control;
+       GainControllable _gain_control;
 
        /* state management */
 
        Change               restore_state (State&);
        StateManager::State* state_factory (std::string why) const;
 
-       bool get_midi_node_info (XMLNode * node, MIDI::eventType & ev, MIDI::channel_t & chan, MIDI::byte & additional);
-       bool set_midi_node_info (XMLNode * node, MIDI::eventType ev, MIDI::channel_t chan, MIDI::byte additional);
-       
        /* automation */
 
        jack_nframes_t last_automation_snapshot;
@@ -406,6 +394,6 @@ public:
        int32_t find_output_port_hole ();
 };
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 #endif /*__ardour_io_h__ */
index 2451953ce569363345a475fdd955bd2094fe2772..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
 #include <string>
 #include <dlfcn.h>
 
-#include <midi++/controllable.h>
 #include <sigc++/signal.h>
 
+#include <pbd/stateful.h> 
+
 #include <jack/types.h>
 #include <ardour/ladspa.h>
-#include <ardour/stateful.h>
 #include <ardour/plugin_state.h>
 #include <ardour/plugin.h>
 #include <ardour/ladspa_plugin.h>
@@ -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 75f4c5d12aa83b0fac9033263487fdbafdd2a0c7..30c02a80a1eaa0802f7937f9a9af1e0c89cf7083 100644 (file)
 #include <glibmm/thread.h>
 
 #include <pbd/undo.h>
+#include <pbd/stateful.h> 
 
-#include "ardour.h"
-#include "stateful.h"
-#include "state_manager.h"
+#include <ardour/ardour.h>
+#include <ardour/state_manager.h>
 
 using std::string;
 
@@ -199,6 +199,6 @@ class Locations : public Stateful, public StateManager
        StateManager::State* state_factory (std::string why) const;
 };
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 #endif /* __ardour_location_h__ */
index e65be55772027addf2ef2ed0747b187b743a3178..ac60a10fd79e27a3b48c712f58a3f0e55fa83d14 100644 (file)
@@ -126,7 +126,7 @@ class LogCurveOut : public LogCurve
 
 };
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 #endif /* __ardour_logcurve_h__ */
 
index 91bb816181b1950f79fbcd92c2b1fa6b6a8071ac..87b71e73ffb12c3176ec199d9c2ecbe9068ea475 100644 (file)
@@ -24,7 +24,7 @@
 #include <string>
 #include <list>
 
-#include <ardour/stateful.h>
+#include <pbd/stateful.h> 
 
 class XMLNode;
 
index 806f350e03b915b4fe054531d932c7fa40fea2eb..75c59eb9241da74ac0d1430edabf10fd01445579 100644 (file)
 #include <iostream>
 #include <sigc++/signal.h>
 
-#include <midi++/controllable.h>
+#include <pbd/stateful.h> 
+#include <pbd/controllable.h>
 
 #include <ardour/types.h>
-#include <ardour/stateful.h>
 #include <ardour/curve.h>
 
 using std::istream;
@@ -75,24 +75,7 @@ class StreamPanner : public sigc::trackable, public Stateful
        virtual void set_automation_state (AutoState) = 0;
        virtual void set_automation_style (AutoStyle) = 0;
        
-       /* MIDI control */
-
-       struct MIDIControl : public MIDI::Controllable {
-           MIDIControl (StreamPanner&, MIDI::Port *);
-           void set_value (float);
-           void send_feedback (gain_t);
-           MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, gain_t val, bool force = false);
-
-           pan_t (*midi_to_pan)(double val);
-           double (*pan_to_midi)(pan_t p);
-
-           StreamPanner& sp;
-           bool setting;
-           gain_t last_written;
-       };
-
-       MIDIControl& midi_control()  { return _midi_control; }
-       void reset_midi_control (MIDI::Port *, bool);
+       PBD::Controllable& control()  { return _control; }
        
        /* XXX this is wrong. for multi-dimensional panners, there
           must surely be more than 1 automation curve.
@@ -100,7 +83,6 @@ class StreamPanner : public sigc::trackable, public Stateful
 
        virtual Curve& automation() = 0;
 
-
        virtual int load (istream&, string path, uint32_t&) = 0;
 
        virtual int save (ostream&) const = 0;
@@ -130,12 +112,20 @@ class StreamPanner : public sigc::trackable, public Stateful
        float effective_z;
 
        bool             _muted;
-       MIDIControl _midi_control;
 
-       void add_state (XMLNode&);
-       bool get_midi_node_info (XMLNode * node, MIDI::eventType & ev, MIDI::channel_t & chan, MIDI::byte & additional);
-       bool set_midi_node_info (XMLNode * node, MIDI::eventType ev, MIDI::channel_t chan, MIDI::byte additional);
+       struct PanControllable : public PBD::Controllable {
+           PanControllable (StreamPanner& p) : panner (p) {}
+           
+           StreamPanner& panner;
+           
+           void set_value (float);
+           float get_value (void) const;
+           bool can_send_feedback() const;
+       };
 
+       PanControllable  _control;
+
+       void add_state (XMLNode&);
        virtual void update () = 0;
 };
 
@@ -290,10 +280,6 @@ class Panner : public std::vector<StreamPanner*>, public Stateful, public sigc::
        std::vector<Output> outputs;
        Session& session() const { return _session; }
 
-       void reset_midi_control (MIDI::Port *, bool);
-       void send_all_midi_feedback ();
-       MIDI::byte* write_midi_feedback (MIDI::byte*, int32_t& bufsize);
-
        enum LinkDirection {
                SameDirection,
                OppositeDirection
@@ -326,6 +312,6 @@ class Panner : public std::vector<StreamPanner*>, public Stateful, public sigc::
        static float current_automation_version_number;
 };
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 #endif /*__ardour_panner_h__ */
index c653c8502e07ded5ec6db448f072d2a2a6b44ea7..9fb5b0eb2b5b2baf97a6bb054f51754027695aa9 100644 (file)
 #include <glib.h>
 
 #include <sigc++/signal.h>
+
 #include <pbd/undo.h>
+#include <pbd/stateful.h> 
 
 #include <ardour/ardour.h>
 #include <ardour/crossfade_compare.h>
 #include <ardour/location.h>
-#include <ardour/stateful.h>
 #include <ardour/state_manager.h>
 
 namespace ARDOUR  {
@@ -53,7 +54,6 @@ class Playlist : public Stateful, public StateManager {
        Playlist (const Playlist&, string name, bool hidden = false);
        Playlist (const Playlist&, jack_nframes_t start, jack_nframes_t cnt, string name, bool hidden = false);
 
-       virtual jack_nframes_t read (Sample *dst, Sample *mixdown, float *gain_buffer, char * workbuf, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n=0) = 0;
        virtual void clear (bool with_delete = false, bool with_save = true);
        virtual void dump () const;
        virtual UndoAction get_memento() const = 0;
@@ -80,13 +80,15 @@ class Playlist : public Stateful, public StateManager {
 
        void add_region (const Region&, jack_nframes_t position, float times = 1, bool with_save = true);
        void remove_region (Region *);
+       void get_equivalent_regions (const Region&, std::vector<Region*>&);
+       void get_region_list_equivalent_regions (const Region&, std::vector<Region*>&);
        void replace_region (Region& old, Region& newr, jack_nframes_t pos);
        void split_region (Region&, jack_nframes_t position);
        void partition (jack_nframes_t start, jack_nframes_t end, bool just_top_level);
        void duplicate (Region&, jack_nframes_t position, float times);
        void nudge_after (jack_nframes_t start, jack_nframes_t distance, bool forwards);
 
-       Region* find_region (id_t) const;
+       Region* find_region (const PBD::ID&) const;
 
        Playlist* cut  (list<AudioRange>&, bool result_is_hidden = true);
        Playlist* copy (list<AudioRange>&, bool result_is_hidden = true);
@@ -107,16 +109,15 @@ class Playlist : public Stateful, public StateManager {
        int set_state (const XMLNode&);
        XMLNode& get_template ();
 
-       sigc::signal<void,Region *> RegionAdded;
-       sigc::signal<void,Region *> RegionRemoved;
-
+       sigc::signal<void,Region *>       RegionAdded;
+       sigc::signal<void,Region *>       RegionRemoved;
        sigc::signal<void,Playlist*,bool> InUse;
-       sigc::signal<void>            Modified;
-       sigc::signal<void>            NameChanged;
-       sigc::signal<void>            LengthChanged;
-       sigc::signal<void>            LayeringChanged;
-       sigc::signal<void,Playlist *> GoingAway;
-       sigc::signal<void>            StatePushed;
+       sigc::signal<void>                Modified;
+       sigc::signal<void>                NameChanged;
+       sigc::signal<void>                LengthChanged;
+       sigc::signal<void>                LayeringChanged;
+       sigc::signal<void,Playlist *>     GoingAway;
+       sigc::signal<void>                StatePushed;
 
        static sigc::signal<void,Playlist*> PlaylistCreated;
 
@@ -135,8 +136,8 @@ class Playlist : public Stateful, public StateManager {
 
        Session& session() { return _session; }
 
-       id_t get_orig_diskstream_id () const { return _orig_diskstream_id; }
-       void set_orig_diskstream_id (id_t did) { _orig_diskstream_id = did; }  
+       const PBD::ID& get_orig_diskstream_id () const { return _orig_diskstream_id; }
+       void set_orig_diskstream_id (const PBD::ID& did) { _orig_diskstream_id = did; }  
 
        /* destructive editing */
        
@@ -190,7 +191,7 @@ class Playlist : public Stateful, public StateManager {
        bool            _frozen;
        uint32_t         subcnt;
        uint32_t        _read_data_count;
-       id_t            _orig_diskstream_id;
+       PBD::ID         _orig_diskstream_id;
        uint64_t         layer_op_counter;
        jack_nframes_t   freeze_length;
 
index 211b00d0bbe43cb786de62218d4c9454f0e6d589..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
     $Id$
 */
 
-#ifndef __ardour_ladspa_h__
-#define __ardour_ladspa_h__
+#ifndef __ardour_plugin_h__
+#define __ardour_plugin_h__
 
-#include <midi++/controllable.h>
+#include <boost/shared_ptr.hpp>
 #include <sigc++/signal.h>
 
+#include <pbd/stateful.h> 
+#include <pbd/controllable.h>
+
 #include <jack/types.h>
 #include <ardour/types.h>
-#include <ardour/stateful.h>
 #include <ardour/plugin_state.h>
 #include <ardour/cycles.h>
 
@@ -44,6 +46,9 @@ namespace ARDOUR {
 class AudioEngine;
 class Session;
 
+class Plugin;
+typedef boost::shared_ptr<Plugin> PluginPtr;
+
 class PluginInfo {
   public:
        enum Type {
@@ -52,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;
@@ -65,19 +71,24 @@ class PluginInfo {
 
        long unique_id;
 
-  private:
+       virtual PluginPtr load (Session& session) = 0;
+
+  protected:
        friend class PluginManager;
        string path;
        uint32_t index;
 };
 
+typedef boost::shared_ptr<PluginInfo> PluginInfoPtr;
+typedef std::list<PluginInfoPtr> PluginInfoList;
+
 class Plugin : public Stateful, public sigc::trackable
 
 {
   public:
        Plugin (ARDOUR::AudioEngine&, ARDOUR::Session&);
        Plugin (const Plugin&);
-       ~Plugin ();
+       virtual ~Plugin ();
        
        struct ParameterDescriptor {
 
@@ -136,13 +147,10 @@ class Plugin : public Stateful, public sigc::trackable
        sigc::signal<void,uint32_t,float> ParameterChanged;
        sigc::signal<void,Plugin *> GoingAway;
        
-       void reset_midi_control (MIDI::Port*, bool);
-       void send_all_midi_feedback ();
-       MIDI::byte* write_midi_feedback (MIDI::byte*, int32_t& bufsize);
-       MIDI::Controllable *get_nth_midi_control (uint32_t);
+       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; }
@@ -153,21 +161,19 @@ 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. */);
 
-       void setup_midi_controls ();
+       void setup_controls ();
 
-
-       struct MIDIPortControl : public MIDI::Controllable {
-           MIDIPortControl (Plugin&, uint32_t abs_port_id, MIDI::Port *,
-                            float lower, float upper, bool toggled, bool logarithmic);
+       struct PortControllable : public PBD::Controllable {
+           PortControllable (Plugin&, uint32_t abs_port_id,
+                             float lower, float upper, bool toggled, bool logarithmic);
 
            void set_value (float);
-           void send_feedback (float);
-           MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, float val, bool force = false);
+           float get_value () const;
 
            Plugin& plugin;
            uint32_t absolute_port;
@@ -176,19 +182,12 @@ class Plugin : public Stateful, public sigc::trackable
            float range;
            bool  toggled;
            bool  logarithmic;
-
-           bool setting;
-           float last_written;
        };
 
-       vector<MIDIPortControl*> midi_controls;
-
-       
+       vector<PortControllable*> controls;
 };
 
-/* this is actually defined in plugin_manager.cc */
-
-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 1a07c67c8dd18eeeb75d2aec6aee2e4d6dbae728..8e6c0bd1c780ff3d4d1e5b8f822e2b580588d9ef 100644 (file)
@@ -6,34 +6,33 @@
 #include <string>
 
 #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 ();
 
-       std::list<PluginInfo*> &vst_plugin_info () { return _vst_plugin_info; }
-       std::list<PluginInfo*> &ladspa_plugin_info () { return _ladspa_plugin_info; }
+       ARDOUR::PluginInfoList &vst_plugin_info () { return _vst_plugin_info; }
+       ARDOUR::PluginInfoList &ladspa_plugin_info () { return _ladspa_plugin_info; }
+
        void refresh ();
 
        int add_ladspa_directory (std::string dirpath);
        int add_vst_directory (std::string dirpath);
 
-       Plugin *load (ARDOUR::Session& s, PluginInfo* info);
-
        static PluginManager* the_manager() { return _manager; }
 
   private:
-       ARDOUR::AudioEngine&   _engine;
-       std::list<PluginInfo*> _vst_plugin_info;
-       std::list<PluginInfo*> _ladspa_plugin_info;
+       ARDOUR::PluginInfoList _vst_plugin_info;
+       ARDOUR::PluginInfoList _ladspa_plugin_info;
        std::map<uint32_t, std::string> rdf_type;
 
        std::string ladspa_path;
@@ -61,3 +60,4 @@ class PluginManager {
 } /* namespace ARDOUR */
 
 #endif /* __ardour_plugin_manager_h__ */
+
index ff9c25e1c4e0c4f0cd06da2f3c368da85439e332..86c99cb7e3e24533f326a1d1b2d2c5691c70a2f7 100644 (file)
@@ -33,24 +33,24 @@ class AudioEngine;
 class Port : public sigc::trackable {
    public:
        virtual ~Port() { 
-               free (port);
+               free (_port);
        }
 
        Sample *get_buffer (jack_nframes_t nframes) {
                if (_flags & JackPortIsOutput) {
                        return _buffer;
                } else {
-                       return (Sample *) jack_port_get_buffer (port, nframes);
+                       return (Sample *) jack_port_get_buffer (_port, nframes);
                }
        }
 
        void reset_buffer () {
                if (_flags & JackPortIsOutput) {
-                       _buffer = (Sample *) jack_port_get_buffer (port, 0);
+                       _buffer = (Sample *) jack_port_get_buffer (_port, 0);
                } else {
                        _buffer = 0; /* catch illegal attempts to use it */
                }
-               silent = false;
+               _silent = false;
        }
 
        std::string name() { 
@@ -58,7 +58,7 @@ class Port : public sigc::trackable {
        }
 
        std::string short_name() { 
-               return jack_port_short_name (port);
+               return jack_port_short_name (_port);
        }
        
        int set_name (std::string str);
@@ -68,7 +68,7 @@ class Port : public sigc::trackable {
        }
 
        bool is_mine (jack_client_t *client) { 
-               return jack_port_is_mine (client, port);
+               return jack_port_is_mine (client, _port);
        }
 
        const char* type() const {
@@ -76,21 +76,21 @@ class Port : public sigc::trackable {
        }
 
        int connected () const {
-               return jack_port_connected (port);
+               return jack_port_connected (_port);
        }
        
        bool connected_to (const std::string& portname) const {
-               return jack_port_connected_to (port, portname.c_str());
+               return jack_port_connected_to (_port, portname.c_str());
        }
 
        const char ** get_connections () const {
-               return jack_port_get_connections (port);
+               return jack_port_get_connections (_port);
        }
 
        void reset_overs () {
                _short_overs = 0;
                _long_overs = 0;
-               overlen = 0;
+               _overlen = 0;
        }
 
        void reset_peak_meter () {
@@ -103,18 +103,18 @@ class Port : public sigc::trackable {
        }
 
        void enable_metering() {
-               metering++;
+               _metering++;
        }
        
        void disable_metering () {
-               if (metering) { metering--; }
+               if (_metering) { _metering--; }
        }
 
-       float    peak_db() const { return _peak_db; }
+       float                       peak_db() const { return _peak_db; }
        jack_default_audio_sample_t peak()    const { return _peak; }
 
        uint32_t short_overs () const { return _short_overs; }
-       uint32_t long_overs () const { return _long_overs; }
+       uint32_t long_overs ()  const { return _long_overs; }
        
        static void set_short_over_length (jack_nframes_t);
        static void set_long_over_length (jack_nframes_t);
@@ -128,7 +128,7 @@ class Port : public sigc::trackable {
        }
        
        bool monitoring_input () const {
-               return jack_port_monitoring_input (port);
+               return jack_port_monitoring_input (_port);
        }
 
        bool can_monitor () const {
@@ -136,30 +136,29 @@ class Port : public sigc::trackable {
        }
        
        void ensure_monitor_input (bool yn) {
-               jack_port_request_monitor (port, yn);
+               jack_port_request_monitor (_port, yn);
        }
        
        void request_monitor_input (bool yn) {
-               jack_port_request_monitor (port, yn);
+               jack_port_request_monitor (_port, yn);
        }
 
        jack_nframes_t latency () const {
-               return jack_port_get_latency (port);
+               return jack_port_get_latency (_port);
        }
 
        void set_latency (jack_nframes_t nframes) {
-               jack_port_set_latency (port, nframes);
+               jack_port_set_latency (_port, nframes);
        }
 
        sigc::signal<void,bool> MonitorInputChanged;
        sigc::signal<void,bool> ClockSyncChanged;
 
-       bool is_silent() const { return silent; }
+       bool is_silent() const { return _silent; }
 
+       /** Assumes that the port is an audio output port */
        void silence (jack_nframes_t nframes, jack_nframes_t offset) {
-               /* assumes that the port is an output port */
-
-               if (!silent) {
+               if (!_silent) {
                        memset (_buffer + offset, 0, sizeof (Sample) * nframes);
                        if (offset == 0) {
                                /* XXX this isn't really true, but i am not sure
@@ -167,13 +166,13 @@ class Port : public sigc::trackable {
                                   want to set it true when the entire port
                                   buffer has been overrwritten.
                                */
-                               silent = true;
+                               _silent = true;
                        }
                }
        }
        
        void mark_silence (bool yn) {
-               silent = yn;
+               _silent = yn;
        }
 
   private:
@@ -184,7 +183,7 @@ class Port : public sigc::trackable {
        
        /* engine isn't supposed to below here */
 
-       Sample       *_buffer;
+       Sample *_buffer;
 
        /* cache these 3 from JACK so that we can
           access them for reconnecting.
@@ -194,20 +193,20 @@ class Port : public sigc::trackable {
        std::string   _type;
        std::string   _name;
 
-       bool           last_monitor : 1;
-       bool           silent : 1;
-       jack_port_t   *port;
-       jack_nframes_t      overlen;
-       jack_default_audio_sample_t      _peak;
-       float         _peak_db;
-       uint32_t _short_overs;
-       uint32_t _long_overs;
-       unsigned short  metering;
+       bool                         _last_monitor : 1;
+       bool                         _silent : 1;
+       jack_port_t                 *_port;
+       jack_nframes_t               _overlen;
+       jack_default_audio_sample_t  _peak;
+       float                        _peak_db;
+       uint32_t                     _short_overs;
+       uint32_t                     _long_overs;
+       unsigned short               _metering;
        
-       static jack_nframes_t long_over_length;
-       static jack_nframes_t short_over_length;
+       static jack_nframes_t        _long_over_length;
+       static jack_nframes_t        _short_over_length;
 };
  
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 #endif /* __ardour_port_h__ */
index ede55a1d80649ff8d12d67a1c6b4c35d41ccfe69..658cab5d3b509e633bbb29f24b11988771829e67 100644 (file)
@@ -25,6 +25,7 @@
 #include <vector>
 #include <set>
 #include <map>
+#include <boost/shared_ptr.hpp>
 #include <sigc++/signal.h>
 
 #include <glibmm/thread.h>
@@ -64,7 +65,7 @@ class Redirect : public IO
        Redirect (const Redirect&);
        virtual ~Redirect ();
 
-       static Redirect *clone (const Redirect&);
+       static boost::shared_ptr<Redirect> clone (boost::shared_ptr<const Redirect>);
 
        bool active () const { return _active; }
        void set_active (bool yn, void *src);
@@ -148,6 +149,6 @@ class Redirect : public IO
        void* _gui;  /* generic, we don't know or care what this is */
 };
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 #endif /* __ardour_redirect_h__ */
index aae776625e6c45703c99fa8b8b9a3d02461b6b70..3773a3b893fe21a52c03d2aa36a4cddebdb8dc7e 100644 (file)
@@ -24,7 +24,6 @@
 #include <pbd/undo.h>
 
 #include <ardour/ardour.h>
-#include <ardour/logcurve.h>
 #include <ardour/state_manager.h>
 
 class XMLNode;
@@ -36,22 +35,22 @@ class Source;
 
 enum RegionEditState {
        EditChangesNothing = 0,
-       EditChangesName = 1,
-       EditChangesID = 2
+       EditChangesName    = 1,
+       EditChangesID      = 2
 };
 
-struct RegionState : public StateManager::State {
-
-    RegionState (std::string why) : StateManager::State (why) {}
-    
-    jack_nframes_t      _start;
-    jack_nframes_t      _length;
-    jack_nframes_t      _position;
-    uint32_t        _flags;
-    jack_nframes_t      _sync_position;
-    layer_t            _layer;
-    string              _name;        
-    mutable RegionEditState _first_edit;
+struct RegionState : public StateManager::State
+{
+       RegionState (std::string why) : StateManager::State (why) {}
+
+       jack_nframes_t          _start;
+       jack_nframes_t          _length;
+       jack_nframes_t          _position;
+       uint32_t                _flags;
+       jack_nframes_t          _sync_position;
+       layer_t                 _layer;
+       string                  _name;        
+       mutable RegionEditState _first_edit;
 };
 
 class Region : public Stateful, public StateManager
@@ -95,9 +94,9 @@ class Region : public Stateful, public StateManager
        Region (const Region&, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t = 0, Flag flags = DefaultFlags);
        Region (const Region&);
        Region (const XMLNode&);
-       ~Region();
+       virtual ~Region();
 
-       ARDOUR::id_t id() const { return _id; }
+       const PBD::ID& id() const { return _id; }
 
        /* Note: changing the name of a Region does not constitute an edit */
 
@@ -105,9 +104,10 @@ class Region : public Stateful, public StateManager
        void set_name (string str);
 
        jack_nframes_t position () const { return _position; }
-       jack_nframes_t start () const { return _start; }
-       jack_nframes_t length() const { return _length; }
-       layer_t layer () const { return _layer; }
+       jack_nframes_t start ()    const { return _start; }
+       jack_nframes_t length()    const { return _length; }
+       layer_t        layer ()    const { return _layer; }
+       
        jack_nframes_t sync_offset(int& dir) const;
        jack_nframes_t sync_position() const;
 
@@ -118,14 +118,13 @@ class Region : public Stateful, public StateManager
        jack_nframes_t first_frame() const { return _position; }
        jack_nframes_t last_frame() const { return _position + _length - 1; }
 
-       bool hidden() const { return _flags & Hidden; }
-       bool muted() const { return _flags & Muted; }
-       bool opaque () const { return _flags & Opaque; }
-       bool envelope_active () const { return _flags & EnvelopeActive; }
-       bool locked() const { return _flags & Locked; }
-       bool automatic() const { return  _flags & Automatic; }
+       bool hidden()     const { return _flags & Hidden; }
+       bool muted()      const { return _flags & Muted; }
+       bool opaque ()    const { return _flags & Opaque; }
+       bool locked()     const { return _flags & Locked; }
+       bool automatic()  const { return _flags & Automatic; }
        bool whole_file() const { return _flags & WholeFile ; }
-       Flag flags() const { return _flags; }
+       Flag flags()      const { return _flags; }
 
        virtual bool should_save_state () const { return !(_flags & DoNotSaveState); };
 
@@ -139,12 +138,14 @@ class Region : public Stateful, public StateManager
        OverlapType coverage (jack_nframes_t start, jack_nframes_t end) const {
                return ARDOUR::coverage (_position, _position + _length - 1, start, end);
        }
-
-       virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, 
-                                       float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, 
-                                       uint32_t chan_n = 0,
-                                       jack_nframes_t read_frames = 0,
-                                       jack_nframes_t skip_frames = 0) const = 0;
+       
+       bool equivalent (const Region&) const;
+       bool size_equivalent (const Region&) const;
+       bool overlap_equivalent (const Region&) const;
+       bool region_list_equivalent (const Region&) const;
+       virtual bool source_equivalent (const Region&) const = 0;
+       
+       virtual bool speed_mismatch (float) const = 0;
 
        /* EDITING OPERATIONS */
 
@@ -173,7 +174,6 @@ class Region : public Stateful, public StateManager
        void set_hidden (bool yn);
        void set_muted (bool yn);
        void set_opaque (bool yn);
-       void set_envelope_active (bool yn);
        void set_locked (bool yn);
 
        virtual uint32_t read_data_count() const { return _read_data_count; }
@@ -189,9 +189,9 @@ class Region : public Stateful, public StateManager
 
        /* serialization */
        
+       XMLNode&         get_state ();
        virtual XMLNode& state (bool);
-       XMLNode& get_state ();
-       int      set_state (const XMLNode&);
+       virtual int      set_state (const XMLNode&);
 
        sigc::signal<void,Region*> GoingAway;
 
@@ -211,23 +211,6 @@ class Region : public Stateful, public StateManager
        void set_last_layer_op (uint64_t when);
 
   protected:
-
-       jack_nframes_t        _start;
-       jack_nframes_t        _length;
-       jack_nframes_t        _position;
-       Flag                  _flags;
-       jack_nframes_t        _sync_position;
-       layer_t               _layer;
-       string                _name;        
-       mutable RegionEditState _first_edit;
-       int                   _frozen;
-       Glib::Mutex              lock;
-       ARDOUR::id_t          _id;
-       ARDOUR::Playlist*     _playlist;
-       mutable uint32_t      _read_data_count; // modified in read()
-       Change                 pending_changed;
-       uint64_t              _last_layer_op; // timestamp
        XMLNode& get_short_state (); /* used only by Session */
 
        /* state management */
@@ -251,6 +234,23 @@ class Region : public Stateful, public StateManager
        virtual bool verify_length (jack_nframes_t) = 0;
        virtual void recompute_at_start () = 0;
        virtual void recompute_at_end () = 0;
+       
+       
+       jack_nframes_t          _start;
+       jack_nframes_t          _length;
+       jack_nframes_t          _position;
+       Flag                     _flags;
+       jack_nframes_t          _sync_position;
+       layer_t                 _layer;
+       string                  _name;        
+       mutable RegionEditState _first_edit;
+       int                     _frozen;
+       Glib::Mutex             lock;
+       PBD::ID                 _id;
+       ARDOUR::Playlist*       _playlist;
+       mutable uint32_t        _read_data_count; // modified in read()
+       Change                   pending_changed;
+       uint64_t                _last_layer_op; // timestamp
 };
 
 } /* namespace ARDOUR */
index 5686dfc9081937c02c6a62d9bbf0db23f39fb5ac..8271c1cf6ab02b3abe20cd791bb235f73b786c91 100644 (file)
 #include <map>
 #include <string>
 
+#include <boost/shared_ptr.hpp>
+
 #include <pbd/fastlog.h>
 #include <glibmm/thread.h>
 #include <pbd/xml++.h>
 #include <pbd/undo.h>
-#include <midi++/controllable.h>
+#include <pbd/stateful.h> 
+#include <pbd/controllable.h>
 
 #include <ardour/ardour.h>
-#include <ardour/stateful.h>
 #include <ardour/io.h>
 #include <ardour/session.h>
 #include <ardour/redirect.h>
+#include <ardour/types.h>
 
 namespace ARDOUR {
 
@@ -56,17 +59,19 @@ class Route : public IO
 {
   protected:
 
-        typedef list<Redirect *> RedirectList;
+        typedef list<boost::shared_ptr<Redirect> > RedirectList;
   public:
 
        enum Flag {
                Hidden = 0x1,
                MasterOut = 0x2,
-               ControlOut = 0x4,
+               ControlOut = 0x4
        };
 
 
-       Route (Session&, std::string name, int input_min, int input_max, int output_min, int output_max, Flag flags = Flag(0));
+       Route (Session&, std::string name, int input_min, int input_max, int output_min, int output_max,
+              Flag flags = Flag(0), DataType default_type = DataType::AUDIO);
+       
        Route (Session&, const XMLNode&);
        virtual ~Route();
 
@@ -138,19 +143,19 @@ class Route : public IO
 
        void flush_redirects ();
 
-       template<class T> void foreach_redirect (T *obj, void (T::*func)(Redirect *)) {
+       template<class T> void foreach_redirect (T *obj, void (T::*func)(boost::shared_ptr<Redirect>)) {
                Glib::RWLock::ReaderLock lm (redirect_lock);
                for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
                        (obj->*func) (*i);
                }
        }
 
-       Redirect *nth_redirect (uint32_t n) {
+       boost::shared_ptr<Redirect> nth_redirect (uint32_t n) {
                Glib::RWLock::ReaderLock lm (redirect_lock);
                RedirectList::iterator i;
                for (i = _redirects.begin(); i != _redirects.end() && n; ++i, --n);
                if (i == _redirects.end()) {
-                       return 0;
+                       return boost::shared_ptr<Redirect> ();
                } else {
                        return *i;
                }
@@ -158,9 +163,9 @@ class Route : public IO
        
        uint32_t max_redirect_outs () const { return redirect_max_outs; }
                
-       int add_redirect (Redirect *, void *src, uint32_t* err_streams = 0);
+       int add_redirect (boost::shared_ptr<Redirect>, void *src, uint32_t* err_streams = 0);
        int add_redirects (const RedirectList&, void *src, uint32_t* err_streams = 0);
-       int remove_redirect (Redirect *, void *src, uint32_t* err_streams = 0);
+       int remove_redirect (boost::shared_ptr<Redirect>, void *src, uint32_t* err_streams = 0);
        int copy_redirects (const Route&, Placement, uint32_t* err_streams = 0);
        int sort_redirects (uint32_t* err_streams = 0);
 
@@ -209,37 +214,31 @@ class Route : public IO
        int set_control_outs (const vector<std::string>& ports);
        IO* control_outs() { return _control_outs; }
 
-       bool feeds (Route *);
-       set<Route *> fed_by;
-
-       struct MIDIToggleControl : public MIDI::Controllable {
-               enum ToggleType {
-                       MuteControl = 0,
-                       SoloControl
-               };
-               
-               MIDIToggleControl (Route&, ToggleType, MIDI::Port *);
-               void set_value (float);
-               void send_feedback (bool);
-               MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force = false);
-
-               Route& route;
-               ToggleType type;
-               bool setting;
-               bool last_written;
+       bool feeds (boost::shared_ptr<Route>);
+       set<boost::shared_ptr<Route> > fed_by;
+
+       struct ToggleControllable : public PBD::Controllable {
+           enum ToggleType {
+                   MuteControl = 0,
+                   SoloControl
+           };
+           
+           ToggleControllable (Route&, ToggleType);
+           void set_value (float);
+           float get_value (void) const;
+
+           Route& route;
+           ToggleType type;
        };
 
-       MIDI::Controllable& midi_solo_control() {
-               return _midi_solo_control;
+       PBD::Controllable& solo_control() {
+               return _solo_control;
        }
-       MIDI::Controllable& midi_mute_control() {
-               return _midi_mute_control;
+
+       PBD::Controllable& mute_control() {
+               return _mute_control;
        }
        
-       virtual void reset_midi_control (MIDI::Port*, bool);
-       virtual void send_all_midi_feedback ();
-       virtual MIDI::byte* write_midi_feedback (MIDI::byte*, int32_t& bufsize);
-
        void automation_snapshot (jack_nframes_t now);
 
        void protect_automation ();
@@ -299,8 +298,8 @@ class Route : public IO
        std::string              _comment;
        bool                     _have_internal_generator;
 
-       MIDIToggleControl _midi_solo_control;
-       MIDIToggleControl _midi_mute_control;
+       ToggleControllable _solo_control;
+       ToggleControllable _mute_control;
        
        void passthru (jack_nframes_t start_frame, jack_nframes_t end_frame, 
                       jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter_inputs);
@@ -342,12 +341,12 @@ class Route : public IO
        /* plugin count handling */
 
        struct InsertCount {
-           ARDOUR::Insert& insert;
+           boost::shared_ptr<ARDOUR::Insert> insert;
            int32_t cnt;
            int32_t in;
            int32_t out;
 
-           InsertCount (ARDOUR::Insert& ins) : insert (ins), cnt (-1) {}
+           InsertCount (boost::shared_ptr<ARDOUR::Insert> ins) : insert (ins), cnt (-1) {}
        };
        
        int32_t apply_some_plugin_counts (std::list<InsertCount>& iclist);
@@ -358,6 +357,6 @@ class Route : public IO
        void redirect_active_proxy (Redirect*, void*);
 };
 
-}; /* namespace ARDOUR*/
+} // namespace ARDOUR
 
 #endif /* __ardour_route_h__ */
index c9f966666f14e5ba3d03b2e97db94c5e4c9ad2cc..e9fad1aa2b66986fe8123bbf2f78a7d287ca6040 100644 (file)
@@ -26,7 +26,7 @@
 #include <string>
 #include <stdint.h>
 #include <sigc++/signal.h>
-#include <ardour/stateful.h>
+#include <pbd/stateful.h> 
 #include <ardour/types.h>
 
 using std::string;
@@ -35,6 +35,7 @@ using std::list;
 namespace ARDOUR {
 
 class Route;
+class Track;
 class AudioTrack;
 class Session;
 
@@ -43,7 +44,7 @@ class RouteGroup : public Stateful, public sigc::trackable {
     enum Flag {
            Relative = 0x1,
            Active = 0x2,
-           Hidden = 0x4,
+           Hidden = 0x4
     };
 
     RouteGroup (Session& s, const string &n, Flag f = Flag(0));
@@ -90,7 +91,7 @@ class RouteGroup : public Stateful, public sigc::trackable {
 
     /* to use these, #include <ardour/route_group_specialized.h> */
 
-    template<class T> void apply (void (AudioTrack::*func)(T, void *), T val, void *src);
+    template<class T> void apply (void (Track::*func)(T, void *), T val, void *src);
 
     /* fills at_set with all members of the group that are AudioTracks */
 
index 0424002dcd5211c841ae7d836c3d480adba653ed..250d3744dfae6b327dec5706a357b383d3e1d1ce 100644 (file)
@@ -7,11 +7,11 @@
 namespace ARDOUR {
 
 template<class T> void 
-RouteGroup::apply (void (AudioTrack::*func)(T, void *), T val, void *src) 
+RouteGroup::apply (void (Track::*func)(T, void *), T val, void *src) 
 {
        for (list<Route *>::iterator i = routes.begin(); i != routes.end(); i++) {
-               AudioTrack *at;
-               if ((at = dynamic_cast<AudioTrack*>(*i)) != 0) {
+               Track *at;
+               if ((at = dynamic_cast<Track*>(*i)) != 0) {
                        (at->*func)(val, this);
                }
        }
index a94318f2a59f8d2b62925fb46936b1dca5a31897..0a068e8af02d4706446c2456224ef0531d1c9d86 100644 (file)
 #include <sigc++/signal.h>
 #include <string>
 
+
+#include <pbd/stateful.h> 
 #include <ardour/ardour.h>
 #include <ardour/audioengine.h>
-
-#include "io.h"
-#include "stateful.h"
-#include "redirect.h"
+#include <ardour/io.h>
+#include <ardour/redirect.h>
 
 namespace ARDOUR {
 
@@ -58,6 +58,6 @@ class Send : public Redirect {
        uint32_t expected_inputs;
 };
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 #endif /* __ardour_send_h__ */
index 7a9e50ae9ba04667031593c75a6f85dc96dc0a59..0c53cc32e76128cb6a38402abce7c66660db7fc9 100644 (file)
 #include <pbd/error.h>
 #include <pbd/undo.h>
 #include <pbd/pool.h>
+#include <pbd/rcu.h>
 
 #include <midi++/types.h>
 #include <midi++/mmc.h>
 
+#include <pbd/stateful.h> 
+
 #include <ardour/ardour.h>
 #include <ardour/configuration.h>
 #include <ardour/location.h>
-#include <ardour/stateful.h>
 #include <ardour/gain.h>
 #include <ardour/io.h>
 
@@ -55,11 +57,16 @@ namespace MIDI {
        class Port;
 }
 
+namespace PBD {
+       class Controllable;
+}
+
 namespace ARDOUR {
 
 class Port;
 class AudioEngine;
 class Slave;
+class Diskstream;      
 class AudioDiskstream; 
 class Route;
 class AuxInput;
@@ -95,9 +102,9 @@ class Session : public sigc::trackable, public Stateful
 
 {
   private:
-       typedef std::pair<Route*,bool> RouteBooleanState;
+       typedef std::pair<boost::shared_ptr<Route>,bool> RouteBooleanState;
        typedef vector<RouteBooleanState> GlobalRouteBooleanState;
-       typedef std::pair<Route*,MeterPoint> RouteMeterState;
+       typedef std::pair<boost::shared_ptr<Route>,MeterPoint> RouteMeterState;
        typedef vector<RouteMeterState> GlobalRouteMeterState;
 
   public:
@@ -110,7 +117,7 @@ class Session : public sigc::trackable, public Stateful
        enum SlaveSource {
                None = 0,
                MTC,
-               JACK,
+               JACK
        };
        
        enum AutoConnectOption {
@@ -141,7 +148,7 @@ class Session : public sigc::trackable, public Stateful
                    */
 
                    StopOnce,
-                   AutoLoop,
+                   AutoLoop
            };
 
            enum Action {
@@ -151,16 +158,17 @@ class Session : public sigc::trackable, public Stateful
                    Clear
            };
 
-           Type                type;
-           Action              action;
-           jack_nframes_t      action_frame;
-           jack_nframes_t      target_frame;
-           float               speed;
+           Type           type;
+           Action         action;
+           jack_nframes_t action_frame;
+           jack_nframes_t target_frame;
+           float          speed;
 
            union {
-               void*                ptr;
-               bool                 yes_or_no;
-               Session::SlaveSource slave;
+                       void*                ptr;
+                       bool                 yes_or_no;
+                       Session::SlaveSource slave;
+                       Route*               route;
            };
 
            list<AudioRange>     audio_range;
@@ -262,52 +270,39 @@ class Session : public sigc::trackable, public Stateful
        vector<Sample*>& get_silent_buffers (uint32_t howmany);
        vector<Sample*>& get_send_buffers () { return _send_buffers; }
 
-       AudioDiskstream    *diskstream_by_id (id_t id);
-       AudioDiskstream    *diskstream_by_name (string name);
+       Diskstream* diskstream_by_id (const PBD::ID& id);
+       Diskstream* diskstream_by_name (string name);
 
        bool have_captured() const { return _have_captured; }
 
        void refill_all_diskstream_buffers ();
        uint32_t diskstream_buffer_size() const { return dstream_buffer_size; }
        
-       /* XXX fix required here when we get new diskstream types *, but
-          not sure of the direction to take this in until then.
-       */
-
-       uint32_t get_next_diskstream_id() const { return n_audio_diskstreams(); }
-       uint32_t n_audio_diskstreams() const;
+       uint32_t get_next_diskstream_id() const { return n_diskstreams(); }
+       uint32_t n_diskstreams() const;
        
-       typedef list<AudioDiskstream *> AudioDiskstreamList;
+       typedef list<Diskstream *> DiskstreamList;
 
-       Session::AudioDiskstreamList audio_disk_streams() const {
-               Glib::RWLock::ReaderLock lm (diskstream_lock);
-               return audio_diskstreams; /* XXX yes, force a copy */
-       }
-
-       void foreach_audio_diskstream (void (AudioDiskstream::*func)(void));
-       template<class T> void foreach_audio_diskstream (T *obj, void (T::*func)(AudioDiskstream&));
-
-       typedef list<Route *> RouteList;
+       typedef std::list<boost::shared_ptr<Route> > RouteList; 
 
-       RouteList get_routes() const {
-               Glib::RWLock::ReaderLock rlock (route_lock);
-               return routes; /* XXX yes, force a copy */
+       boost::shared_ptr<RouteList> get_routes() const {
+               return routes.reader ();
        }
 
-       uint32_t nroutes() const { return routes.size(); }
+       uint32_t nroutes() const { return routes.reader()->size(); }
        uint32_t ntracks () const;
        uint32_t nbusses () const;
 
        struct RoutePublicOrderSorter {
-           bool operator() (Route *, Route *b);
+           bool operator() (boost::shared_ptr<Route>, boost::shared_ptr<Route> b);
        };
        
        template<class T> void foreach_route (T *obj, void (T::*func)(Route&));
-       template<class T> void foreach_route (T *obj, void (T::*func)(Route*));
+       template<class T> void foreach_route (T *obj, void (T::*func)(boost::shared_ptr<Route>));
        template<class T, class A> void foreach_route (T *obj, void (T::*func)(Route&, A), A arg);
 
-       Route *route_by_name (string);
-       Route *route_by_remote_id (uint32_t id);
+       boost::shared_ptr<Route> route_by_name (string);
+       boost::shared_ptr<Route> route_by_remote_id (uint32_t id);
 
        bool route_name_unique (string) const;
 
@@ -349,8 +344,8 @@ class Session : public sigc::trackable, public Stateful
        sigc::signal<void> DurationChanged;
        sigc::signal<void> HaltOnXrun;
 
-       sigc::signal<void,Route*> RouteAdded;
-       sigc::signal<void,AudioDiskstream*> AudioDiskstreamAdded;
+       sigc::signal<void,boost::shared_ptr<Route> > RouteAdded;
+       sigc::signal<void,Diskstream*> DiskstreamAdded; // FIXME: make a shared_ptr
 
        void request_roll ();
        void request_bounded_roll (jack_nframes_t start, jack_nframes_t end);
@@ -362,15 +357,14 @@ class Session : public sigc::trackable, public Stateful
        void goto_start () { request_locate (start_location->start(), false); }
        void use_rf_shuttle_speed ();
        void request_transport_speed (float speed);
-       void request_overwrite_buffer (AudioDiskstream*);
-       void request_diskstream_speed (AudioDiskstream&, float speed);
+       void request_overwrite_buffer (Diskstream*);
+       void request_diskstream_speed (Diskstream&, float speed);
        void request_input_change_handling ();
 
        bool locate_pending() const { return static_cast<bool>(post_transport_work&PostTransportLocate); }
        bool transport_locked () const;
 
        int wipe ();
-       int wipe_diskstream (AudioDiskstream *);
 
        int remove_region_from_region_list (Region&);
 
@@ -500,9 +494,6 @@ class Session : public sigc::trackable, public Stateful
 
        void add_instant_xml (XMLNode&, const std::string& dir);
 
-       void swap_configuration(Configuration** new_config);
-       void copy_configuration(Configuration* new_config);
-
        enum StateOfTheState {
                Clean = 0x0,
                Dirty = 0x1,
@@ -543,13 +534,13 @@ class Session : public sigc::trackable, public Stateful
 
        /* fundamental operations. duh. */
 
+       boost::shared_ptr<AudioTrack> new_audio_track (int input_channels, int output_channels, TrackMode mode = Normal);
+       boost::shared_ptr<Route>      new_audio_route (int input_channels, int output_channels);
 
-       AudioTrack *new_audio_track (int input_channels, int output_channels, TrackMode mode = Normal);
-
-       Route *new_audio_route (int input_channels, int output_channels);
+       void   remove_route (boost::shared_ptr<Route>);
 
-       void   remove_route (Route&);
-       void   resort_routes (void *src);
+       void   resort_routes ();
+       void   resort_routes_using (boost::shared_ptr<RouteList>);
 
        AudioEngine &engine() { return _engine; };
 
@@ -630,7 +621,7 @@ class Session : public sigc::trackable, public Stateful
        string path_from_region_name (string name, string identifier);
 
        AudioRegion* find_whole_file_parent (AudioRegion&);
-       void find_equivalent_playlist_regions (AudioRegion&, std::vector<AudioRegion*>& result);
+       void find_equivalent_playlist_regions (Region&, std::vector<Region*>& result);
 
        AudioRegion *XMLRegionFactory (const XMLNode&, bool full);
 
@@ -698,7 +689,7 @@ class Session : public sigc::trackable, public Stateful
 
        AudioFileSource *create_audio_source_for_session (ARDOUR::AudioDiskstream&, uint32_t which_channel, bool destructive);
 
-       Source *get_source (ARDOUR::id_t);
+       Source *source_by_id (const PBD::ID&);
 
        /* playlist management */
 
@@ -707,8 +698,6 @@ class Session : public sigc::trackable, public Stateful
        sigc::signal<void,Playlist*> PlaylistAdded;
        sigc::signal<void,Playlist*> PlaylistRemoved;
 
-       Playlist *get_playlist (string name);
-
        uint32_t n_playlists() const;
 
        template<class T> void foreach_playlist (T *obj, void (T::*func)(Playlist *));
@@ -731,9 +720,9 @@ class Session : public sigc::trackable, public Stateful
 
        /* auditioning */
 
-       Auditioner& the_auditioner() { return *auditioner; }
+       boost::shared_ptr<Auditioner> the_auditioner() { return auditioner; }
        void audition_playlist ();
-       void audition_region (AudioRegion&);
+       void audition_region (Region&);
        void cancel_audition ();
        bool is_auditioning () const;
        
@@ -770,8 +759,8 @@ class Session : public sigc::trackable, public Stateful
 
        /* control/master out */
 
-       IO* control_out() const { return _control_out; }
-       IO* master_out() const { return _master_out; }
+       boost::shared_ptr<IO> control_out() const { return _control_out; }
+       boost::shared_ptr<IO> master_out() const { return _master_out; }
 
        /* insert/send management */
        
@@ -908,7 +897,7 @@ class Session : public sigc::trackable, public Stateful
 
        /* clicking */
 
-       IO&  click_io() { return *_click_io; }
+       boost::shared_ptr<IO>  click_io() { return _click_io; }
        void set_clicking (bool yn);
        bool get_clicking() const;
 
@@ -1003,14 +992,20 @@ class Session : public sigc::trackable, public Stateful
        static apply_gain_to_buffer_t   apply_gain_to_buffer;
        static mix_buffers_with_gain_t  mix_buffers_with_gain;
        static mix_buffers_no_gain_t    mix_buffers_no_gain;
-       
+
+       static sigc::signal<void> SendFeedback;
+
+       /* Controllables */
+
+       PBD::Controllable* controllable_by_id (const PBD::ID&);
+
   protected:
        friend class AudioEngine;
        void set_block_size (jack_nframes_t nframes);
        void set_frame_rate (jack_nframes_t nframes);
 
   protected:
-       friend class AudioDiskstream;
+       friend class Diskstream;
        void stop_butler ();
        void wait_till_butler_finished();
 
@@ -1072,9 +1067,9 @@ class Session : public sigc::trackable, public Stateful
        float                   _meter_falloff;
        bool                    _end_location_is_free;
 
-       void set_worst_io_latencies (bool take_lock);
+       void set_worst_io_latencies ();
        void set_worst_io_latencies_x (IOChange asifwecare, void *ignored) {
-               set_worst_io_latencies (true);
+               set_worst_io_latencies ();
        }
 
        void update_latency_compensation_proxy (void* ignored);
@@ -1472,12 +1467,12 @@ class Session : public sigc::trackable, public Stateful
        bool waiting_to_start;
 
        void set_auto_loop (bool yn);
-       void overwrite_some_buffers (AudioDiskstream*);
+       void overwrite_some_buffers (Diskstream*);
        void flush_all_redirects ();
        void locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
        void start_locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
        void force_locate (jack_nframes_t frame, bool with_roll = false);
-       void set_diskstream_speed (AudioDiskstream*, float speed);
+       void set_diskstream_speed (Diskstream*, float speed);
        void set_transport_speed (float speed, bool abort = false);
        void stop_transport (bool abort = false);
        void start_transport ();
@@ -1508,21 +1503,21 @@ class Session : public sigc::trackable, public Stateful
 
        /* disk-streams */
 
-       AudioDiskstreamList  audio_diskstreams; 
+       DiskstreamList  diskstreams; 
        mutable Glib::RWLock diskstream_lock;
        uint32_t dstream_buffer_size;
-       void add_diskstream (AudioDiskstream*);
+       void add_diskstream (Diskstream*);
        int  load_diskstreams (const XMLNode&);
 
        /* routes stuff */
 
-       RouteList       routes;
-       mutable Glib::RWLock route_lock;
-       void   add_route (Route*);
+       SerializedRCUManager<RouteList>  routes;
+
+       void   add_route (boost::shared_ptr<Route>);
        uint32_t destructive_index;
 
        int load_routes (const XMLNode&);
-       Route* XMLRouteFactory (const XMLNode&);
+       boost::shared_ptr<Route> XMLRouteFactory (const XMLNode&);
 
        /* mixer stuff */
 
@@ -1532,7 +1527,7 @@ class Session : public sigc::trackable, public Stateful
        bool       currently_soloing;
        
        void route_mute_changed (void *src);
-       void route_solo_changed (void *src, Route *);
+       void route_solo_changed (void *src, boost::shared_ptr<Route>);
        void catch_up_on_solo ();
        void update_route_solo_state ();
        void modify_solo_mute (bool, bool);
@@ -1541,7 +1536,7 @@ class Session : public sigc::trackable, public Stateful
        /* REGION MANAGEMENT */
 
        mutable Glib::Mutex region_lock;
-       typedef map<ARDOUR::id_t,AudioRegion *> AudioRegionList;
+       typedef map<PBD::ID,AudioRegion *> AudioRegionList;
        AudioRegionList audio_regions;
        
        void region_renamed (Region *);
@@ -1554,7 +1549,7 @@ class Session : public sigc::trackable, public Stateful
        /* SOURCES */
        
        mutable Glib::Mutex audio_source_lock;
-       typedef std::map<id_t, AudioSource *>    AudioSourceList;
+       typedef std::map<PBD::ID,AudioSource *> AudioSourceList;
 
        AudioSourceList audio_sources;
 
@@ -1579,7 +1574,7 @@ class Session : public sigc::trackable, public Stateful
        Playlist *XMLPlaylistFactory (const XMLNode&);
 
        void playlist_length_changed (Playlist *);
-       void diskstream_playlist_changed (AudioDiskstream *);
+       void diskstream_playlist_changed (Diskstream *);
 
        /* NAMED SELECTIONS */
 
@@ -1599,7 +1594,7 @@ class Session : public sigc::trackable, public Stateful
 
        /* AUDITIONING */
 
-       Auditioner *auditioner;
+       boost::shared_ptr<Auditioner> auditioner;
        void set_audition (AudioRegion*);
        void non_realtime_set_audition ();
        AudioRegion *pending_audition_region;
@@ -1716,7 +1711,7 @@ class Session : public sigc::trackable, public Stateful
 
        Clicks          clicks;
        bool           _clicking;
-       IO*            _click_io;
+       boost::shared_ptr<IO> _click_io;
        Sample*         click_data;
        Sample*         click_emphasis_data;
        jack_nframes_t  click_length;
@@ -1748,8 +1743,8 @@ class Session : public sigc::trackable, public Stateful
        /* main outs */
        uint32_t main_outs;
        
-       IO* _master_out;
-       IO* _control_out;
+       boost::shared_ptr<IO> _master_out;
+       boost::shared_ptr<IO> _control_out;
 
        AutoConnectOption input_auto_connect;
        AutoConnectOption output_auto_connect;
@@ -1782,8 +1777,15 @@ class Session : public sigc::trackable, public Stateful
 
        LayerModel layer_model;
        CrossfadeModel xfade_model;
+
+       typedef std::list<PBD::Controllable*> Controllables;
+       Glib::Mutex controllables_lock;
+       Controllables controllables;
+
+       void add_controllable (PBD::Controllable*);
+       void remove_controllable (PBD::Controllable*);
 };
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 #endif /* __ardour_session_h__ */
diff --git a/libs/ardour/ardour/session_diskstream.h b/libs/ardour/ardour/session_diskstream.h
deleted file mode 100644 (file)
index 33fc541..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-    Copyright (C) 2002 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$
-*/
-
-#ifndef  __ardour_session_diskstream_h__
-#define __ardour_session_diskstream_h__
-
-#include <ardour/session.h>
-#include <ardour/audio_diskstream.h>
-
-namespace ARDOUR {
-
-template<class T> void 
-Session::foreach_audio_diskstream (T *obj, void (T::*func)(AudioDiskstream&)) 
-{
-       Glib::RWLock::ReaderLock lm (diskstream_lock);
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); i++) {
-               if (!(*i)->hidden()) {
-                       (obj->*func) (**i);
-               }
-       }
-}
-
-} /* namespace */
-
-#endif /* __ardour_session_diskstream_h__ */
index 13d88a9aa4d4a13d56329edc641c88995fe66e9b..4f0fb92e3b878418e9c7bf47861132eef3e7f579 100644 (file)
@@ -10,7 +10,7 @@ template<class T> void Session::foreach_audio_region (T *obj, void (T::*func)(Au
 {
        Glib::Mutex::Lock lm (region_lock);
        for (AudioRegionList::iterator i = audio_regions.begin(); i != audio_regions.end(); i++) {
-               (obj->*func) ((*i).second);
+               (obj->*func) (i->second);
        }
 }
 
index afe78b394e39efcafba0cf1b0893a1d7c2431c18..feacc14775a8cc76f80b6cf15b824e29bad412a1 100644 (file)
@@ -33,14 +33,10 @@ namespace ARDOUR {
 template<class T> void 
 Session::foreach_route (T *obj, void (T::*func)(Route&))
 {
-       RouteList public_order;
-
-       {
-               Glib::RWLock::ReaderLock lm (route_lock);
-               public_order = routes;
-       }
-
+       boost::shared_ptr<RouteList> r = routes.reader();
+       RouteList public_order (*r);
        RoutePublicOrderSorter cmp;
+
        public_order.sort (cmp);
 
        for (RouteList::iterator i = public_order.begin(); i != public_order.end(); i++) {
@@ -49,16 +45,12 @@ Session::foreach_route (T *obj, void (T::*func)(Route&))
 }
 
 template<class T> void 
-Session::foreach_route (T *obj, void (T::*func)(Route*))
+Session::foreach_route (T *obj, void (T::*func)(boost::shared_ptr<Route>))
 {
-       RouteList public_order;
-
-       {
-               Glib::RWLock::ReaderLock lm (route_lock);
-               public_order = routes;
-       }
-
+       boost::shared_ptr<RouteList> r = routes.reader();
+       RouteList public_order (*r);
        RoutePublicOrderSorter cmp;
+
        public_order.sort (cmp);
 
        for (RouteList::iterator i = public_order.begin(); i != public_order.end(); i++) {
@@ -66,18 +58,13 @@ Session::foreach_route (T *obj, void (T::*func)(Route*))
        }
 }
 
-
 template<class T, class A> void 
 Session::foreach_route (T *obj, void (T::*func)(Route&, A), A arg1)
 {
-       RouteList public_order;
-
-       {
-               Glib::RWLock::ReaderLock lm (route_lock);
-               public_order = routes;
-       }
-
+       boost::shared_ptr<RouteList> r = routes.reader();
+       RouteList public_order (*r);
        RoutePublicOrderSorter cmp;
+
        public_order.sort (cmp);
 
        for (RouteList::iterator i = public_order.begin(); i != public_order.end(); i++) {
index 5e3c1f621d7028ba13a6a03edf549ee4bb43678e..476433945147f2d4cd8403c0f7f8048933ea75c8 100644 (file)
@@ -51,7 +51,7 @@ class SndFileSource : public AudioFileSource {
        int update_header (jack_nframes_t when, struct tm&, time_t);
        int flush_header ();
 
-       void handle_smpte_offset_change (jack_nframes_t offset, bool negative);
+       jack_nframes_t natural_position () const;
 
   protected:
        void set_header_timeline_position ();
@@ -75,7 +75,7 @@ class SndFileSource : public AudioFileSource {
        int setup_broadcast_info (jack_nframes_t when, struct tm&, time_t);
 };
 
-}; /* namespace ARDOUR */
+} // namespace ARDOUR
 
 #endif /* __sndfile_source_h__ */
 
index f3133c71cd9618b038d20903b9b5c39e933afa2a..f57ea7985447d80930205dd44c9dd1d9adca2695 100644 (file)
@@ -25,8 +25,9 @@
 
 #include <sigc++/signal.h>
 
+#include <pbd/stateful.h> 
+
 #include <ardour/ardour.h>
-#include <ardour/stateful.h>
 
 namespace ARDOUR {
 
@@ -40,7 +41,7 @@ class Source : public Stateful, public sigc::trackable
        std::string name() const { return _name; }
        int set_name (std::string str, bool destructive);
 
-       ARDOUR::id_t  id() const   { return _id; }
+       const PBD::ID&  id() const   { return _id; }
 
        uint32_t use_cnt() const { return _use_cnt; }
        void use ();
@@ -60,7 +61,7 @@ class Source : public Stateful, public sigc::trackable
        time_t            _timestamp;
 
   private:
-       ARDOUR::id_t _id;
+       PBD::ID _id;
 };
 
 }
diff --git a/libs/ardour/ardour/stateful.h b/libs/ardour/ardour/stateful.h
deleted file mode 100644 (file)
index 4f4cb20..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-    Copyright (C) 2000 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$
-*/
-
-#ifndef __ardour_stateful_h__
-#define __ardour_stateful_h__
-
-#include <string>
-
-class XMLNode;
-
-class Stateful {
-  public:
-       Stateful();
-       virtual ~Stateful();
-
-       virtual XMLNode& get_state (void) = 0;
-
-       virtual int set_state (const XMLNode&) = 0;
-
-       /* Extra XML nodes */
-
-       void add_extra_xml (XMLNode&);
-       XMLNode *extra_xml (const std::string& str);
-
-       virtual void add_instant_xml (XMLNode&, const std::string& dir);
-       XMLNode *instant_xml (const std::string& str, const std::string& dir);
-
-  protected:
-       XMLNode *_extra_xml;
-       XMLNode *_instant_xml;
-};
-
-#endif /* __ardour_stateful_h__ */
-
index 13e8eb6348915661491d4f048688c17bb7d67a3d..db0689460728a34670d324122f2b421fc7e94906 100644 (file)
 #include <cmath>
 #include <glibmm/thread.h>
 #include <pbd/undo.h>
+#include <pbd/stateful.h> 
 #include <sigc++/signal.h>
 
 #include <ardour/ardour.h>
-#include <ardour/stateful.h>
 #include <ardour/state_manager.h>
 
 class XMLNode;
diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h
new file mode 100644 (file)
index 0000000..f16e9d2
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+    Copyright (C) 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
+    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.
+*/
+
+#ifndef __ardour_track_h__
+#define __ardour_track_h__
+
+#include <ardour/route.h>
+
+namespace ARDOUR {
+
+class Session;
+class Diskstream;
+class Playlist;
+class RouteGroup;
+
+class Track : public Route
+{
+  public:
+       Track (Session&, string name, Route::Flag f = Route::Flag (0), TrackMode m = Normal, DataType default_type = DataType::AUDIO);
+
+       virtual ~Track ();
+       
+       int set_name (string str, void *src);
+
+       virtual int roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
+               jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input) = 0;
+       
+       virtual int no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, 
+               jack_nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input) = 0;
+       
+       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) = 0;
+
+       void toggle_monitor_input ();
+
+       bool can_record() const { return true; }
+
+       Diskstream& diskstream() const { return *_diskstream; }
+
+       virtual int use_diskstream (string name) = 0;
+       virtual int use_diskstream (const PBD::ID& id) = 0;
+
+       TrackMode mode() const { return _mode; }
+       void      set_mode (TrackMode m);
+
+       jack_nframes_t update_total_latency();
+       void           set_latency_delay (jack_nframes_t);
+
+       enum FreezeState {
+               NoFreeze,
+               Frozen,
+               UnFrozen
+       };
+
+       FreezeState freeze_state() const;
+       virtual void freeze (InterThreadInfo&) = 0;
+       virtual void unfreeze () = 0;
+
+       virtual void bounce (InterThreadInfo&) = 0;
+       virtual void bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo&) = 0;
+
+       XMLNode&    get_state();
+       XMLNode&    get_template();
+       virtual int set_state(const XMLNode& node) = 0;
+
+       PBD::Controllable& rec_enable_control() { return _rec_enable_control; }
+
+       bool record_enabled() const;
+       void set_record_enable (bool yn, void *src);
+       
+       void set_meter_point (MeterPoint, void* src);
+       
+       sigc::signal<void> ModeChanged;
+       sigc::signal<void> DiskstreamChanged;
+       sigc::signal<void> FreezeChange;
+
+  protected:
+       Track (Session& sess, const XMLNode& node, DataType default_type = DataType::AUDIO);
+
+       virtual XMLNode& state (bool full) = 0;
+
+       virtual void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, 
+               jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter) = 0;
+
+       virtual uint32_t n_process_buffers () = 0;
+       
+       Diskstream *_diskstream;
+       MeterPoint  _saved_meter_point;
+       TrackMode   _mode;
+
+       //private: (FIXME)
+       struct FreezeRecordInsertInfo {
+           FreezeRecordInsertInfo(XMLNode& st, boost::shared_ptr<Insert> ins) 
+                   : state (st), insert (ins) {}
+
+           XMLNode                   state;
+           boost::shared_ptr<Insert> insert;
+           PBD::ID                   id;
+           UndoAction                memento;
+       };
+
+       struct FreezeRecord {
+           FreezeRecord()
+               : playlist(0)
+               , have_mementos(false)
+           {}
+
+           ~FreezeRecord();
+
+           Playlist*                       playlist;
+           vector<FreezeRecordInsertInfo*> insert_info;
+           bool                            have_mementos;
+           FreezeState                     state;
+       };
+
+       struct RecEnableControllable : public PBD::Controllable {
+           RecEnableControllable (Track&);
+           
+           void set_value (float);
+           float get_value (void) const;
+
+           Track& track;
+       };
+
+       //virtual void diskstream_record_enable_changed (void *src) = 0;
+       //virtual void diskstream_input_channel_changed (void *src) = 0;
+
+       //virtual void input_change_handler (void *src) = 0;
+
+       virtual void set_state_part_two () = 0;
+
+       FreezeRecord          _freeze_record;
+       XMLNode*              pending_state;
+       sigc::connection      recenable_connection;
+       sigc::connection      ic_connection;
+       RecEnableControllable _rec_enable_control;
+       bool                  _destructive;
+};
+
+}; /* namespace ARDOUR*/
+
+#endif /* __ardour_track_h__ */
index a0a209b569248ee87a6a40cb65b0c7e22944216d..b2230f12d7ba4c78a56965c746fad708e126d9cc 100644 (file)
@@ -30,6 +30,8 @@
 #include <inttypes.h>
 #include <jack/types.h>
 #include <control_protocol/smpte.h>
+#include <pbd/id.h>
+
 #include <map>
 
 #if __GNUC__ < 3
@@ -45,7 +47,7 @@ namespace ARDOUR {
        typedef float                       pan_t;
        typedef float                       gain_t;
        typedef uint32_t                    layer_t;
-       typedef uint64_t                    id_t;
+       typedef uint64_t                    microseconds_t;
 
        enum IOChange {
                NoChange = 0,
@@ -69,7 +71,7 @@ namespace ARDOUR {
                PanAutomation = 0x2,
                PluginAutomation = 0x4,
                SoloAutomation = 0x8,
-               MuteAutomation = 0x10,
+               MuteAutomation = 0x10
        };
 
        enum AutoState {
@@ -188,10 +190,10 @@ namespace ARDOUR {
 
        enum EditMode {
                Slide,
-               Splice,
+               Splice
        };
 
-        enum RegionPoint { 
+       enum RegionPoint { 
            Start,
            End,
            SyncPoint
@@ -241,7 +243,7 @@ namespace ARDOUR {
            PeakDatum min;
            PeakDatum max;
        };
-};
+}
 
 std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
 std::istream& operator>>(std::istream& o, ARDOUR::HeaderFormat& sf);
index 3a9905b3ac4c9ffae9d477943e71328ffef69b41..ee4482d26061cf8c880862cd7ea4c7b7c7d31b58 100644 (file)
 #include <string>
 #include <cmath>
 
+#ifdef HAVE_COREAUDIO
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
 #include "ardour.h"
 
 class XMLNode;
@@ -50,9 +54,11 @@ int tokenize_fullpath (std::string fullpath, std::string& path, std::string& nam
 
 int touch_file(std::string path);
 
-uint32_t long get_uid();
-
 std::string region_name_from_path (std::string path);
 std::string path_expand (std::string);
 
+#ifdef HAVE_COREAUDIO
+std::string CFStringRefToStdString(CFStringRef stringRef);
+#endif // HAVE_COREAUDIO
+
 #endif /* __ardour_utils_h__ */
index ee8e6e986b806e3e8bd7af83a62bd2e0c5890ddc..3636fe275a01efabf53b5152013b982785018bb5 100644 (file)
 #include <string>
 #include <dlfcn.h>
 
-#include <midi++/controllable.h>
 #include <sigc++/signal.h>
-
+#include <pbd/stateful.h> 
 #include <jack/types.h>
-#include <ardour/stateful.h>
 #include <ardour/plugin_state.h>
 #include <ardour/plugin.h>
 
@@ -106,6 +104,14 @@ class VSTPlugin : public ARDOUR::Plugin
        bool        been_resumed;
 };
 
-}
+class VSTPluginInfo : public PluginInfo
+{
+       VSTPluginInfo () {}
+       ~VSTPluginInfo () {}
+       
+       PluginPtr load (Session& session);
+};
+
+} // namespace ARDOUR
 
 #endif /* __ardour_vst_plugin_h__ */
index 977616dd8b1a67256f7805ed9a9f4625a877e562..7d2a2103bb869aba8cd6f60297719a962ba210f0 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000-2003 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
@@ -14,8 +14,6 @@
     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: diskstream.cc 567 2006-06-07 14:54:12Z trutkin $
 */
 
 #include <fstream>
@@ -23,6 +21,7 @@
 #include <unistd.h>
 #include <cmath>
 #include <cerrno>
+#include <cassert>
 #include <string>
 #include <climits>
 #include <fcntl.h>
@@ -56,32 +55,30 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-jack_nframes_t AudioDiskstream::disk_io_chunk_frames;
-
-sigc::signal<void,AudioDiskstream*>    AudioDiskstream::AudioDiskstreamCreated;
-sigc::signal<void,list<AudioFileSource*>*> AudioDiskstream::DeleteSources;
-sigc::signal<void>                AudioDiskstream::DiskOverrun;
-sigc::signal<void>                AudioDiskstream::DiskUnderrun;
+size_t  AudioDiskstream::_working_buffers_size = 0;
+Sample* AudioDiskstream::_mixdown_buffer       = 0;
+gain_t* AudioDiskstream::_gain_buffer          = 0;
+char*   AudioDiskstream::_conversion_buffer    = 0;
 
-AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Flag flag)
-       : _name (name),
-         _session (sess)
+AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream::Flag flag)
+       : Diskstream(sess, name, flag)
+       , deprecated_io_node(NULL)
 {
        /* prevent any write sources from being created */
 
        in_set_state = true;
 
-       init (flag);
+       init(flag);
        use_new_playlist ();
 
        in_set_state = false;
 
-       AudioDiskstreamCreated (this); /* EMIT SIGNAL */
+       DiskstreamCreated (this); /* EMIT SIGNAL */
 }
        
 AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
-       : _session (sess)
-       
+       : Diskstream(sess, node)
+       , deprecated_io_node(NULL)
 {
        in_set_state = true;
        init (Recordable);
@@ -97,7 +94,7 @@ AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
                use_destructive_playlist ();
        }
 
-       AudioDiskstreamCreated (this); /* EMIT SIGNAL */
+       DiskstreamCreated (this); /* EMIT SIGNAL */
 }
 
 void
@@ -130,44 +127,9 @@ AudioDiskstream::init_channel (ChannelInfo &chan)
 
 
 void
-AudioDiskstream::init (Flag f)
+AudioDiskstream::init (Diskstream::Flag f)
 {
-       _id = new_id();
-       _refcnt = 0;
-       _flags = f;
-       _io = 0;
-       _alignment_style = ExistingMaterial;
-       _persistent_alignment_style = ExistingMaterial;
-       first_input_change = true;
-       _playlist = 0;
-       i_am_the_modifier = 0;
-       g_atomic_int_set (&_record_enabled, 0);
-       was_recording = false;
-       capture_start_frame = 0;
-       capture_captured = 0;
-       _visible_speed = 1.0f;
-       _actual_speed = 1.0f;
-       _buffer_reallocation_required = false;
-       _seek_required = false;
-       first_recordable_frame = max_frames;
-       last_recordable_frame = max_frames;
-       _roll_delay = 0;
-       _capture_offset = 0;
-       _processed = false;
-       _slaved = false;
-       adjust_capture_position = 0;
-       last_possibly_recording = 0;
-       loop_location = 0;
-       wrap_buffer_size = 0;
-       speed_buffer_size = 0;
-       last_phase = 0;
-       phi = (uint64_t) (0x1000000);
-       file_frame = 0;
-       playback_sample = 0;
-       playback_distance = 0;
-       _read_data_count = 0;
-       _write_data_count = 0;
-       deprecated_io_node = 0;
+       Diskstream::init(f);
 
        /* there are no channels at this point, so these
           two calls just get speed_buffer_size and wrap_buffer
@@ -177,13 +139,8 @@ AudioDiskstream::init (Flag f)
        set_block_size (_session.get_block_size());
        allocate_temporary_buffers ();
 
-       pending_overwrite = false;
-       overwrite_frame = 0;
-       overwrite_queued = false;
-       input_change_pending = NoChange;
-
        add_channel ();
-       _n_channels = 1;
+       assert(_n_channels == 1);
 }
 
 void
@@ -217,26 +174,33 @@ AudioDiskstream::~AudioDiskstream ()
 {
        Glib::Mutex::Lock lm (state_lock);
 
-       if (_playlist) {
-               _playlist->unref ();
-       }
-
-       for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+       for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan)
                destroy_channel((*chan));
-       }
        
        channels.clear();
 }
 
 void
-AudioDiskstream::handle_input_change (IOChange change, void *src)
+AudioDiskstream::allocate_working_buffers()
 {
-       Glib::Mutex::Lock lm (state_lock);
+       assert(disk_io_frames() > 0);
 
-       if (!(input_change_pending & change)) {
-               input_change_pending = IOChange (input_change_pending|change);
-               _session.request_input_change_handling ();
-       }
+       _working_buffers_size = disk_io_frames();
+       _mixdown_buffer       = new Sample[_working_buffers_size];
+       _gain_buffer          = new gain_t[_working_buffers_size];
+       _conversion_buffer    = new char[_working_buffers_size * 4];
+}
+
+void
+AudioDiskstream::free_working_buffers()
+{
+       delete _mixdown_buffer;
+       delete _gain_buffer;
+       delete _conversion_buffer;
+       _working_buffers_size = 0;
+       _mixdown_buffer       = 0;
+       _gain_buffer          = 0;
+       _conversion_buffer    = 0;
 }
 
 void
@@ -334,9 +298,9 @@ AudioDiskstream::find_and_use_playlist (const string& name)
        Playlist* pl;
        AudioPlaylist* playlist;
                
-       if ((pl = _session.get_playlist (name)) == 0) {
-               error << string_compose(_("AudioDiskstream: Session doesn't know about a Playlist called \"%1\""), name) << endmsg;
-               return -1;
+       if ((pl = _session.playlist_by_name (name)) == 0) {
+               playlist = new AudioPlaylist(_session, name);
+               pl = playlist;
        }
 
        if ((playlist = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
@@ -348,57 +312,15 @@ AudioDiskstream::find_and_use_playlist (const string& name)
 }
 
 int
-AudioDiskstream::use_playlist (AudioPlaylist* playlist)
+AudioDiskstream::use_playlist (Playlist* playlist)
 {
-       {
-               Glib::Mutex::Lock lm (state_lock);
-
-               if (playlist == _playlist) {
-                       return 0;
-               }
+       assert(dynamic_cast<AudioPlaylist*>(playlist));
 
-               plstate_connection.disconnect();
-               plmod_connection.disconnect ();
-               plgone_connection.disconnect ();
-
-               if (_playlist) {
-                       _playlist->unref();
-               }
-                       
-               _playlist = playlist;
-               _playlist->ref();
-
-               if (!in_set_state && recordable()) {
-                       reset_write_sources (false);
-               }
-               
-               plstate_connection = _playlist->StateChanged.connect (mem_fun (*this, &AudioDiskstream::playlist_changed));
-               plmod_connection = _playlist->Modified.connect (mem_fun (*this, &AudioDiskstream::playlist_modified));
-               plgone_connection = _playlist->GoingAway.connect (mem_fun (*this, &AudioDiskstream::playlist_deleted));
-       }
-
-       if (!overwrite_queued) {
-               _session.request_overwrite_buffer (this);
-               overwrite_queued = true;
-       }
-       
-       PlaylistChanged (); /* EMIT SIGNAL */
-       _session.set_dirty ();
+       Diskstream::use_playlist(playlist);
 
        return 0;
 }
 
-void
-AudioDiskstream::playlist_deleted (Playlist* pl)
-{
-       /* this catches an ordering issue with session destruction. playlists 
-          are destroyed before diskstreams. we have to invalidate any handles
-          we have to the playlist.
-       */
-
-       _playlist = 0;
-}
-
 int
 AudioDiskstream::use_new_playlist ()
 {
@@ -426,6 +348,8 @@ AudioDiskstream::use_new_playlist ()
 int
 AudioDiskstream::use_copy_playlist ()
 {
+       assert(audio_playlist());
+
        if (destructive()) {
                return 0;
        }
@@ -440,7 +364,7 @@ AudioDiskstream::use_copy_playlist ()
 
        newname = Playlist::bump_name (_playlist->name(), _session);
        
-       if ((playlist  = new AudioPlaylist (*_playlist, newname)) != 0) {
+       if ((playlist  = new AudioPlaylist (*audio_playlist(), newname)) != 0) {
                playlist->set_orig_diskstream_id (id());
                return use_playlist (playlist);
        } else { 
@@ -459,8 +383,10 @@ AudioDiskstream::setup_destructive_playlist ()
 
        /* a single full-sized region */
 
+       cerr << "setup DS using " << srcs.front()->natural_position () << endl;
+
        AudioRegion* region = new AudioRegion (srcs, 0, max_frames, _name);
-       _playlist->add_region (*region, 0);             
+       _playlist->add_region (*region, srcs.front()->natural_position());              
 }
 
 void
@@ -488,110 +414,13 @@ AudioDiskstream::use_destructive_playlist ()
 
        for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
                (*chan).write_source = dynamic_cast<AudioFileSource*>(&region->source (n));
+               assert((*chan).write_source);
                (*chan).write_source->set_allow_remove_if_empty (false);
        }
 
        /* the source list will never be reset for a destructive track */
 }
 
-void
-AudioDiskstream::set_io (IO& io)
-{
-       _io = &io;
-       set_align_style_from_io ();
-}
-
-int
-AudioDiskstream::set_name (string str, void *src)
-{
-       if (str != _name) {
-               _playlist->set_name (str);
-               _name = str;
-               
-               if (!in_set_state && recordable()) {
-                       /* rename existing capture files so that they have the correct name */
-                       return rename_write_sources ();
-               } else {
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-void
-AudioDiskstream::set_speed (double sp)
-{
-       _session.request_diskstream_speed (*this, sp);
-
-       /* to force a rebuffering at the right place */
-       playlist_modified();
-}
-
-bool
-AudioDiskstream::realtime_set_speed (double sp, bool global)
-{
-       bool changed = false;
-       double new_speed = sp * _session.transport_speed();
-       
-       if (_visible_speed != sp) {
-               _visible_speed = sp;
-               changed = true;
-       }
-       
-       if (new_speed != _actual_speed) {
-               
-               jack_nframes_t required_wrap_size = (jack_nframes_t) floor (_session.get_block_size() * 
-                                                                           fabs (new_speed)) + 1;
-               
-               if (required_wrap_size > wrap_buffer_size) {
-                       _buffer_reallocation_required = true;
-               }
-               
-               _actual_speed = new_speed;
-               phi = (uint64_t) (0x1000000 * fabs(_actual_speed));
-       }
-
-       if (changed) {
-               if (!global) {
-                       _seek_required = true;
-               }
-                speed_changed (); /* EMIT SIGNAL */
-       }
-
-       return _buffer_reallocation_required || _seek_required;
-}
-
-void
-AudioDiskstream::non_realtime_set_speed ()
-{
-       if (_buffer_reallocation_required)
-       {
-               Glib::Mutex::Lock lm (state_lock);
-               allocate_temporary_buffers ();
-
-               _buffer_reallocation_required = false;
-       }
-
-       if (_seek_required) {
-               if (speed() != 1.0f || speed() != -1.0f) {
-                       seek ((jack_nframes_t) (_session.transport_frame() * (double) speed()), true);
-               }
-               else {
-                       seek (_session.transport_frame(), true);
-               }
-
-               _seek_required = false;
-       }
-}
-
-void
-AudioDiskstream::prepare ()
-{
-       _processed = false;
-       playback_distance = 0;
-}
-
 void
 AudioDiskstream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record)
 {
@@ -755,7 +584,7 @@ AudioDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes
           returns a non-zero value, in which case, ::commit should not be called.
        */
 
-        // If we can't take the state lock return.
+       // If we can't take the state lock return.
        if (!state_lock.trylock()) {
                return 1;
        }
@@ -1011,13 +840,6 @@ AudioDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes
        return ret;
 }
 
-void
-AudioDiskstream::recover ()
-{
-       state_lock.unlock();
-       _processed = false;
-}
-
 bool
 AudioDiskstream::commit (jack_nframes_t nframes)
 {
@@ -1153,13 +975,19 @@ AudioDiskstream::seek (jack_nframes_t frame, bool complete_refill)
                (*chan).capture_buf->reset ();
        }
        
+       /* can't rec-enable in destructive mode if transport is before start */
+
+       if (destructive() && record_enabled() && frame < _session.current_start_frame()) {
+               disengage_record_enable ();
+       }
+
        playback_sample = frame;
        file_frame = frame;
 
        if (complete_refill) {
-               while ((ret = do_refill (0, 0, 0)) > 0);
+               while ((ret = do_refill_with_alloc ()) > 0) ;
        } else {
-               ret = do_refill (0, 0, 0);
+               ret = do_refill_with_alloc ();
        }
 
        return ret;
@@ -1251,7 +1079,7 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
 
                this_read = min(cnt,this_read);
 
-               if (_playlist->read (buf+offset, mixdown_buffer, gain_buffer, workbuf, start, this_read, channel) != this_read) {
+               if (audio_playlist()->read (buf+offset, mixdown_buffer, gain_buffer, workbuf, start, this_read, channel) != this_read) {
                        error << string_compose(_("AudioDiskstream %1: cannot read %2 from playlist at frame %3"), _id, this_read, 
                                         start) << endmsg;
                        return -1;
@@ -1285,14 +1113,27 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
 }
 
 int
-AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbuf)
+AudioDiskstream::do_refill_with_alloc()
+{
+       Sample* mix_buf  = new Sample[disk_io_chunk_frames];
+       float*  gain_buf = new float[disk_io_chunk_frames];
+       char*   work_buf = new char[disk_io_chunk_frames * 4];
+
+       int ret = _do_refill(mix_buf, gain_buf, work_buf);
+       
+       delete [] mix_buf;
+       delete [] gain_buf;
+       delete [] work_buf;
+
+       return ret;
+}
+
+int
+AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbuf)
 {
        int32_t ret = 0;
        jack_nframes_t to_read;
        RingBufferNPT<Sample>::rw_vector vector;
-       bool free_mixdown;
-       bool free_gain;
-       bool free_workbuf;
        bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f;
        jack_nframes_t total_space;
        jack_nframes_t zero_fill;
@@ -1300,6 +1141,10 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w
        ChannelList::iterator i;
        jack_nframes_t ts;
 
+       assert(mixdown_buffer);
+       assert(gain_buffer);
+       assert(workbuf);
+
        channels.front().playback_buf->get_write_vector (&vector);
        
        if ((total_space = vector.len[0] + vector.len[1]) == 0) {
@@ -1406,33 +1251,6 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w
                        zero_fill = 0;
                }
        }
-
-       /* Please note: the code to allocate buffers isn't run
-          during normal butler thread operation. Its there
-          for other times when we need to call do_refill()
-          from somewhere other than the butler thread.
-       */
-
-       if (mixdown_buffer == 0) {
-               mixdown_buffer = new Sample[disk_io_chunk_frames];
-               free_mixdown = true;
-       } else {
-               free_mixdown = false;
-       }
-
-       if (gain_buffer == 0) {
-               gain_buffer = new float[disk_io_chunk_frames];
-               free_gain = true;
-       } else {
-               free_gain = false;
-       }
-
-       if (workbuf == 0) {
-               workbuf = new char[disk_io_chunk_frames * 4];
-               free_workbuf = true;
-       } else {
-               free_workbuf = false;
-       }
        
        jack_nframes_t file_frame_tmp = 0;
 
@@ -1501,37 +1319,30 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w
        file_frame = file_frame_tmp;
 
   out:
-       if (free_mixdown) {
-               delete [] mixdown_buffer;
-       }
-       if (free_gain) {
-               delete [] gain_buffer;
-       }
-       if (free_workbuf) {
-               delete [] workbuf;
-       }
 
        return ret;
 }      
 
+/** Flush pending data to disk.
+ *
+ * Important note: this function will write *AT MOST* disk_io_chunk_frames
+ * of data to disk. it will never write more than that.  If it writes that
+ * much and there is more than that waiting to be written, it will return 1,
+ * otherwise 0 on success or -1 on failure.
+ * 
+ * If there is less than disk_io_chunk_frames to be written, no data will be
+ * written at all unless @a force_flush is true.
+ */
 int
-AudioDiskstream::do_flush (char * workbuf, bool force_flush)
+AudioDiskstream::do_flush (Session::RunContext context, bool force_flush)
 {
+       char* workbuf = _session.conversion_buffer(context);
+
        uint32_t to_write;
        int32_t ret = 0;
        RingBufferNPT<Sample>::rw_vector vector;
        RingBufferNPT<CaptureTransition>::rw_vector transvec;
        jack_nframes_t total;
-       
-       /* important note: this function will write *AT MOST* 
-          disk_io_chunk_frames of data to disk. it will never 
-          write more than that. if its writes that much and there 
-          is more than that waiting to be written, it will return 1,
-          otherwise 0 on success or -1 on failure.
-
-          if there is less than disk_io_chunk_frames to be written, 
-          no data will be written at all unless `force_flush' is true.  
-       */
 
        _write_data_count = 0;
 
@@ -1546,7 +1357,6 @@ AudioDiskstream::do_flush (char * workbuf, bool force_flush)
                        goto out;
                }
 
-               
                /* if there are 2+ chunks of disk i/o possible for
                   this track, let the caller know so that it can arrange
                   for us to be called again, ASAP.
@@ -1564,7 +1374,6 @@ AudioDiskstream::do_flush (char * workbuf, bool force_flush)
 
                to_write = min (disk_io_chunk_frames, (jack_nframes_t) vector.len[0]);
                
-               
                // check the transition buffer when recording destructive
                // important that we get this after the capture buf
 
@@ -1651,21 +1460,6 @@ AudioDiskstream::do_flush (char * workbuf, bool force_flush)
        return ret;
 }
 
-void
-AudioDiskstream::playlist_changed (Change ignored)
-{
-       playlist_modified ();
-}
-
-void
-AudioDiskstream::playlist_modified ()
-{
-       if (!i_am_the_modifier && !overwrite_queued) {
-               _session.request_overwrite_buffer (this);
-               overwrite_queued = true;
-       } 
-}
-
 void
 AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture)
 {
@@ -1679,7 +1473,6 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
        ChannelList::iterator chan;
        vector<CaptureInfo*>::iterator ci;
        uint32_t n = 0; 
-       list<AudioFileSource*>* deletion_list;
        bool mark_write_completed = false;
 
        finish_capture (true);
@@ -1689,7 +1482,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
        */
 
        while (more_work && !err) {
-               switch (do_flush ( _session.conversion_buffer(Session::TransportContext), true)) {
+               switch (do_flush (Session::TransportContext, true)) {
                case 0:
                        more_work = false;
                        break;
@@ -1712,7 +1505,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
                
                ChannelList::iterator chan;
                
-               deletion_list = new list<AudioFileSource*>;
+               list<Source*>* deletion_list = new list<Source*>;
 
                for ( chan = channels.begin(); chan != channels.end(); ++chan) {
 
@@ -1900,17 +1693,17 @@ AudioDiskstream::finish_capture (bool rec_monitors_input)
 }
 
 void
-AudioDiskstream::set_record_enabled (bool yn, void* src)
+AudioDiskstream::set_record_enabled (bool yn)
 {
-        bool rolling = _session.transport_speed() != 0.0f;
-
        if (!recordable() || !_session.record_enabling_legal()) {
                return;
        }
-       
-       /* if we're turning on rec-enable, there needs to be an
-          input connection.
-        */
+
+       /* can't rec-enable in destructive mode if transport is before start */
+
+       if (destructive() && yn && _session.transport_frame() < _session.current_start_frame()) {
+               return;
+       }
 
        if (yn && channels[0].source == 0) {
 
@@ -1927,42 +1720,57 @@ AudioDiskstream::set_record_enabled (bool yn, void* src)
 
        if (record_enabled() != yn) {
                if (yn) {
-                       g_atomic_int_set (&_record_enabled, 1);
-                       capturing_sources.clear ();
-                       if (Config->get_use_hardware_monitoring())  {
-                               for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
-                                       if ((*chan).source) {
-                                               (*chan).source->request_monitor_input (!(_session.get_auto_input() && rolling));
-                                       }
-                                       capturing_sources.push_back ((*chan).write_source);
-                               }
-                       } else {
-                               for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
-                                       capturing_sources.push_back ((*chan).write_source);
-                               }
-                       }
-
+                       engage_record_enable ();
                } else {
-                       g_atomic_int_set (&_record_enabled, 0);
-                       if (Config->get_use_hardware_monitoring()) {
-                               for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
-                                       if ((*chan).source) {
-                                               (*chan).source->request_monitor_input (false);
-                                       }
-                               }
+                       disengage_record_enable ();
+               }
+       }
+}
+
+void
+AudioDiskstream::engage_record_enable ()
+{
+    bool rolling = _session.transport_speed() != 0.0f;
+
+       g_atomic_int_set (&_record_enabled, 1);
+       capturing_sources.clear ();
+       if (Config->get_use_hardware_monitoring())  {
+               for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+                       if ((*chan).source) {
+                               (*chan).source->request_monitor_input (!(_session.get_auto_input() && rolling));
                        }
-                       capturing_sources.clear ();
+                       capturing_sources.push_back ((*chan).write_source);
+               }
+       } else {
+               for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+                       capturing_sources.push_back ((*chan).write_source);
                }
+       }
+
+       RecordEnableChanged (); /* EMIT SIGNAL */
+}
 
-               record_enable_changed (src); /* EMIT SIGNAL */
+void
+AudioDiskstream::disengage_record_enable ()
+{
+       g_atomic_int_set (&_record_enabled, 0);
+       if (Config->get_use_hardware_monitoring()) {
+               for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+                       if ((*chan).source) {
+                               (*chan).source->request_monitor_input (false);
+                       }
+               }
        }
+       capturing_sources.clear ();
+       RecordEnableChanged (); /* EMIT SIGNAL */
 }
+               
 
 XMLNode&
 AudioDiskstream::get_state ()
 {
        XMLNode* node = new XMLNode ("AudioDiskstream");
-       char buf[64];
+       char buf[64] = "";
        LocaleGuard lg (X_("POSIX"));
 
        snprintf (buf, sizeof(buf), "0x%x", _flags);
@@ -1977,7 +1785,7 @@ AudioDiskstream::get_state ()
        node->add_property ("speed", buf);
 
        node->add_property("name", _name);
-       snprintf (buf, sizeof(buf), "%" PRIu64, id());
+       id().print (buf);
        node->add_property("id", buf);
 
        if (!capturing_sources.empty() && _session.get_record_enabled()) {
@@ -2044,11 +1852,11 @@ AudioDiskstream::set_state (const XMLNode& node)
 
        if (deprecated_io_node) {
                if ((prop = deprecated_io_node->property ("id")) != 0) {
-                       sscanf (prop->value().c_str(), "%" PRIu64, &_id);
+                       _id = prop->value ();
                }
        } else {
                if ((prop = node.property ("id")) != 0) {
-                       sscanf (prop->value().c_str(), "%" PRIu64, &_id);
+                       _id = prop->value ();
                }
        }
 
@@ -2061,8 +1869,7 @@ AudioDiskstream::set_state (const XMLNode& node)
        }
        
        // create necessary extra channels
-       // we are always constructed with one
-       // and we always need one
+       // we are always constructed with one and we always need one
 
        if (nchans > _n_channels) {
 
@@ -2292,23 +2099,6 @@ AudioDiskstream::monitor_input (bool yn)
        }
 }
 
-void
-AudioDiskstream::set_capture_offset ()
-{
-       if (_io == 0) {
-               /* can't capture, so forget it */
-               return;
-       }
-
-       _capture_offset = _io->input_latency();
-}
-
-void
-AudioDiskstream::set_persistent_align_style (AlignStyle a)
-{
-       _persistent_alignment_style = a;
-}
-
 void
 AudioDiskstream::set_align_style_from_io ()
 {
@@ -2334,20 +2124,6 @@ AudioDiskstream::set_align_style_from_io ()
        }
 }
 
-void
-AudioDiskstream::set_align_style (AlignStyle a)
-{
-       if (record_enabled() && _session.actively_recording()) {
-               return;
-       }
-
-
-       if (a != _alignment_style) {
-               _alignment_style = a;
-               AlignmentStyleChanged ();
-       }
-}
-
 int
 AudioDiskstream::add_channel ()
 {
@@ -2398,58 +2174,6 @@ AudioDiskstream::capture_buffer_load () const
                        (double) channels.front().capture_buf->bufsize());
 }
 
-int
-AudioDiskstream::set_loop (Location *location)
-{
-       if (location) {
-               if (location->start() >= location->end()) {
-                       error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
-                       return -1;
-               }
-       }
-
-       loop_location = location;
-
-        LoopSet (location); /* EMIT SIGNAL */
-       return 0;
-}
-
-jack_nframes_t
-AudioDiskstream::get_capture_start_frame (uint32_t n)
-{
-       Glib::Mutex::Lock lm (capture_info_lock);
-
-       if (capture_info.size() > n) {
-               return capture_info[n]->start;
-       }
-       else {
-               return capture_start_frame;
-       }
-}
-
-jack_nframes_t
-AudioDiskstream::get_captured_frames (uint32_t n)
-{
-       Glib::Mutex::Lock lm (capture_info_lock);
-
-       if (capture_info.size() > n) {
-               return capture_info[n]->frames;
-       }
-       else {
-               return capture_captured;
-       }
-}
-
-void
-AudioDiskstream::punch_in ()
-{
-}
-
-void
-AudioDiskstream::punch_out ()
-{
-}
-
 int
 AudioDiskstream::use_pending_capture_data (XMLNode& node)
 {
@@ -2545,22 +2269,3 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
 
        return 0;
 }
-
-void
-AudioDiskstream::set_roll_delay (jack_nframes_t nframes)
-{
-       _roll_delay = nframes;
-}
-
-void
-AudioDiskstream::set_destructive (bool yn)
-{
-       if (yn != destructive()) {
-               reset_write_sources (true, true);
-               if (yn) {
-                       _flags |= Destructive;
-               } else {
-                       _flags &= ~Destructive;
-               }
-       }
-}
index 7f421e86c817dc4074aa19cdbfed9e29bc98a55d..ad008f6312d4463444fe2db8b3929bcdb1184d02 100644 (file)
@@ -46,6 +46,8 @@ using namespace PBD;
 
 static char* SOUNDFILE = "http://ardour.org/ontology/Soundfile";
 
+string AudioLibrary::state_node_name = "AudioLibrary";
+
 AudioLibrary::AudioLibrary ()
 {
 //     sfdb_paths.push_back("/Users/taybin/sounds");
@@ -74,8 +76,6 @@ AudioLibrary::AudioLibrary ()
        } 
 
        lrdf_free_statements(matches);
-
-       scan_paths();
 }
 
 AudioLibrary::~AudioLibrary ()
@@ -356,6 +356,8 @@ void
 AudioLibrary::set_paths (vector<string> paths)
 {
        sfdb_paths = paths;
+       
+       scan_paths ();
 }
 
 vector<string> 
@@ -429,5 +431,50 @@ AudioLibrary::safe_file_extension(string file)
         file.rfind(".maud")== string::npos &&
         file.rfind(".vwe") == string::npos &&
         file.rfind(".paf") == string::npos &&
+#ifdef HAVE_COREAUDIO
+               file.rfind(".mp3") == string::npos &&
+               file.rfind(".aac") == string::npos &&
+               file.rfind(".mp4") == string::npos &&
+#endif // HAVE_COREAUDIO
         file.rfind(".voc") == string::npos);
 }
+
+XMLNode&
+AudioLibrary::get_state ()
+{
+       XMLNode* root = new XMLNode(X_("AudioLibrary"));
+       
+       for (vector<string>::iterator i = sfdb_paths.begin(); i != sfdb_paths.end(); ++i) {
+               XMLNode* node = new XMLNode(X_("Path"));
+               node->add_property("value", *i);
+               root->add_child_nocopy(*node);
+       }
+       
+       return *root;
+}
+
+int
+AudioLibrary::set_state (const XMLNode& node)
+{
+       if (node.name() != X_("AudioLibrary")) {
+               fatal << "programming error: AudioLibrary: incorrect XML node sent to set_state()" << endmsg;
+               return -1;
+       }
+       
+       XMLNodeList nodes = node.children(X_("Path"));
+       
+       vector<string> paths;
+       XMLProperty* prop;
+       XMLNode* child;
+       for (XMLNodeConstIterator iter = nodes.begin(); iter != nodes.end(); ++iter) {
+               child = *iter;
+               
+               if ((prop = child->property(X_("value"))) != 0) {
+                       paths.push_back(prop->value());
+               }
+       }
+       
+       set_paths (paths);
+       
+       return 0;
+}
index 85c11647f45e34ceb97953738beeae68a0943b36..93d380679d9e396ef43e961bdf7a099c9a6b1785 100644 (file)
@@ -243,16 +243,18 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, ch
 
        for (vector<uint32_t>::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) {
 
+               // FIXME: Should be vector<AudioRegion*>
                vector<Region*>& r (relevant_regions[*l]);
                vector<Crossfade*>& x (relevant_xfades[*l]);
 
                for (vector<Region*>::iterator i = r.begin(); i != r.end(); ++i) {
-                       (*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n, read_frames, skip_frames);
-                       _read_data_count += (*i)->read_data_count();
+                       AudioRegion* const ar = dynamic_cast<AudioRegion*>(*i);
+                       assert(ar);
+                       ar->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n, read_frames, skip_frames);
+                       _read_data_count += ar->read_data_count();
                }
                
                for (vector<Crossfade*>::iterator i = x.begin(); i != x.end(); ++i) {
-                       
                        (*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n);
 
                        /* don't JACK up _read_data_count, since its the same data as we just
@@ -880,38 +882,6 @@ AudioPlaylist::crossfade_changed (Change ignored)
        notify_modified ();
 }
 
-void
-AudioPlaylist::get_equivalent_regions (const AudioRegion& other, vector<AudioRegion*>& results)
-{
-       for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
-
-               AudioRegion* ar = dynamic_cast<AudioRegion*> (*i);
-
-               if (ar) {
-                       if (Config->get_use_overlap_equivalency()) {
-                               if (ar->overlap_equivalent (other)) {
-                                       results.push_back (ar);
-                               } else if (ar->equivalent (other)) {
-                                       results.push_back (ar);
-                               }
-                       }
-               }
-       }
-}
-
-void
-AudioPlaylist::get_region_list_equivalent_regions (const AudioRegion& other, vector<AudioRegion*>& results)
-{
-       for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
-
-               AudioRegion* ar = dynamic_cast<AudioRegion*> (*i);
-               
-               if (ar && ar->region_list_equivalent (other)) {
-                       results.push_back (ar);
-               }
-       }
-}
-
 bool
 AudioPlaylist::region_changed (Change what_changed, Region* region)
 {
index 74b7dd071ca4d405ddba8f582e09a91d4704de7b..78af23e3df8bf7cdea43b2f2ad91dc5fbe8b02ae 100644 (file)
@@ -41,9 +41,7 @@ using namespace ARDOUR;
 using namespace PBD;
 
 AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
-       : Route (sess, name, 1, -1, -1, -1, flag),
-         diskstream (0),
-         _midi_rec_enable_control (*this, _session.midi_port())
+       : Track (sess, name, flag, mode)
 {
        AudioDiskstream::Flag dflags = AudioDiskstream::Flag (0);
 
@@ -59,54 +57,34 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
 
        AudioDiskstream* ds = new AudioDiskstream (_session, name, dflags);
        
-       _declickable = true;
-       _freeze_record.state = NoFreeze;
-       _saved_meter_point = _meter_point;
-       _mode = mode;
-
        set_diskstream (*ds, this);
-
-       // session.SMPTEOffsetChanged.connect (mem_fun (*this, &AudioTrack::handle_smpte_offset_change));
-
-       // we do this even though Route already did it in it's init
-       reset_midi_control (_session.midi_port(), _session.get_midi_control());
-       
 }
 
 AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
-       : Route (sess, "to be renamed", 0, 0, -1, -1),
-         diskstream (0),
-         _midi_rec_enable_control (*this, _session.midi_port())
+       : Track (sess, node)
 {
-       _freeze_record.state = NoFreeze;
        set_state (node);
-       _declickable = true;
-       _saved_meter_point = _meter_point;
-
-       // we do this even though Route already did it in it's init
-       reset_midi_control (_session.midi_port(), _session.get_midi_control());
 }
 
 AudioTrack::~AudioTrack ()
 {
-       if (diskstream) {
-               diskstream->unref();
-       }
 }
 
 int
 AudioTrack::deprecated_use_diskstream_connections ()
 {
-       if (diskstream->deprecated_io_node == 0) {
+       AudioDiskstream& diskstream = audio_diskstream();
+
+       if (diskstream.deprecated_io_node == 0) {
                return 0;
        }
 
        const XMLProperty* prop;
-       XMLNode& node (*diskstream->deprecated_io_node);
+       XMLNode& node (*diskstream.deprecated_io_node);
 
        /* don't do this more than once. */
 
-       diskstream->deprecated_io_node = 0;
+       diskstream.deprecated_io_node = 0;
 
        set_input_minimum (-1);
        set_input_maximum (-1);
@@ -149,15 +127,15 @@ AudioTrack::deprecated_use_diskstream_connections ()
 int
 AudioTrack::set_diskstream (AudioDiskstream& ds, void *src)
 {
-       if (diskstream) {
-               diskstream->unref();
+       if (_diskstream) {
+               _diskstream->unref();
        }
 
-       diskstream = &ds.ref();
-       diskstream->set_io (*this);
-       diskstream->set_destructive (_mode == Destructive);
+       _diskstream = &ds.ref();
+       _diskstream->set_io (*this);
+       _diskstream->set_destructive (_mode == Destructive);
 
-       if (diskstream->deprecated_io_node) {
+       if (audio_diskstream().deprecated_io_node) {
 
                if (!connecting_legal) {
                        ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
@@ -166,13 +144,13 @@ AudioTrack::set_diskstream (AudioDiskstream& ds, void *src)
                }
        }
 
-       diskstream->set_record_enabled (false, this);
-       diskstream->monitor_input (false);
+       _diskstream->set_record_enabled (false);
+       _diskstream->monitor_input (false);
 
        ic_connection.disconnect();
-       ic_connection = input_changed.connect (mem_fun (*diskstream, &AudioDiskstream::handle_input_change));
+       ic_connection = input_changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change));
 
-       diskstream_changed (src); /* EMIT SIGNAL */
+       DiskstreamChanged (); /* EMIT SIGNAL */
 
        return 0;
 }      
@@ -182,8 +160,8 @@ AudioTrack::use_diskstream (string name)
 {
        AudioDiskstream *dstream;
 
-       if ((dstream = _session.diskstream_by_name (name)) == 0) {
-         error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), name) << endmsg;
+       if ((dstream = dynamic_cast<AudioDiskstream*>(_session.diskstream_by_name (name))) == 0) {
+         error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg;
                return -1;
        }
        
@@ -191,60 +169,22 @@ AudioTrack::use_diskstream (string name)
 }
 
 int 
-AudioTrack::use_diskstream (id_t id)
+AudioTrack::use_diskstream (const PBD::ID& id)
 {
        AudioDiskstream *dstream;
 
-       if ((dstream = _session.diskstream_by_id (id)) == 0) {
-               error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), id) << endmsg;
+       if ((dstream = dynamic_cast<AudioDiskstream*>(_session.diskstream_by_id (id))) == 0) {
+               error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg;
                return -1;
        }
        
        return set_diskstream (*dstream, this);
 }
 
-bool
-AudioTrack::record_enabled () const
+AudioDiskstream&
+AudioTrack::audio_diskstream() const
 {
-       return diskstream->record_enabled ();
-}
-
-void
-AudioTrack::set_record_enable (bool yn, void *src)
-{
-       if (_freeze_record.state == Frozen) {
-               return;
-       }
-
-       if (_mix_group && src != _mix_group && _mix_group->is_active()) {
-               _mix_group->apply (&AudioTrack::set_record_enable, yn, _mix_group);
-               return;
-       }
-
-       /* keep track of the meter point as it was before we rec-enabled */
-
-       if (!diskstream->record_enabled()) {
-               _saved_meter_point = _meter_point;
-       }
-       
-       diskstream->set_record_enabled (yn, src);
-
-       if (diskstream->record_enabled()) {
-               set_meter_point (MeterInput, this);
-       } else {
-               set_meter_point (_saved_meter_point, this);
-       }
-
-       if (_session.get_midi_feedback()) {
-               _midi_rec_enable_control.send_feedback (record_enabled());
-       }
-
-}
-
-void
-AudioTrack::set_meter_point (MeterPoint p, void *src)
-{
-       Route::set_meter_point (p, src);
+       return *dynamic_cast<AudioDiskstream*>(_diskstream);
 }
 
 int
@@ -252,7 +192,6 @@ AudioTrack::set_state (const XMLNode& node)
 {
        const XMLProperty *prop;
        XMLNodeConstIterator iter;
-       XMLNodeList midi_kids;
 
        if (Route::set_state (node)) {
                return -1;
@@ -271,36 +210,6 @@ AudioTrack::set_state (const XMLNode& node)
                _mode = Normal;
        }
 
-       midi_kids = node.children ("MIDI");
-       
-       for (iter = midi_kids.begin(); iter != midi_kids.end(); ++iter) {
-       
-               XMLNodeList kids;
-               XMLNodeConstIterator miter;
-               XMLNode*    child;
-
-               kids = (*iter)->children ();
-
-               for (miter = kids.begin(); miter != kids.end(); ++miter) {
-
-                       child =* miter;
-
-                       if (child->name() == "rec_enable") {
-                       
-                               MIDI::eventType ev = MIDI::on; /* initialize to keep gcc happy */
-                               MIDI::byte additional = 0;  /* ditto */
-                               MIDI::channel_t chn = 0;    /* ditto */
-
-                               if (get_midi_node_info (child, ev, chn, additional)) {
-                                       _midi_rec_enable_control.set_control_type (chn, ev, additional);
-                               } else {
-                                 error << string_compose(_("MIDI rec_enable control specification for %1 is incomplete, so it has been ignored"), _name) << endmsg;
-                               }
-                       }
-               }
-       }
-
-       
        if ((prop = node.property ("diskstream-id")) == 0) {
                
                /* some old sessions use the diskstream name rather than the ID */
@@ -317,7 +226,7 @@ AudioTrack::set_state (const XMLNode& node)
 
        } else {
                
-               id_t id = strtoull (prop->value().c_str(), 0, 10);
+               PBD::ID id (prop->value());
                
                if (use_diskstream (id)) {
                        return -1;
@@ -349,24 +258,12 @@ AudioTrack::set_state (const XMLNode& node)
        return 0;
 }
 
-XMLNode&
-AudioTrack::get_template ()
-{
-       return state (false);
-}
-
-XMLNode&
-AudioTrack::get_state ()
-{
-       return state (true);
-}
-
 XMLNode& 
 AudioTrack::state(bool full_state)
 {
        XMLNode& root (Route::state(full_state));
        XMLNode* freeze_node;
-       char buf[32];
+       char buf[64];
 
        if (_freeze_record.playlist) {
                XMLNode* inode;
@@ -378,7 +275,7 @@ AudioTrack::state(bool full_state)
 
                for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
                        inode = new XMLNode (X_("insert"));
-                       snprintf (buf, sizeof (buf), "%" PRIu64, (*i)->id);
+                       (*i)->id.print (buf);
                        inode->add_property (X_("id"), buf);
                        inode->add_child_copy ((*i)->state);
                
@@ -391,7 +288,7 @@ AudioTrack::state(bool full_state)
        /* Alignment: act as a proxy for the diskstream */
        
        XMLNode* align_node = new XMLNode (X_("alignment"));
-       switch (diskstream->alignment_style()) {
+       switch (_diskstream->alignment_style()) {
        case ExistingMaterial:
                snprintf (buf, sizeof (buf), X_("existing"));
                break;
@@ -402,29 +299,6 @@ AudioTrack::state(bool full_state)
        align_node->add_property (X_("style"), buf);
        root.add_child_nocopy (*align_node);
 
-       /* MIDI control */
-
-       MIDI::channel_t chn;
-       MIDI::eventType ev;
-       MIDI::byte      additional;
-       XMLNode*        midi_node = 0;
-       XMLNode*        child;
-       XMLNodeList     midikids;
-
-       midikids = root.children ("MIDI");
-       if (!midikids.empty()) {
-               midi_node = midikids.front();
-       }
-       else {
-               midi_node = root.add_child ("MIDI");
-       }
-               
-       if (_midi_rec_enable_control.get_control_info (chn, ev, additional) && midi_node) {
-
-               child = midi_node->add_child ("rec_enable");
-               set_midi_node_info (child, ev, chn, additional);
-       }
-
        XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
        snprintf (buf, sizeof (buf), "%d", _remote_control_id);
        remote_control_node->add_property (X_("id"), buf);
@@ -445,7 +319,7 @@ AudioTrack::state(bool full_state)
           diskstream.
        */
 
-       snprintf (buf, sizeof (buf), "%" PRIu64, diskstream->id());
+       _diskstream->id().print (buf);
        root.add_property ("diskstream-id", buf);
 
        return root;
@@ -504,9 +378,9 @@ AudioTrack::set_state_part_two ()
                                continue;
                        }
                        
-                       FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()));
-                       frii->insert = 0;
-                       sscanf (prop->value().c_str(), "%" PRIu64, &frii->id);
+                       FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()),
+                                                                                  boost::shared_ptr<Insert>());
+                       frii->id = prop->value ();
                        _freeze_record.insert_info.push_back (frii);
                }
        }
@@ -517,9 +391,9 @@ AudioTrack::set_state_part_two ()
 
                if ((prop = fnode->property (X_("style"))) != 0) {
                        if (prop->value() == "existing") {
-                               diskstream->set_persistent_align_style (ExistingMaterial);
+                               _diskstream->set_persistent_align_style (ExistingMaterial);
                        } else if (prop->value() == "capture") {
-                               diskstream->set_persistent_align_style (CaptureTime);
+                               _diskstream->set_persistent_align_style (CaptureTime);
                        }
                }
        }
@@ -529,7 +403,7 @@ AudioTrack::set_state_part_two ()
 uint32_t
 AudioTrack::n_process_buffers ()
 {
-       return max ((uint32_t) diskstream->n_channels(), redirect_max_outs);
+       return max ((uint32_t) _diskstream->n_channels(), redirect_max_outs);
 }
 
 void
@@ -560,7 +434,7 @@ AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nf
                return 0;
        }
 
-       diskstream->check_record_status (start_frame, nframes, can_record);
+       audio_diskstream().check_record_status (start_frame, nframes, can_record);
 
        bool send_silence;
        
@@ -579,7 +453,7 @@ AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nf
                                send_silence = true;
                        }
                } else {
-                       if (diskstream->record_enabled()) {
+                       if (_diskstream->record_enabled()) {
                                if (Config->get_use_sw_monitoring()) {
                                        send_silence = false;
                                } else {
@@ -627,7 +501,8 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
        Sample* b;
        Sample* tmpb;
        jack_nframes_t transport_frame;
-
+       AudioDiskstream& diskstream = audio_diskstream();
+       
        {
                Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
                if (lm.locked()) {
@@ -653,13 +528,13 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
                   playback distance to zero, thus causing diskstream::commit
                   to do nothing.
                */
-               return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
+               return diskstream.process (transport_frame, 0, 0, can_record, rec_monitors_input);
        } 
 
        _silent = false;
        apply_gain_automation = false;
 
-       if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
+       if ((dret = diskstream.process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
                
                silence (nframes, offset);
 
@@ -672,7 +547,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
                just_meter_input (start_frame, end_frame, nframes, offset);
        }
 
-       if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
+       if (diskstream.record_enabled() && !can_record && !_session.get_auto_input()) {
 
                /* not actually recording, but we want to hear the input material anyway,
                   at least potentially (depending on monitoring options)
@@ -680,7 +555,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
 
                passthru (start_frame, end_frame, nframes, offset, 0, true);
 
-       } else if ((b = diskstream->playback_buffer(0)) != 0) {
+       } else if ((b = diskstream.playback_buffer(0)) != 0) {
 
                /*
                  XXX is it true that the earlier test on n_outputs()
@@ -702,8 +577,8 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
 
                for (i = 0, n = 1; i < limit; ++i, ++n) {
                        memcpy (bufs[i], b, sizeof (Sample) * nframes); 
-                       if (n < diskstream->n_channels()) {
-                               tmpb = diskstream->playback_buffer(n);
+                       if (n < diskstream.n_channels()) {
+                               tmpb = diskstream.playback_buffer(n);
                                if (tmpb!=0) {
                                        b = tmpb;
                                }
@@ -712,7 +587,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
 
                /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
 
-               if (!diskstream->record_enabled() && _session.transport_rolling()) {
+               if (!diskstream.record_enabled() && _session.transport_rolling()) {
                        Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
                        
                        if (am.locked() && gain_automation_playback()) {
@@ -748,37 +623,7 @@ AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jac
 
        silence (nframes, offset);
 
-       return diskstream->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
-}
-
-void
-AudioTrack::toggle_monitor_input ()
-{
-       for (vector<Port*>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
-               (*i)->request_monitor_input(!(*i)->monitoring_input());
-       }
-}
-
-int
-AudioTrack::set_name (string str, void *src)
-{
-       int ret;
-
-       if (record_enabled() && _session.actively_recording()) {
-               /* this messes things up if done while recording */
-               return -1;
-       }
-
-       if (diskstream->set_name (str, src)) {
-               return -1;
-       }
-
-       /* save state so that the statefile fully reflects any filename changes */
-
-       if ((ret = IO::set_name (str, src)) == 0) {
-               _session.save_state ("");
-       }
-       return ret;
+       return audio_diskstream().process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
 }
 
 int
@@ -792,10 +637,15 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbu
        gain_t this_gain = _gain;
        vector<Sample*>::iterator bi;
        Sample * b;
+       AudioDiskstream& diskstream = audio_diskstream();
        
        Glib::RWLock::ReaderLock rlock (redirect_lock);
-               
-       if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) {
+
+       // FIXME
+       AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(diskstream.playlist());
+       assert(apl);
+
+       if (apl->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) {
                return -1;
        }
 
@@ -804,8 +654,8 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbu
        b = buffers[0];
        ++bi;
        for (; bi != buffers.end(); ++bi, ++n) {
-               if (n < diskstream->n_channels()) {
-                       if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) {
+               if (n < diskstream.n_channels()) {
+                       if (apl->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) {
                                return -1;
                        }
                        b = (*bi);
@@ -822,9 +672,9 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbu
        */
        
        for (i = _redirects.begin(); i != _redirects.end(); ++i) {
-               Insert *insert;
+               boost::shared_ptr<Insert> insert;
                
-               if ((insert = dynamic_cast<Insert*>(*i)) != 0) {
+               if ((insert = boost::dynamic_pointer_cast<Insert>(*i)) != 0) {
                        switch (insert->placement()) {
                        case PreFader:
                                insert->run (buffers, nbufs, nframes, 0);
@@ -860,9 +710,9 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbu
        if (post_fader_work) {
 
                for (i = _redirects.begin(); i != _redirects.end(); ++i) {
-                       PluginInsert *insert;
+                       boost::shared_ptr<PluginInsert> insert;
                        
-                       if ((insert = dynamic_cast<PluginInsert*>(*i)) != 0) {
+                       if ((insert = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
                                switch ((*i)->placement()) {
                                case PreFader:
                                        break;
@@ -877,29 +727,6 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, char * workbuf, uint32_t nbu
        return 0;
 }
 
-void
-AudioTrack::set_latency_delay (jack_nframes_t longest_session_latency)
-{
-       Route::set_latency_delay (longest_session_latency);
-       diskstream->set_roll_delay (_roll_delay);
-}
-
-jack_nframes_t
-AudioTrack::update_total_latency ()
-{
-       _own_latency = 0;
-
-       for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
-               if ((*i)->active ()) {
-                       _own_latency += (*i)->latency ();
-               }
-       }
-
-       set_port_latency (_own_latency);
-
-       return _own_latency;
-}
-
 void
 AudioTrack::bounce (InterThreadInfo& itt)
 {
@@ -918,15 +745,15 @@ AudioTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadI
 void
 AudioTrack::freeze (InterThreadInfo& itt)
 {
-       Insert* insert;
        vector<AudioSource*> srcs;
        string new_playlist_name;
        Playlist* new_playlist;
        string dir;
        AudioRegion* region;
        string region_name;
+       AudioDiskstream& diskstream = audio_diskstream();
        
-       if ((_freeze_record.playlist = diskstream->playlist()) == 0) {
+       if ((_freeze_record.playlist = dynamic_cast<AudioPlaylist*>(diskstream.playlist())) == 0) {
                return;
        }
 
@@ -948,7 +775,7 @@ AudioTrack::freeze (InterThreadInfo& itt)
        } 
 
        if (n == (UINT_MAX-1)) {
-         error << string_compose (X_("There Are too many frozen versions of playlist \"%1\""
+         error << string_compose (X_("There are too many frozen versions of playlist \"%1\""
                            " to create another one"), _freeze_record.playlist->name())
               << endmsg;
                return;
@@ -966,11 +793,12 @@ AudioTrack::freeze (InterThreadInfo& itt)
                
                for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); ++r) {
                        
-                       if ((insert = dynamic_cast<Insert*>(*r)) != 0) {
+                       boost::shared_ptr<Insert> insert;
+
+                       if ((insert = boost::dynamic_pointer_cast<Insert>(*r)) != 0) {
                                
-                               FreezeRecordInsertInfo* frii  = new FreezeRecordInsertInfo ((*r)->get_state());
+                               FreezeRecordInsertInfo* frii  = new FreezeRecordInsertInfo ((*r)->get_state(), insert);
                                
-                               frii->insert = insert;
                                frii->id = insert->id();
                                frii->memento = (*r)->get_memento();
                                
@@ -993,13 +821,13 @@ AudioTrack::freeze (InterThreadInfo& itt)
                                  (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
                                  false);
 
-       new_playlist->set_orig_diskstream_id (diskstream->id());
+       new_playlist->set_orig_diskstream_id (diskstream.id());
        new_playlist->add_region (*region, 0);
        new_playlist->set_frozen (true);
        region->set_locked (true);
 
-       diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
-       diskstream->set_record_enabled (false, this);
+       diskstream.use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
+       diskstream.set_record_enabled (false);
 
        _freeze_record.state = Frozen;
        FreezeChange(); /* EMIT SIGNAL */
@@ -1009,7 +837,7 @@ void
 AudioTrack::unfreeze ()
 {
        if (_freeze_record.playlist) {
-               diskstream->use_playlist (_freeze_record.playlist);
+               audio_diskstream().use_playlist (_freeze_record.playlist);
 
                if (_freeze_record.have_mementos) {
 
@@ -1037,116 +865,3 @@ AudioTrack::unfreeze ()
        FreezeChange (); /* EMIT SIGNAL */
 }
 
-AudioTrack::FreezeRecord::~FreezeRecord ()
-{
-       for (vector<FreezeRecordInsertInfo*>::iterator i = insert_info.begin(); i != insert_info.end(); ++i) {
-               delete *i;
-       }
-}
-
-AudioTrack::FreezeState
-AudioTrack::freeze_state() const
-{
-       return _freeze_record.state;
-}
-
-
-void
-AudioTrack::reset_midi_control (MIDI::Port* port, bool on)
-{
-       MIDI::channel_t chn;
-       MIDI::eventType ev;
-       MIDI::byte extra;
-
-       Route::reset_midi_control (port, on);
-       
-       _midi_rec_enable_control.get_control_info (chn, ev, extra);
-       if (!on) {
-               chn = -1;
-       }
-       _midi_rec_enable_control.midi_rebind (port, chn);
-}
-
-void
-AudioTrack::send_all_midi_feedback ()
-{
-       if (_session.get_midi_feedback()) {
-
-               Route::send_all_midi_feedback();
-
-               _midi_rec_enable_control.send_feedback (record_enabled());
-       }
-}
-
-
-AudioTrack::MIDIRecEnableControl::MIDIRecEnableControl (AudioTrack& s,  MIDI::Port* port)
-       : MIDI::Controllable (port, 0), track (s), setting(false)
-{
-       last_written = false; /* XXX need a good out of bound value */
-}
-
-void
-AudioTrack::MIDIRecEnableControl::set_value (float val)
-{
-       bool bval = ((val >= 0.5f) ? true: false);
-       
-       setting = true;
-       track.set_record_enable (bval, this);
-       setting = false;
-}
-
-void
-AudioTrack::MIDIRecEnableControl::send_feedback (bool value)
-{
-
-       if (!setting && get_midi_feedback()) {
-               MIDI::byte val = (MIDI::byte) (value ? 127: 0);
-               MIDI::channel_t ch = 0;
-               MIDI::eventType ev = MIDI::none;
-               MIDI::byte additional = 0;
-               MIDI::EventTwoBytes data;
-           
-               if (get_control_info (ch, ev, additional)) {
-                       data.controller_number = additional;
-                       data.value = val;
-
-                       track._session.send_midi_message (get_port(), ev, ch, data);
-               }
-       }
-       
-}
-
-MIDI::byte*
-AudioTrack::MIDIRecEnableControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force)
-{
-       if (get_midi_feedback()) {
-
-               MIDI::channel_t ch = 0;
-               MIDI::eventType ev = MIDI::none;
-               MIDI::byte additional = 0;
-
-               if (get_control_info (ch, ev, additional)) {
-                       if (val != last_written || force) {
-                               *buf++ = ev & ch;
-                               *buf++ = additional; /* controller number */
-                               *buf++ = (MIDI::byte) (val ? 127: 0);
-                               last_written = val;
-                               bufsize -= 3;
-                       }
-               }
-       }
-
-       return buf;
-}
-
-void
-AudioTrack::set_mode (TrackMode m)
-{
-       if (diskstream) {
-               if (_mode != m) {
-                       _mode = m;
-                       diskstream->set_destructive (m == Destructive);
-                       ModeChanged();
-               }
-       }
-}
diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc
new file mode 100644 (file)
index 0000000..0756f55
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+    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 <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;
+
+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 ()
+{
+       if (unit) {
+               unit->Uninitialize ();
+               delete unit;
+       }
+       
+       if (comp) {
+               delete comp;
+       }
+}
+
+AUPluginInfo::~AUPluginInfo ()
+{
+       if (desc) {
+               delete desc;
+       }
+}
+
+uint32_t
+AUPlugin::unique_id () const
+{
+       return 0;
+}
+
+const char *
+AUPlugin::label () const
+{
+       return "";
+}
+
+const char *
+AUPlugin::maker () const
+{
+       return "";
+}
+
+uint32_t
+AUPlugin::parameter_count () const
+{
+       return 0;
+}
+
+float
+AUPlugin::default_value (uint32_t port)
+{
+       return 0.0;
+}
+
+jack_nframes_t
+AUPlugin::latency () const
+{
+       return 0;
+}
+
+void
+AUPlugin::set_parameter (uint32_t which, float val)
+{
+       
+}
+
+float
+AUPlugin::get_parameter (uint32_t which) const
+{
+       return 0.0;
+}
+
+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 ()
+{
+       
+}
+
+void
+AUPlugin::deactivate ()
+{
+       
+}
+
+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)
+{
+       return -1;
+}
+
+set<uint32_t>
+AUPlugin::automatable() const
+{
+       set<uint32_t> automates;
+       
+       return automates;
+}
+
+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;
+       }
+
+       catch (failed_constructor &err) {
+               return PluginPtr ((Plugin*) 0);
+       }
+}
+
+PluginInfoList
+AUPluginInfo::discover ()
+{
+       PluginInfoList plugs;
+
+       int numTypes = 2;    // this magic number was retrieved from the apple AUHost example.
+
+       CAComponentDescription desc;
+       desc.componentFlags = 0;
+       desc.componentFlagsMask = 0;
+       desc.componentSubType = 0;
+       desc.componentManufacturer = 0;
+
+       for (int i = 0; i < numTypes; ++i) {
+               if (i == 1) {
+                       desc.componentType = kAudioUnitType_MusicEffect;
+               } else {
+                       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 = 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 5a5e20053187db19c0d33ddb07cc12765f72ad3a..982a7c5971cb0fa0c718444fd6e32a97d608aeb1 100644 (file)
@@ -26,6 +26,7 @@
 #include <pbd/pthread_utils.h>
 
 #include <ardour/audioengine.h>
+#include <ardour/buffer.h>
 #include <ardour/port.h>
 #include <ardour/session.h>
 #include <ardour/cycle_timer.h>
@@ -42,8 +43,8 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-jack_nframes_t Port::short_over_length = 2;
-jack_nframes_t Port::long_over_length = 10;
+jack_nframes_t Port::_short_over_length = 2;
+jack_nframes_t Port::_long_over_length = 10;
 
 AudioEngine::AudioEngine (string client_name) 
 {
@@ -274,8 +275,8 @@ AudioEngine::process_callback (jack_nframes_t nframes)
                        Port *port = (*i);
                        bool x;
                        
-                       if (port->last_monitor != (x = port->monitoring_input ())) {
-                               port->last_monitor = x;
+                       if (port->_last_monitor != (x = port->monitoring_input ())) {
+                               port->_last_monitor = x;
                                /* XXX I think this is dangerous, due to 
                                   a likely mutex in the signal handlers ...
                                */
@@ -388,18 +389,19 @@ AudioEngine::remove_session ()
 }
 
 Port *
-AudioEngine::register_audio_input_port (const string& portname)
+AudioEngine::register_input_port (DataType type, const string& portname)
 {
        if (!_running) {
                if (!_has_run) {
-                       fatal << _("register audio input port called before engine was started") << endmsg;
+                       fatal << _("register input port called before engine was started") << endmsg;
                        /*NOTREACHED*/
                } else {
                        return 0;
                }
        }
 
-       jack_port_t *p = jack_port_register (_jack, portname.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+       jack_port_t *p = jack_port_register (_jack, portname.c_str(),
+               type.to_jack_type(), JackPortIsInput, 0);
 
        if (p) {
 
@@ -419,11 +421,11 @@ AudioEngine::register_audio_input_port (const string& portname)
 }
 
 Port *
-AudioEngine::register_audio_output_port (const string& portname)
+AudioEngine::register_output_port (DataType type, const string& portname)
 {
        if (!_running) {
                if (!_has_run) {
-                       fatal << _("register audio output port called before engine was started") << endmsg;
+                       fatal << _("register output port called before engine was started") << endmsg;
                        /*NOTREACHED*/
                } else {
                        return 0;
@@ -432,7 +434,8 @@ AudioEngine::register_audio_output_port (const string& portname)
 
        jack_port_t *p;
 
-       if ((p = jack_port_register (_jack, portname.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) != 0) {
+       if ((p = jack_port_register (_jack, portname.c_str(),
+               type.to_jack_type(), JackPortIsOutput, 0)) != 0) {
                Port *newport = new Port (p);
                ports.insert (ports.begin(), newport);
                return newport;
@@ -446,6 +449,7 @@ AudioEngine::register_audio_output_port (const string& portname)
        return 0;
 }
 
+
 int          
 AudioEngine::unregister_port (Port *port)
 {
@@ -458,7 +462,7 @@ AudioEngine::unregister_port (Port *port)
 
        if (port) {
 
-               int ret = jack_port_unregister (_jack, port->port);
+               int ret = jack_port_unregister (_jack, port->_port);
                
                if (ret == 0) {
 
@@ -549,7 +553,7 @@ AudioEngine::disconnect (Port *port)
                }
        }
 
-       int ret = jack_port_disconnect (_jack, port->port);
+       int ret = jack_port_disconnect (_jack, port->_port);
 
        if (ret == 0) {
                remove_connections_for (port);
@@ -699,7 +703,6 @@ AudioEngine::n_physical_inputs () const
 }
 
 string
-
 AudioEngine::get_nth_physical (uint32_t n, int flag)
 {
        const char ** ports;
@@ -747,7 +750,7 @@ AudioEngine::get_port_total_latency (const Port& port)
                } 
        }
 
-       return jack_port_get_total_latency (_jack, port.port);
+       return jack_port_get_total_latency (_jack, port._port);
 }
 
 void
@@ -825,7 +828,7 @@ AudioEngine::remove_all_ports ()
 
        if (_jack) {
                for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
-                       jack_port_unregister (_jack, (*i)->port);
+                       jack_port_unregister (_jack, (*i)->_port);
                }
        }
 
@@ -948,7 +951,7 @@ AudioEngine::reconnect_to_jack ()
                
                short_name = long_name.substr (long_name.find_last_of (':') + 1);
 
-               if (((*i)->port = jack_port_register (_jack, short_name.c_str(), (*i)->type(), (*i)->flags(), 0)) == 0) {
+               if (((*i)->_port = jack_port_register (_jack, short_name.c_str(), (*i)->type(), (*i)->flags(), 0)) == 0) {
                        error << string_compose (_("could not reregister %1"), (*i)->name()) << endmsg;
                        break;
                } else {
@@ -963,7 +966,7 @@ AudioEngine::reconnect_to_jack ()
 
        if (i != ports.end()) {
                for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
-                       jack_port_unregister (_jack, (*i)->port);
+                       jack_port_unregister (_jack, (*i)->_port);
                }
                return -1;
        } 
index 0663f5f9b1047c6d11096c259cc616a018a13fa5..ee35f3068a355c52c4e99b0efe7a61c772592c18 100644 (file)
@@ -56,8 +56,7 @@ string AudioFileSource::peak_dir = "";
 string AudioFileSource::search_path;
 
 sigc::signal<void> AudioFileSource::HeaderPositionOffsetChanged;
-bool               AudioFileSource::header_position_negative;
-uint64_t           AudioFileSource::header_position_offset;
+uint64_t           AudioFileSource::header_position_offset = 0;
 
 char   AudioFileSource::bwf_country_code[3] = "US";
 char   AudioFileSource::bwf_organization_code[4] = "LAS";
@@ -214,6 +213,10 @@ AudioFileSource::create (const string& idstr, Flag flags)
 {
        AudioFileSource* es = 0;
 
+       if (flags & Destructive) {
+               return new DestructiveFileSource (idstr, flags);
+       }
+
        try {
                es = new CoreAudioSource (idstr, flags);
        }
@@ -235,25 +238,6 @@ AudioFileSource::create (const string& idstr, Flag flags)
 
 #endif // HAVE_COREAUDIO
 
-#ifdef HAVE_COREAUDIO
-std::string 
-CFStringRefToStdString(CFStringRef stringRef)
-{
-       CFIndex size = 
-               CFStringGetMaximumSizeForEncoding(CFStringGetLength(stringRef) , 
-               kCFStringEncodingASCII);
-           char *buf = new char[size];
-       
-       std::string result;
-
-       if(CFStringGetCString(stringRef, buf, size, kCFStringEncodingASCII)) {
-           result = buf;
-       }
-       delete [] buf;
-       return result;
-}
-#endif // HAVE_COREAUDIO
-
 bool
 AudioFileSource::get_soundfile_info (string path, SoundFileInfo& _info, string& error_msg)
 {
@@ -592,23 +576,13 @@ AudioFileSource::set_search_path (string p)
 }
 
 void
-AudioFileSource::set_header_position_offset (jack_nframes_t offset, bool negative)
+AudioFileSource::set_header_position_offset (jack_nframes_t offset)
 {
        header_position_offset = offset;
-       header_position_negative = negative;
-
+       cerr << "hpo set to " << offset << endl;
        HeaderPositionOffsetChanged ();
 }
 
-void 
-AudioFileSource::handle_header_position_change ()
-{
-       if (writable()) {
-               set_header_timeline_position ();
-               flush_header ();
-       }
-}
-
 void
 AudioFileSource::set_timeline_position (jack_nframes_t pos)
 {
@@ -635,6 +609,12 @@ AudioFileSource::set_name (string newname, bool destructive)
                return -1;
        }
 
+       // Test whether newpath exists, if yes notify the user but continue. 
+       if (access(newpath.c_str(),F_OK) == 0) {
+               error << _("Programming error! Ardour tried to rename a file over another file! It's safe to continue working, but please report this to the developers.") << endmsg;
+               return -1;
+       }
+
        if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
                error << string_compose (_("cannot rename audio file for %1 to %2"), _name, newpath) << endmsg;
                return -1;
index 6b118faa514f57e5f0df9821cb2ff10ffe2a7a57..20d1dbfbd62dd4756924dd33213c4bbc4bbf88c9 100644 (file)
@@ -48,13 +48,13 @@ using namespace ARDOUR;
 
 /* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */
 
-Change AudioRegion::FadeInChanged = ARDOUR::new_change();
-Change AudioRegion::FadeOutChanged = ARDOUR::new_change();
-Change AudioRegion::FadeInActiveChanged = ARDOUR::new_change();
-Change AudioRegion::FadeOutActiveChanged = ARDOUR::new_change();
+Change AudioRegion::FadeInChanged         = ARDOUR::new_change();
+Change AudioRegion::FadeOutChanged        = ARDOUR::new_change();
+Change AudioRegion::FadeInActiveChanged   = ARDOUR::new_change();
+Change AudioRegion::FadeOutActiveChanged  = ARDOUR::new_change();
 Change AudioRegion::EnvelopeActiveChanged = ARDOUR::new_change();
 Change AudioRegion::ScaleAmplitudeChanged = ARDOUR::new_change();
-Change AudioRegion::EnvelopeChanged = ARDOUR::new_change();
+Change AudioRegion::EnvelopeChanged       = ARDOUR::new_change();
 
 AudioRegionState::AudioRegionState (string why)
        : RegionState (why),
@@ -267,8 +267,6 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
          _fade_out (0.0, 2.0, 1.0, false),
          _envelope (0.0, 2.0, 1.0, false)
 {
-       /* basic AudioRegion constructor */
-
        set<AudioSource*> unique_srcs;
 
        for (SourceList::iterator i=srcs.begin(); i != srcs.end(); ++i) {
@@ -635,12 +633,6 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
        return to_read;
 }
        
-XMLNode&
-AudioRegion::get_state ()
-{
-       return state (true);
-}
-
 XMLNode&
 AudioRegion::state (bool full)
 {
@@ -652,12 +644,12 @@ AudioRegion::state (bool full)
        
        snprintf (buf, sizeof (buf), "0x%x", (int) _flags);
        node.add_property ("flags", buf);
-       snprintf (buf, sizeof(buf), "%f", _scale_amplitude);
+       snprintf (buf, sizeof(buf), "%.12g", _scale_amplitude);
        node.add_property ("scale-gain", buf);
 
        for (uint32_t n=0; n < sources.size(); ++n) {
                snprintf (buf2, sizeof(buf2), "source-%d", n);
-               snprintf (buf, sizeof(buf), "%" PRIu64, sources[n]->id());
+               sources[n]->id().print (buf);
                node.add_property (buf2, buf);
        }
 
@@ -1141,24 +1133,22 @@ AudioRegion::master_source_names ()
 }
 
 bool
-AudioRegion::region_list_equivalent (const AudioRegion& other) const
+AudioRegion::source_equivalent (const Region& o) const
 {
-       return size_equivalent (other) && source_equivalent (other) && _name == other._name;
-}
+       const AudioRegion* other = dynamic_cast<const AudioRegion*>(&o);
+       if (!other)
+               return false;
 
-bool
-AudioRegion::source_equivalent (const AudioRegion& other) const
-{
        SourceList::const_iterator i;
        SourceList::const_iterator io;
 
-       for (i = sources.begin(), io = other.sources.begin(); i != sources.end() && io != other.sources.end(); ++i, ++io) {
+       for (i = sources.begin(), io = other->sources.begin(); i != sources.end() && io != other->sources.end(); ++i, ++io) {
                if ((*i)->id() != (*io)->id()) {
                        return false;
                }
        }
 
-       for (i = master_sources.begin(), io = other.master_sources.begin(); i != master_sources.end() && io != other.master_sources.end(); ++i, ++io) {
+       for (i = master_sources.begin(), io = other->master_sources.begin(); i != master_sources.end() && io != other->master_sources.end(); ++i, ++io) {
                if ((*i)->id() != (*io)->id()) {
                        return false;
                }
@@ -1167,27 +1157,6 @@ AudioRegion::source_equivalent (const AudioRegion& other) const
        return true;
 }
 
-bool
-AudioRegion::overlap_equivalent (const AudioRegion& other) const
-{
-       return coverage (other.first_frame(), other.last_frame()) != OverlapNone;
-}
-
-bool
-AudioRegion::equivalent (const AudioRegion& other) const
-{
-       return _start == other._start &&
-               _position == other._position &&
-               _length == other._length;
-}
-
-bool
-AudioRegion::size_equivalent (const AudioRegion& other) const
-{
-       return _start == other._start &&
-               _length == other._length;
-}
-
 int
 AudioRegion::apply (AudioFilter& filter)
 {
@@ -1289,7 +1258,7 @@ AudioRegion::set_scale_amplitude (gain_t g)
 void
 AudioRegion::normalize_to (float target_dB)
 {
-       const jack_nframes_t blocksize = 256 * 1048;
+       const jack_nframes_t blocksize = 64 * 1024;
        Sample buf[blocksize];
        char workbuf[blocksize * 4];
        jack_nframes_t fpos;
@@ -1410,7 +1379,7 @@ AudioRegion::speed_mismatch (float sr) const
 
        float fsr = sources.front()->sample_rate();
 
-       return fsr == sr;
+       return fsr != sr;
 }
 
 extern "C" {
index add9364cadd09a1207866cac7f9f115589d6a03a..bf7a32c885a096d8ba575a0447d8f7f1a2527e3c 100644 (file)
@@ -640,7 +640,7 @@ AudioSource::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t
                                
                                to_read = min (chunksize, (_length - current_frame));
                                
-                               if ((frames_read = read_unlocked (raw_staging, current_frame, to_read, workbuf)) < 0) {
+                               if ((frames_read = read_unlocked (raw_staging, current_frame, to_read, workbuf)) == 0) {
                                        error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3")
                                                         , _name, to_read, current_frame) 
                                              << endmsg;
index 2f0b943c0e68e95827a4476b64c35946d02205d4..e48f103b9fb976b57e7bebd512d0ddaddea41ea0 100644 (file)
@@ -27,6 +27,7 @@
 #include <ardour/auditioner.h>
 #include <ardour/audioplaylist.h>
 #include <ardour/panner.h>
+#include <ardour/data_type.h>
 
 using namespace std;
 using namespace ARDOUR;
@@ -44,12 +45,12 @@ Auditioner::Auditioner (Session& s)
        defer_pan_reset ();
 
        if (left.length()) {
-               add_output_port (left, this);
+               add_output_port (left, this, DataType::AUDIO);
        }
 
        if (right.length()) {
-               disk_stream().add_channel();
-               add_output_port (right, this);
+               audio_diskstream().add_channel();
+               add_output_port (right, this, DataType::AUDIO);
        }
 
        allow_pan_reset ();
@@ -67,8 +68,12 @@ Auditioner::~Auditioner ()
 AudioPlaylist&
 Auditioner::prepare_playlist ()
 {
-       diskstream->playlist()->clear (false, false);
-       return *diskstream->playlist();
+       // FIXME auditioner is still audio-only
+       AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(_diskstream->playlist());
+       assert(apl);
+
+       apl->clear (false, false);
+       return *apl;
 }
 
 void
@@ -82,13 +87,13 @@ Auditioner::audition_current_playlist ()
        }
 
        Glib::Mutex::Lock lm (lock);
-       diskstream->seek (0);
-       length = diskstream->playlist()->get_maximum_extent();
+       _diskstream->seek (0);
+       length = _diskstream->playlist()->get_maximum_extent();
        current_frame = 0;
 
        /* force a panner reset now that we have all channels */
 
-       _panner->reset (n_outputs(), diskstream->n_channels());
+       _panner->reset (n_outputs(), _diskstream->n_channels());
 
        g_atomic_int_set (&_active, 1);
 }
@@ -108,23 +113,23 @@ Auditioner::audition_region (AudioRegion& region)
        the_region = new AudioRegion (region);
        the_region->set_position (0, this);
 
-       diskstream->playlist()->clear (true, false);
-       diskstream->playlist()->add_region (*the_region, 0, 1, false);
+       _diskstream->playlist()->clear (true, false);
+       _diskstream->playlist()->add_region (*the_region, 0, 1, false);
 
-       while (diskstream->n_channels() < the_region->n_channels()) {
-               diskstream->add_channel ();
+       while (_diskstream->n_channels() < the_region->n_channels()) {
+               audio_diskstream().add_channel ();
        }
 
-       while (diskstream->n_channels() > the_region->n_channels()) {
-               diskstream->remove_channel ();
+       while (_diskstream->n_channels() > the_region->n_channels()) {
+               audio_diskstream().remove_channel ();
        }
 
        /* force a panner reset now that we have all channels */
 
-       _panner->reset (n_outputs(), diskstream->n_channels());
+       _panner->reset (n_outputs(), _diskstream->n_channels());
 
        length = the_region->length();
-       diskstream->seek (0);
+       _diskstream->seek (0);
        current_frame = 0;
        g_atomic_int_set (&_active, 1);
 }
@@ -143,14 +148,14 @@ Auditioner::play_audition (jack_nframes_t nframes)
 
        this_nframes = min (nframes, length - current_frame);
 
-       diskstream->prepare ();
+       _diskstream->prepare ();
 
        if ((ret = roll (this_nframes, current_frame, current_frame + nframes, 0, false, false, false)) != 0) {
                silence (nframes, 0);
                return ret;
        }
 
-       need_butler = diskstream->commit (this_nframes);
+       need_butler = _diskstream->commit (this_nframes);
        current_frame += this_nframes;
 
        if (current_frame >= length) {
index a9e76ac55cc24f2b7119aa94bc648c7626a3cf72..dc1767d1e79abc2d881f52e11572b73f205dbab0 100644 (file)
@@ -1211,7 +1211,7 @@ AutomationList::store_state (XMLNode& node) const
                
                snprintf (buf, sizeof (buf), "%" PRIu32, (jack_nframes_t) floor ((*i)->when));
                pointnode->add_property ("x", buf);
-               snprintf (buf, sizeof (buf), "%f", (*i)->value);
+               snprintf (buf, sizeof (buf), "%.12g", (*i)->value);
                pointnode->add_property ("y", buf);
 
                node.add_child_nocopy (*pointnode);
index fc708f805de832b5b67d81f3c38af8b1d0722759..58da77f933105fb26e03aae22472741df1e4f9f1 100644 (file)
@@ -25,6 +25,7 @@
 #include <pbd/xml++.h>
 
 #include <ardour/ardour.h>
+#include <ardour/audio_library.h>
 #include <ardour/configuration.h>
 #include <ardour/audio_diskstream.h>
 #include <ardour/destructive_filesource.h>
@@ -178,6 +179,7 @@ Configuration::state (bool user_only)
        }
 
        root->add_child_nocopy (ControlProtocolManager::instance().get_state());
+       root->add_child_nocopy (Library->get_state());
 
        return *root;
 }
@@ -229,6 +231,8 @@ Configuration::set_state (const XMLNode& root)
 
                } else if (node->name() == ControlProtocolManager::state_node_name) {
                        _control_protocol_state = new XMLNode (*node);
+               } else if (node->name() == AudioLibrary::state_node_name) {
+                       Library->set_state (*node);
                }
        }
 
index c2fb18895322398a462e6e874dc812c46a1602cc..0370886a35b338d14bed27ae7e2c3def0d18a902 100644 (file)
@@ -49,6 +49,10 @@ ControlProtocolManager::set_session (Session& s)
                if ((*i)->requested || (*i)->mandatory) {
                        instantiate (**i);
                        (*i)->requested = false;
+
+                       if ((*i)->state) {
+                               (*i)->protocol->set_state (*(*i)->state);
+                       }
                }
        }
 }
@@ -181,6 +185,7 @@ ControlProtocolManager::control_protocol_discover (string path)
                        cpi->protocol = 0;
                        cpi->requested = false;
                        cpi->mandatory = descriptor->mandatory;
+                       cpi->state = 0;
                        
                        control_protocol_info.push_back (cpi);
                        
index 55409a8524cf631b6f6e2eec0c0918cc9b988fbf..5e9de225d450022ac39664bb0c09812287a9c503 100644 (file)
@@ -68,13 +68,13 @@ CoreAudioSource::init (const string& idstr)
        FSRef fsr;
        err = FSPathMakeRef ((UInt8*)file.c_str(), &fsr, 0);
        if (err != noErr) {
-               cerr << "FSPathMakeRef " << err << endl;
+               error << string_compose (_("Could not make reference to file: %1"), name()) << endmsg;
                throw failed_constructor();
        }
 
        err = ExtAudioFileOpen (&fsr, &af);
        if (err != noErr) {
-               cerr << "ExtAudioFileOpen " << err << endl;
+               error << string_compose (_("Could not open file: %1"), name()) << endmsg;
                ExtAudioFileDispose (af);
                throw failed_constructor();
        }
@@ -85,7 +85,7 @@ CoreAudioSource::init (const string& idstr)
        err = ExtAudioFileGetProperty(af,
                        kExtAudioFileProperty_FileDataFormat, &asbd_size, &file_asbd);
        if (err != noErr) {
-               cerr << "ExtAudioFileGetProperty1 " << err << endl;
+               error << string_compose (_("Could not get file data format for file: %1"), name()) << endmsg;
                ExtAudioFileDispose (af);
                throw failed_constructor();
        }
@@ -104,7 +104,7 @@ CoreAudioSource::init (const string& idstr)
 
        err = ExtAudioFileGetProperty(af, kExtAudioFileProperty_FileLengthFrames, &prop_size, &ca_frames);
        if (err != noErr) {
-               cerr << "ExtAudioFileGetProperty2 " << err << endl;
+               error << string_compose (_("Could not get file length for file: %1"), name()) << endmsg;
                ExtAudioFileDispose (af);
                throw failed_constructor();
        }
@@ -125,14 +125,14 @@ CoreAudioSource::init (const string& idstr)
 
        err = ExtAudioFileSetProperty (af, kExtAudioFileProperty_ClientDataFormat, asbd_size, &client_asbd);
        if (err != noErr) {
-               cerr << "ExtAudioFileSetProperty3 " << err << endl;
+               error << string_compose (_("Could not set client data format for file: %1"), name()) << endmsg;
                ExtAudioFileDispose (af);
                throw failed_constructor ();
        }
        
        if (_build_peakfiles) {
                if (initialize_peakfile (false, file)) {
-                       error << "initialize peakfile failed" << endmsg;
+                       error << string_compose(_("initialize peakfile failed for file %1"), name()) << endmsg;
                        ExtAudioFileDispose (af);
                        throw failed_constructor ();
                }
@@ -212,7 +212,24 @@ CoreAudioSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_
 float
 CoreAudioSource::sample_rate() const
 {
-       /* XXX taybin fill me in please */
+        AudioStreamBasicDescription client_asbd;
+        memset(&client_asbd, 0, sizeof(AudioStreamBasicDescription));
 
-       return 44100.0f;
+       OSStatus err = noErr;
+       size_t asbd_size = sizeof(AudioStreamBasicDescription);
+
+        err = ExtAudioFileSetProperty (af, kExtAudioFileProperty_ClientDataFormat, asbd_size, &client_asbd);
+        if (err != noErr) {
+               error << string_compose(_("Could not detect samplerate for: %1"), name()) << endmsg;
+               return 0.0;
+       }
+
+       return client_asbd.mSampleRate;
 }
+
+int
+CoreAudioSource::update_header (jack_nframes_t when, struct tm&, time_t)
+{
+       return 0;
+}
+
index 5d36c63f011818558a33499f5fecc2bbdaecde9c..dc4c074844dc7d2e7fddb1e59c7d0e4dd9332014 100644 (file)
@@ -112,7 +112,6 @@ Crossfade::Crossfade (const Playlist& playlist, XMLNode& node)
 {
        Region* r;
        XMLProperty* prop;
-       id_t id;
        LocaleGuard lg (X_("POSIX"));
 
        /* we have to find the in/out regions before we can do anything else */
@@ -122,7 +121,7 @@ Crossfade::Crossfade (const Playlist& playlist, XMLNode& node)
                throw failed_constructor();
        }
        
-       sscanf (prop->value().c_str(), "%" PRIu64, &id);
+       PBD::ID id (prop->value());
 
        if ((r = playlist.find_region (id)) == 0) {
                error << string_compose (_("Crossfade: no \"in\" region %1 found in playlist %2"), id, playlist.name())
@@ -139,10 +138,10 @@ Crossfade::Crossfade (const Playlist& playlist, XMLNode& node)
                throw failed_constructor();
        }
 
-       sscanf (prop->value().c_str(), "%" PRIu64, &id);
+       PBD::ID id2 (prop->value());
 
-       if ((r = playlist.find_region (id)) == 0) {
-               error << string_compose (_("Crossfade: no \"out\" region %1 found in playlist %2"), id, playlist.name())
+       if ((r = playlist.find_region (id2)) == 0) {
+               error << string_compose (_("Crossfade: no \"out\" region %1 found in playlist %2"), id2, playlist.name())
                      << endmsg;
                throw failed_constructor();
        }
@@ -680,9 +679,9 @@ Crossfade::get_state ()
        char buf[64];
        LocaleGuard lg (X_("POSIX"));
 
-       snprintf (buf, sizeof(buf), "%" PRIu64, _out->id());
+       _out->id().print (buf);
        node->add_property ("out", buf);
-       snprintf (buf, sizeof(buf), "%" PRIu64, _in->id());
+       _in->id().print (buf);
        node->add_property ("in", buf);
        node->add_property ("active", (_active ? "yes" : "no"));
        node->add_property ("follow-overlap", (_follow_overlap ? "yes" : "no"));
@@ -703,7 +702,7 @@ Crossfade::get_state ()
 
                snprintf (buf, sizeof (buf), "%" PRIu32, (jack_nframes_t) floor ((*ii)->when));
                pnode->add_property ("x", buf);
-               snprintf (buf, sizeof (buf), "%f", (*ii)->value);
+               snprintf (buf, sizeof (buf), "%.12g", (*ii)->value);
                pnode->add_property ("y", buf);
                child->add_child_nocopy (*pnode);
        }
@@ -717,7 +716,7 @@ Crossfade::get_state ()
 
                snprintf (buf, sizeof (buf), "%" PRIu32, (jack_nframes_t) floor ((*ii)->when));
                pnode->add_property ("x", buf);
-               snprintf (buf, sizeof (buf), "%f", (*ii)->value);
+               snprintf (buf, sizeof (buf), "%.12g", (*ii)->value);
                pnode->add_property ("y", buf);
                child->add_child_nocopy (*pnode);
        }
index cce757509a48efb592899a02db6351c29bad32ec..43fafff30a1ae0a30f289b7eb178c26786c37c26 100644 (file)
@@ -70,21 +70,33 @@ jack_nframes_t DestructiveFileSource::xfade_frames = 64;
 DestructiveFileSource::DestructiveFileSource (string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate, Flag flags)
        : SndFileSource (path, samp_format, hdr_format, rate, flags)
 {
-       xfade_buf = new Sample[xfade_frames];
+       init ();
+}
 
-       _capture_start = false;
-       _capture_end = false;
-       file_pos = 0;
+
+DestructiveFileSource::DestructiveFileSource (string path, Flag flags)
+       : SndFileSource (path, flags)
+{
+       init ();
 }
 
 DestructiveFileSource::DestructiveFileSource (const XMLNode& node)
        : SndFileSource (node)
+{
+       init ();
+}
+
+void
+DestructiveFileSource::init ()
 {
        xfade_buf = new Sample[xfade_frames];
 
        _capture_start = false;
        _capture_end = false;
        file_pos = 0;
+
+       timeline_position = header_position_offset;
+       AudioFileSource::HeaderPositionOffsetChanged.connect (mem_fun (*this, &DestructiveFileSource::handle_header_position_change));
 }
 
 DestructiveFileSource::~DestructiveFileSource()
@@ -124,8 +136,12 @@ DestructiveFileSource::setup_standard_crossfades (jack_nframes_t rate)
 void
 DestructiveFileSource::mark_capture_start (jack_nframes_t pos)
 {
-       _capture_start = true;
-       capture_start_frame = pos;
+       if (pos < timeline_position) {
+               _capture_start = false;
+       } else {
+               _capture_start = true;
+               capture_start_frame = pos;
+       }
 }
 
 void
@@ -265,6 +281,11 @@ DestructiveFileSource::write_unlocked (Sample* data, jack_nframes_t cnt, char *
        }
 
        if (_capture_start && _capture_end) {
+
+               /* start and end of capture both occur within the data we are writing,
+                  so do both crossfades.
+               */
+
                _capture_start = false;
                _capture_end = false;
                
@@ -290,8 +311,12 @@ DestructiveFileSource::write_unlocked (Sample* data, jack_nframes_t cnt, char *
                }
                
                file_pos = ofilepos; // adjusted below
-       }
-       else if (_capture_start) {
+
+       } else if (_capture_start) {
+
+               /* start of capture both occur within the data we are writing,
+                  so do the fade in
+               */
 
                _capture_start = false;
                _capture_end = false;
@@ -305,6 +330,10 @@ DestructiveFileSource::write_unlocked (Sample* data, jack_nframes_t cnt, char *
                
        } else if (_capture_end) {
 
+               /* end of capture both occur within the data we are writing,
+                  so do the fade out
+               */
+
                _capture_start = false;
                _capture_end = false;
                
@@ -314,6 +343,8 @@ DestructiveFileSource::write_unlocked (Sample* data, jack_nframes_t cnt, char *
 
        } else {
 
+               /* in the middle of recording */
+               
                if (write_float (data, file_pos, cnt) != cnt) {
                        return 0;
                }
@@ -365,9 +396,20 @@ DestructiveFileSource::get_state ()
        return node;
 }
 
+void
+DestructiveFileSource::handle_header_position_change ()
+{
+       if ( _length != 0 ) {
+               error << string_compose(_("Filesource: start time is already set for existing file (%1): Cannot change start time."), _path ) << endmsg;
+               //in the future, pop up a dialog here that allows user to regenerate file with new start offset
+       } else if (writable()) {
+               timeline_position = header_position_offset;
+               set_header_timeline_position ();  //this will get flushed if/when the file is recorded to
+       }
+}
+
 void
 DestructiveFileSource::set_timeline_position (jack_nframes_t pos)
 {
-       /* destructive tracks always start at where our reference frame zero is */
-       timeline_position = 0;
+       //destructive track timeline postion does not change except at instantion or when header_position_offset (session start) changes
 }
diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc
new file mode 100644 (file)
index 0000000..9312de5
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+    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
+    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: diskstream.cc 567 2006-06-07 14:54:12Z trutkin $
+*/
+
+#include <fstream>
+#include <cstdio>
+#include <unistd.h>
+#include <cmath>
+#include <cerrno>
+#include <string>
+#include <climits>
+#include <fcntl.h>
+#include <cstdlib>
+#include <ctime>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <pbd/error.h>
+#include <pbd/basename.h>
+#include <glibmm/thread.h>
+#include <pbd/xml++.h>
+
+#include <ardour/ardour.h>
+#include <ardour/audioengine.h>
+#include <ardour/diskstream.h>
+#include <ardour/utils.h>
+#include <ardour/configuration.h>
+#include <ardour/audiofilesource.h>
+#include <ardour/destructive_filesource.h>
+#include <ardour/send.h>
+#include <ardour/playlist.h>
+#include <ardour/cycle_timer.h>
+#include <ardour/region.h>
+
+#include "i18n.h"
+#include <locale.h>
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+
+jack_nframes_t Diskstream::disk_io_chunk_frames = 0;
+
+sigc::signal<void,Diskstream*>    Diskstream::DiskstreamCreated;
+sigc::signal<void,list<Source*>*> Diskstream::DeleteSources;
+sigc::signal<void>                Diskstream::DiskOverrun;
+sigc::signal<void>                Diskstream::DiskUnderrun;
+
+Diskstream::Diskstream (Session &sess, const string &name, Flag flag)
+       : _name (name)
+       , _session (sess)
+       , _playlist(NULL)
+{
+       init (flag);
+}
+       
+Diskstream::Diskstream (Session& sess, const XMLNode& node)
+       : _session (sess)
+       , _playlist(NULL)
+{
+       init (Recordable);
+}
+
+void
+Diskstream::init (Flag f)
+{
+       _refcnt = 0;
+       _flags = f;
+       _io = 0;
+       _alignment_style = ExistingMaterial;
+       _persistent_alignment_style = ExistingMaterial;
+       first_input_change = true;
+       i_am_the_modifier = 0;
+       g_atomic_int_set (&_record_enabled, 0);
+       was_recording = false;
+       capture_start_frame = 0;
+       capture_captured = 0;
+       _visible_speed = 1.0f;
+       _actual_speed = 1.0f;
+       _buffer_reallocation_required = false;
+       _seek_required = false;
+       first_recordable_frame = max_frames;
+       last_recordable_frame = max_frames;
+       _roll_delay = 0;
+       _capture_offset = 0;
+       _processed = false;
+       _slaved = false;
+       adjust_capture_position = 0;
+       last_possibly_recording = 0;
+       loop_location = 0;
+       wrap_buffer_size = 0;
+       speed_buffer_size = 0;
+       last_phase = 0;
+       phi = (uint64_t) (0x1000000);
+       file_frame = 0;
+       playback_sample = 0;
+       playback_distance = 0;
+       _read_data_count = 0;
+       _write_data_count = 0;
+
+       pending_overwrite = false;
+       overwrite_frame = 0;
+       overwrite_queued = false;
+       input_change_pending = NoChange;
+
+       _n_channels = 0;
+}
+
+Diskstream::~Diskstream ()
+{
+       // Taken by derived class destrctors.. should assure locked here somehow?
+       //Glib::Mutex::Lock lm (state_lock);
+
+       if (_playlist)
+               _playlist->unref ();
+}
+
+void
+Diskstream::set_io (IO& io)
+{
+       _io = &io;
+       set_align_style_from_io ();
+}
+
+void
+Diskstream::handle_input_change (IOChange change, void *src)
+{
+       Glib::Mutex::Lock lm (state_lock);
+
+       if (!(input_change_pending & change)) {
+               input_change_pending = IOChange (input_change_pending|change);
+               _session.request_input_change_handling ();
+       }
+}
+
+void
+Diskstream::non_realtime_set_speed ()
+{
+       if (_buffer_reallocation_required)
+       {
+               Glib::Mutex::Lock lm (state_lock);
+               allocate_temporary_buffers ();
+
+               _buffer_reallocation_required = false;
+       }
+
+       if (_seek_required) {
+               if (speed() != 1.0f || speed() != -1.0f) {
+                       seek ((jack_nframes_t) (_session.transport_frame() * (double) speed()), true);
+               }
+               else {
+                       seek (_session.transport_frame(), true);
+               }
+
+               _seek_required = false;
+       }
+}
+
+bool
+Diskstream::realtime_set_speed (double sp, bool global)
+{
+       bool changed = false;
+       double new_speed = sp * _session.transport_speed();
+       
+       if (_visible_speed != sp) {
+               _visible_speed = sp;
+               changed = true;
+       }
+       
+       if (new_speed != _actual_speed) {
+               
+               jack_nframes_t required_wrap_size = (jack_nframes_t) floor (_session.get_block_size() * 
+                                                                           fabs (new_speed)) + 1;
+               
+               if (required_wrap_size > wrap_buffer_size) {
+                       _buffer_reallocation_required = true;
+               }
+               
+               _actual_speed = new_speed;
+               phi = (uint64_t) (0x1000000 * fabs(_actual_speed));
+       }
+
+       if (changed) {
+               if (!global) {
+                       _seek_required = true;
+               }
+               SpeedChanged (); /* EMIT SIGNAL */
+       }
+
+       return _buffer_reallocation_required || _seek_required;
+}
+
+void
+Diskstream::prepare ()
+{
+       _processed = false;
+       playback_distance = 0;
+}
+
+void
+Diskstream::recover ()
+{
+       state_lock.unlock();
+       _processed = false;
+}
+
+void
+Diskstream::set_capture_offset ()
+{
+       if (_io == 0) {
+               /* can't capture, so forget it */
+               return;
+       }
+
+       _capture_offset = _io->input_latency();
+}
+
+void
+Diskstream::set_align_style (AlignStyle a)
+{
+       if (record_enabled() && _session.actively_recording()) {
+               return;
+       }
+
+       if (a != _alignment_style) {
+               _alignment_style = a;
+               AlignmentStyleChanged ();
+       }
+}
+
+int
+Diskstream::set_loop (Location *location)
+{
+       if (location) {
+               if (location->start() >= location->end()) {
+                       error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl;
+                       return -1;
+               }
+       }
+
+       loop_location = location;
+
+        LoopSet (location); /* EMIT SIGNAL */
+       return 0;
+}
+
+jack_nframes_t
+Diskstream::get_capture_start_frame (uint32_t n)
+{
+       Glib::Mutex::Lock lm (capture_info_lock);
+
+       if (capture_info.size() > n) {
+               return capture_info[n]->start;
+       }
+       else {
+               return capture_start_frame;
+       }
+}
+
+jack_nframes_t
+Diskstream::get_captured_frames (uint32_t n)
+{
+       Glib::Mutex::Lock lm (capture_info_lock);
+
+       if (capture_info.size() > n) {
+               return capture_info[n]->frames;
+       }
+       else {
+               return capture_captured;
+       }
+}
+
+void
+Diskstream::set_roll_delay (jack_nframes_t nframes)
+{
+       _roll_delay = nframes;
+}
+
+void
+Diskstream::set_speed (double sp)
+{
+       _session.request_diskstream_speed (*this, sp);
+
+       /* to force a rebuffering at the right place */
+       playlist_modified();
+}
+
+int
+Diskstream::use_playlist (Playlist* playlist)
+{
+       {
+               Glib::Mutex::Lock lm (state_lock);
+
+               if (playlist == _playlist) {
+                       return 0;
+               }
+
+               plstate_connection.disconnect();
+               plmod_connection.disconnect ();
+               plgone_connection.disconnect ();
+
+               if (_playlist) {
+                       _playlist->unref();
+               }
+                       
+               _playlist = playlist;
+               _playlist->ref();
+
+               if (!in_set_state && recordable()) {
+                       reset_write_sources (false);
+               }
+               
+               plstate_connection = _playlist->StateChanged.connect (mem_fun (*this, &Diskstream::playlist_changed));
+               plmod_connection = _playlist->Modified.connect (mem_fun (*this, &Diskstream::playlist_modified));
+               plgone_connection = _playlist->GoingAway.connect (mem_fun (*this, &Diskstream::playlist_deleted));
+       }
+
+       if (!overwrite_queued) {
+               _session.request_overwrite_buffer (this);
+               overwrite_queued = true;
+       }
+       
+       PlaylistChanged (); /* EMIT SIGNAL */
+       _session.set_dirty ();
+
+       return 0;
+}
+
+void
+Diskstream::playlist_changed (Change ignored)
+{
+       playlist_modified ();
+}
+
+void
+Diskstream::playlist_modified ()
+{
+       if (!i_am_the_modifier && !overwrite_queued) {
+               _session.request_overwrite_buffer (this);
+               overwrite_queued = true;
+       } 
+}
+
+void
+Diskstream::playlist_deleted (Playlist* pl)
+{
+       /* this catches an ordering issue with session destruction. playlists 
+          are destroyed before diskstreams. we have to invalidate any handles
+          we have to the playlist.
+       */
+
+       _playlist = 0;
+}
+
+int
+Diskstream::set_name (string str)
+{
+       if (str != _name) {
+               assert(playlist());
+               playlist()->set_name (str);
+               _name = str;
+               
+               if (!in_set_state && recordable()) {
+                       /* rename existing capture files so that they have the correct name */
+                       return rename_write_sources ();
+               } else {
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+void
+Diskstream::set_destructive (bool yn)
+{
+       if (yn != destructive()) {
+               reset_write_sources (true, true);
+               if (yn) {
+                       _flags |= Destructive;
+               } else {
+                       _flags &= ~Destructive;
+               }
+       }
+}
index f80c9dc287faa5c93bbc251cdbf4fddf9b3bff95..1342c0147baecacaa37add2550da15dc13150839 100644 (file)
@@ -32,6 +32,7 @@
 #include <lrdf.h>
 
 #include <pbd/error.h>
+#include <pbd/id.h>
 #include <pbd/strsplit.h>
 
 #include <midi++/port.h>
@@ -189,12 +190,17 @@ setup_midi ()
 }
 
 int
-ARDOUR::init (AudioEngine& engine, bool use_vst, bool try_optimization)
+ARDOUR::init (bool use_vst, bool try_optimization)
 {
         bool generic_mix_functions = true;
 
        (void) bindtextdomain(PACKAGE, LOCALEDIR);
 
+       PBD::ID::init ();
+
+       lrdf_init();
+       Library = new AudioLibrary;
+
        Config = new Configuration;
 
        if (Config->load_state ()) {
@@ -292,12 +298,9 @@ ARDOUR::init (AudioEngine& engine, bool use_vst, bool try_optimization)
                
                info << "No H/W specific optimizations in use" << endmsg;
        }
-       
-       lrdf_init();
-       Library = new AudioLibrary;
 
        /* singleton - first object is "it" */
-       new PluginManager (engine);
+       new PluginManager ();
        
        /* singleton - first object is "it" */
        new ControlProtocolManager ();
@@ -322,10 +325,15 @@ ARDOUR::cleanup ()
        return 0;
 }
 
-ARDOUR::id_t
-ARDOUR::new_id ()
+
+microseconds_t
+ARDOUR::get_microseconds ()
 {
-       return get_uid();
+       /* XXX need JACK to export its functionality */
+
+       struct timeval now;
+       gettimeofday (&now, 0);
+       return now.tv_sec * 1000000ULL + now.tv_usec;
 }
 
 ARDOUR::Change
index fc05355d4ae821ec39fc4f13cbef4bb0b9996e7d..a057fef931708e23b733c7e73eaf5ca1e9805dbe 100644 (file)
@@ -62,12 +62,12 @@ Insert::Insert(Session& s, string name, Placement p)
 
 const string PluginInsert::port_automation_node_name = "PortAutomation";
 
-PluginInsert::PluginInsert (Session& s, Plugin& plug, Placement placement)
-       : Insert (s, plug.name(), placement)
+PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug, Placement placement)
+       : Insert (s, plug->name(), placement)
 {
        /* the first is the master */
 
-       _plugins.push_back(&plug);
+       _plugins.push_back (plug);
 
        _plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed));
        
@@ -103,13 +103,13 @@ PluginInsert::PluginInsert (Session& s, const XMLNode& node)
 }
 
 PluginInsert::PluginInsert (const PluginInsert& other)
-       : Insert (other._session, other.plugin().name(), other.placement())
+       : Insert (other._session, other.plugin()->name(), other.placement())
 {
        uint32_t count = other._plugins.size();
 
        /* make as many copies as requested */
        for (uint32_t n = 0; n < count; ++n) {
-               _plugins.push_back (plugin_factory (other.plugin()));
+               _plugins.push_back (plugin_factory (other.plugin (n)));
        }
 
 
@@ -137,7 +137,7 @@ PluginInsert::set_count (uint32_t num)
                uint32_t diff = num - _plugins.size();
 
                for (uint32_t n = 0; n < diff; ++n) {
-                       _plugins.push_back (plugin_factory (*_plugins[0]));
+                       _plugins.push_back (plugin_factory (_plugins[0]));
 
                        if (require_state) {
                                /* XXX do something */
@@ -147,9 +147,7 @@ PluginInsert::set_count (uint32_t num)
        } else if (num < _plugins.size()) {
                uint32_t diff = _plugins.size() - num;
                for (uint32_t n= 0; n < diff; ++n) {
-                       Plugin * plug = _plugins.back();
                        _plugins.pop_back();
-                       delete plug;
                }
        }
 
@@ -167,12 +165,6 @@ PluginInsert::init ()
 PluginInsert::~PluginInsert ()
 {
        GoingAway (this); /* EMIT SIGNAL */
-       
-       while (!_plugins.empty()) {
-               Plugin* p = _plugins.back();
-               _plugins.pop_back();
-               delete p;
-       }
 }
 
 void
@@ -194,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
@@ -222,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
@@ -240,7 +232,7 @@ PluginInsert::set_automatable ()
 void
 PluginInsert::parameter_changed (uint32_t which, float val)
 {
-       vector<Plugin*>::iterator i = _plugins.begin();
+       vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin();
 
        /* don't set the first plugin, just all the slaves */
 
@@ -255,7 +247,7 @@ PluginInsert::parameter_changed (uint32_t which, float val)
 void
 PluginInsert::set_block_size (jack_nframes_t nframes)
 {
-       for (vector<Plugin*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
+       for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
                (*i)->set_block_size (nframes);
        }
 }
@@ -263,7 +255,7 @@ PluginInsert::set_block_size (jack_nframes_t nframes)
 void
 PluginInsert::activate ()
 {
-       for (vector<Plugin*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
+       for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
                (*i)->activate ();
        }
 }
@@ -271,7 +263,7 @@ PluginInsert::activate ()
 void
 PluginInsert::deactivate ()
 {
-       for (vector<Plugin*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
+       for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
                (*i)->deactivate ();
        }
 }
@@ -309,7 +301,7 @@ PluginInsert::connect_and_run (vector<Sample*>& bufs, uint32_t nbufs, jack_nfram
                }
        }
 
-       for (vector<Plugin*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
+       for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
                (*i)->connect_and_run (bufs, nbufs, in_index, out_index, nframes, offset);
        }
 
@@ -357,8 +349,8 @@ PluginInsert::silence (jack_nframes_t nframes, jack_nframes_t offset)
        uint32_t n;
 
        if (active()) {
-               for (vector<Plugin*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
-                       n = (*i) -> get_info().n_inputs;
+               for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
+                       n = (*i) -> get_info()->n_inputs;
                        (*i)->connect_and_run (_session.get_silent_buffers (n), n, in_index, out_index, nframes, offset);
                }
        }
@@ -375,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) {
 
@@ -506,19 +498,19 @@ PluginInsert::protect_automation ()
        }
 }
 
-Plugin*
-PluginInsert::plugin_factory (Plugin& other)
+boost::shared_ptr<Plugin>
+PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
 {
-       LadspaPlugin* lp;
+       boost::shared_ptr<LadspaPlugin> lp;
 #ifdef VST_SUPPORT
-       VSTPlugin* vp;
+       boost::shared_ptr<VSTPlugin> vp;
 #endif
 
-       if ((lp = dynamic_cast<LadspaPlugin*> (&other)) != 0) {
-               return new LadspaPlugin (*lp);
+       if ((lp = boost::dynamic_pointer_cast<LadspaPlugin> (other)) != 0) {
+               return boost::shared_ptr<Plugin> (new LadspaPlugin (*lp));
 #ifdef VST_SUPPORT
-       } else if ((vp = dynamic_cast<VSTPlugin*> (&other)) != 0) {
-               return new VSTPlugin (*vp);
+       } else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
+               return boost::shared_ptr<Plugin> (new VSTPlugin (*vp));
 #endif
        }
 
@@ -526,13 +518,13 @@ PluginInsert::plugin_factory (Plugin& other)
                          X_("unknown plugin type in PluginInsert::plugin_factory"))
              << endmsg;
        /*NOTREACHED*/
-       return 0;
+       return boost::shared_ptr<Plugin> ((Plugin*) 0);
 }
 
 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
@@ -544,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) {
 
@@ -599,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, 31, "%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()));
@@ -666,7 +658,7 @@ PluginInsert::set_state(const XMLNode& node)
                return -1;
        }
 
-       Plugin* plugin;
+       boost::shared_ptr<Plugin> plugin;
        
        if (unique != 0) {
                plugin = find_plugin (_session, "", unique, type);      
@@ -692,13 +684,13 @@ PluginInsert::set_state(const XMLNode& node)
                _plugins.push_back (plugin);
                
                for (uint32_t n=1; n < count; ++n) {
-                       _plugins.push_back (plugin_factory (*plugin));
+                       _plugins.push_back (plugin_factory (plugin));
                }
        }
        
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
                if ((*niter)->name() == plugin->state_node_name()) {
-                       for (vector<Plugin*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
+                       for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
                                (*i)->set_state (**niter);
                        }
                        break;
@@ -769,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;
 }
@@ -780,18 +772,6 @@ PluginInsert::describe_parameter (uint32_t what)
        return _plugins[0]->describe_parameter (what);
 }
 
-void
-PluginInsert::reset_midi_control (MIDI::Port* port, bool on)
-{
-       _plugins[0]->reset_midi_control (port, on);
-}
-
-void
-PluginInsert::send_all_midi_feedback ()
-{
-       _plugins[0]->send_all_midi_feedback();
-}
-
 jack_nframes_t 
 PluginInsert::latency() 
 {
index 87c03c6b70fafe56440cc694af29a188dcc697ea..2dfd735a6b28150edc93703c09c577fa20a9123b 100644 (file)
@@ -74,17 +74,17 @@ sigc::signal<int>                 IO::PortsCreated;
 
 Glib::StaticMutex       IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
 
-/* this is a default mapper of MIDI control values to a gain coefficient.
-   others can be imagined. see IO::set_midi_to_gain_function().
+/* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
+   others can be imagined. 
 */
 
-static gain_t direct_midi_to_gain (double fract) { 
+static gain_t direct_control_to_gain (double fract) { 
        /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
        /* this maxes at +6dB */
        return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
 }
 
-static double direct_gain_to_midi (gain_t gain) { 
+static double direct_gain_to_control (gain_t gain) { 
        /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
        if (gain == 0) return 0.0;
        
@@ -97,19 +97,22 @@ static bool sort_ports_by_name (Port* a, Port* b)
 }
 
 
+/** @param default_type The type of port that will be created by ensure_io
+ * and friends if no type is explicitly requested (to avoid breakage).
+ */
 IO::IO (Session& s, string name,
-
-       int input_min, int input_max, int output_min, int output_max)
+       int input_min, int input_max, int output_min, int output_max,
+       DataType default_type)
        : _session (s),
          _name (name),
-         _midi_gain_control (*this, _session.midi_port()),
+         _default_type(default_type),
+         _gain_control (*this),
          _gain_automation_curve (0.0, 2.0, 1.0),
          _input_minimum (input_min),
          _input_maximum (input_max),
          _output_minimum (output_min),
          _output_maximum (output_max)
 {
-       _id = new_id();
        _panner = new Panner (name, _session);
        _gain = 1.0;
        _desired_gain = 1.0;
@@ -121,9 +124,6 @@ IO::IO (Session& s, string name,
        no_panner_reset = false;
        deferred_state = 0;
 
-       _midi_gain_control.midi_to_gain = direct_midi_to_gain;
-       _midi_gain_control.gain_to_midi = direct_gain_to_midi;
-
        apply_gain_automation = false;
 
        last_automation_snapshot = 0;
@@ -785,11 +785,20 @@ IO::remove_output_port (Port* port, void* src)
        return -1;
 }
 
+/** Add an output port.
+ *
+ * @param destination Name of input port to connect new port to.
+ * @param src Source for emitted ConfigurationChanged signal.
+ * @param type Data type of port.  Default value (NIL) will use this IO's default type.
+ */
 int
-IO::add_output_port (string destination, void* src)
+IO::add_output_port (string destination, void* src, DataType type)
 {
        Port* our_port;
-       char buf[64];
+       char name[64];
+
+       if (type == DataType::NIL)
+               type = _default_type;
 
        {
                Glib::Mutex::Lock em(_session.engine().process_lock());
@@ -803,14 +812,15 @@ IO::add_output_port (string destination, void* src)
                
                        /* Create a new output port */
                        
+                       // FIXME: naming scheme for differently typed ports?
                        if (_output_maximum == 1) {
-                               snprintf (buf, sizeof (buf), _("%s/out"), _name.c_str());
+                               snprintf (name, sizeof (name), _("%s/out"), _name.c_str());
                        } else {
-                               snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
+                               snprintf (name, sizeof (name), _("%s/out %u"), _name.c_str(), find_output_port_hole());
                        }
                        
-                       if ((our_port = _session.engine().register_audio_output_port (buf)) == 0) {
-                               error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
+                       if ((our_port = _session.engine().register_output_port (type, name)) == 0) {
+                               error << string_compose(_("IO: cannot register output port %1"), name) << endmsg;
                                return -1;
                        }
                        
@@ -886,11 +896,21 @@ IO::remove_input_port (Port* port, void* src)
        return -1;
 }
 
+
+/** Add an input port.
+ *
+ * @param type Data type of port.  The appropriate Jack port type, and @ref Port will be created.
+ * @param destination Name of input port to connect new port to.
+ * @param src Source for emitted ConfigurationChanged signal.
+ */
 int
-IO::add_input_port (string source, void* src)
+IO::add_input_port (string source, void* src, DataType type)
 {
        Port* our_port;
-       char buf[64];
+       char name[64];
+       
+       if (type == DataType::NIL)
+               type = _default_type;
 
        {
                Glib::Mutex::Lock em (_session.engine().process_lock());
@@ -904,14 +924,15 @@ IO::add_input_port (string source, void* src)
 
                        /* Create a new input port */
                        
+                       // FIXME: naming scheme for differently typed ports?
                        if (_input_maximum == 1) {
-                               snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str());
+                               snprintf (name, sizeof (name), _("%s/in"), _name.c_str());
                        } else {
-                               snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole());
+                               snprintf (name, sizeof (name), _("%s/in %u"), _name.c_str(), find_input_port_hole());
                        }
                        
-                       if ((our_port = _session.engine().register_audio_input_port (buf)) == 0) {
-                               error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
+                       if ((our_port = _session.engine().register_input_port (type, name)) == 0) {
+                               error << string_compose(_("IO: cannot register input port %1"), name) << endmsg;
                                return -1;
                        }
                        
@@ -1005,7 +1026,7 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src)
                
                char buf[64];
                
-               /* Create a new input port */
+               /* Create a new input port (of the default type) */
                
                if (_input_maximum == 1) {
                        snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str());
@@ -1016,7 +1037,7 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src)
                
                try {
                        
-                       if ((input_port = _session.engine().register_audio_input_port (buf)) == 0) {
+                       if ((input_port = _session.engine().register_input_port (_default_type, buf)) == 0) {
                                error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
                                return -1;
                        }
@@ -1105,7 +1126,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
                        out_changed = true;
                }
                
-               /* create any necessary new ports */
+               /* create any necessary new ports (of the default type) */
                
                while (_ninputs < nin) {
                        
@@ -1121,7 +1142,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
                        }
                        
                        try {
-                               if ((port = _session.engine().register_audio_input_port (buf)) == 0) {
+                               if ((port = _session.engine().register_input_port (_default_type, buf)) == 0) {
                                        error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
                                        return -1;
                                }
@@ -1154,7 +1175,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
                        }
                        
                        try { 
-                               if ((port = _session.engine().register_audio_output_port (buf)) == 0) {
+                               if ((port = _session.engine().register_output_port (_default_type, buf)) == 0) {
                                        error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
                                        return -1;
                                }
@@ -1279,7 +1300,7 @@ IO::ensure_outputs_locked (uint32_t n, bool clear, void* src)
                        snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
                }
                
-               if ((output_port = _session.engine().register_audio_output_port (buf)) == 0) {
+               if ((output_port = _session.engine().register_output_port (_default_type, buf)) == 0) {
                        error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
                        return -1;
                }
@@ -1397,7 +1418,7 @@ XMLNode&
 IO::state (bool full_state)
 {
        XMLNode* node = new XMLNode (state_node_name);
-       char buf[32];
+       char buf[64];
        string str;
        bool need_ins = true;
        bool need_outs = true;
@@ -1405,7 +1426,7 @@ IO::state (bool full_state)
        Glib::Mutex::Lock lm (io_lock);
 
        node->add_property("name", _name);
-       snprintf (buf, sizeof(buf), "%" PRIu64, id());
+       id().print (buf);
        node->add_property("id", buf);
 
        str = "";
@@ -1499,22 +1520,6 @@ IO::state (bool full_state)
 
        node->add_property ("iolimits", buf);
 
-       /* MIDI control */
-
-       MIDI::channel_t chn;
-       MIDI::eventType ev;
-       MIDI::byte      additional;
-       XMLNode*        midi_node = 0;
-       XMLNode*        child;
-
-       if (_midi_gain_control.get_control_info (chn, ev, additional)) {
-
-               midi_node = node->add_child ("MIDI");
-
-               child = midi_node->add_child ("gain");
-               set_midi_node_info (child, ev, chn, additional);
-       }
-
        /* automation */
 
        if (full_state) {
@@ -1583,7 +1588,6 @@ IO::set_state (const XMLNode& node)
 {
        const XMLProperty* prop;
        XMLNodeConstIterator iter;
-       XMLNodeList midi_kids;
        LocaleGuard lg (X_("POSIX"));
 
        /* force use of non-localized representation of decimal point,
@@ -1601,7 +1605,7 @@ IO::set_state (const XMLNode& node)
        } 
 
        if ((prop = node.property ("id")) != 0) {
-               sscanf (prop->value().c_str(), "%" PRIu64, &_id);
+               _id = prop->value ();
        }
 
        if ((prop = node.property ("iolimits")) != 0) {
@@ -1623,35 +1627,6 @@ IO::set_state (const XMLNode& node)
                }
        }
 
-       midi_kids = node.children ("MIDI");
-       
-       for (iter = midi_kids.begin(); iter != midi_kids.end(); ++iter) {
-       
-               XMLNodeList kids;
-               XMLNodeConstIterator miter;
-               XMLNode*    child;
-
-               kids = (*iter)->children ();
-
-               for (miter = kids.begin(); miter != kids.end(); ++miter) {
-
-                       child =* miter;
-
-                       if (child->name() == "gain") {
-                       
-                               MIDI::eventType ev = MIDI::on; /* initialize to keep gcc happy */
-                               MIDI::byte additional = 0;  /* ditto */
-                               MIDI::channel_t chn = 0;    /* ditto */
-
-                               if (get_midi_node_info (child, ev, chn, additional)) {
-                                       _midi_gain_control.set_control_type (chn, ev, additional);
-                               } else {
-                                       error << string_compose(_("MIDI gain control specification for %1 is incomplete, so it has been ignored"), _name) << endmsg;
-                               }
-                       }
-               }
-       }
-                       
        if ((prop = node.property ("automation-state")) != 0) {
 
                long int x;
@@ -1769,50 +1744,6 @@ IO::create_ports (const XMLNode& node)
        return 0;
 }
 
-bool
-IO::get_midi_node_info (XMLNode * node, MIDI::eventType & ev, MIDI::channel_t & chan, MIDI::byte & additional)
-{
-       bool ok = true;
-       const XMLProperty* prop;
-       int xx;
-
-       if ((prop = node->property ("event")) != 0) {
-               sscanf (prop->value().c_str(), "0x%x", &xx);
-               ev = (MIDI::eventType) xx;
-       } else {
-               ok = false;
-       }
-
-       if (ok && ((prop = node->property ("channel")) != 0)) {
-               sscanf (prop->value().c_str(), "%d", &xx);
-               chan = (MIDI::channel_t) xx;
-       } else {
-               ok = false;
-       }
-
-       if (ok && ((prop = node->property ("additional")) != 0)) {
-               sscanf (prop->value().c_str(), "0x%x", &xx);
-               additional = (MIDI::byte) xx;
-       }
-
-       return ok;
-}
-
-bool
-IO::set_midi_node_info (XMLNode * node, MIDI::eventType ev, MIDI::channel_t chan, MIDI::byte additional)
-{
-       char buf[32];
-
-       snprintf (buf, sizeof(buf), "0x%x", ev);
-       node->add_property ("event", buf);
-       snprintf (buf, sizeof(buf), "%d", chan);
-       node->add_property ("channel", buf);
-       snprintf (buf, sizeof(buf), "0x%x", additional);
-       node->add_property ("additional", buf);
-
-       return true;
-}
-
 
 int
 IO::make_connections (const XMLNode& node)
@@ -2339,69 +2270,16 @@ IO::output_connection_configuration_changed ()
        use_output_connection (*_output_connection, this);
 }
 
-IO::MIDIGainControl::MIDIGainControl (IO& i, MIDI::Port* port)
-       : MIDI::Controllable (port, 0), io (i), setting(false)
-{
-       midi_to_gain = 0;
-       gain_to_midi = 0;
-       setting = false;
-       last_written = 0; /* XXX need a good out-of-bound-value */
-}
-
 void
-IO::MIDIGainControl::set_value (float val)
+IO::GainControllable::set_value (float val)
 {
-       if (midi_to_gain == 0) return;
-       
-       setting = true;
-       io.set_gain (midi_to_gain (val), this);
-       setting = false;
+       io.set_gain (direct_control_to_gain (val), this);
 }
 
-void
-IO::MIDIGainControl::send_feedback (gain_t gain)
-{
-       if (!setting && get_midi_feedback() && gain_to_midi) {
-               MIDI::byte val = (MIDI::byte) (gain_to_midi (gain) * 127.0);
-               MIDI::channel_t ch = 0;
-               MIDI::eventType ev = MIDI::none;
-               MIDI::byte additional = 0;
-               MIDI::EventTwoBytes data;
-           
-               if (get_control_info (ch, ev, additional)) {
-                       data.controller_number = additional;
-                       data.value = val;
-                       last_written = val;
-                       
-                       io._session.send_midi_message (get_port(), ev, ch, data);
-               }
-               //send_midi_feedback (gain_to_midi (gain));
-       }
-}
-
-MIDI::byte*
-IO::MIDIGainControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, gain_t val, bool force)
+float
+IO::GainControllable::get_value (void) const
 {
-       if (get_midi_feedback() && gain_to_midi && bufsize > 2) {
-               MIDI::channel_t ch = 0;
-               MIDI::eventType ev = MIDI::none;
-               MIDI::byte additional = 0;
-               MIDI::byte gm;
-
-               if (get_control_info (ch, ev, additional)) {
-                       gm = (MIDI::byte) (gain_to_midi (val) * 127.0);
-                       
-                       if (gm != last_written) {
-                               *buf++ = (0xF0 & ev) | (0xF & ch);
-                               *buf++ = additional; /* controller number */
-                               *buf++ = gm;
-                               last_written = gm;
-                               bufsize -= 3;
-                       }
-               }
-       }
-       
-       return buf;
+       return direct_gain_to_control (io.effective_gain());
 }
 
 void
@@ -2493,23 +2371,6 @@ IO::meter ()
        }
 }
 
-void
-IO::reset_midi_control (MIDI::Port* port, bool on)
-{
-       MIDI::channel_t chn;
-       MIDI::eventType ev;
-       MIDI::byte extra;
-
-       _midi_gain_control.get_control_info (chn, ev, extra);
-       if (!on) {
-               chn = -1;
-       }
-       _midi_gain_control.midi_rebind (port, chn);
-       
-       _panner->reset_midi_control (port, on);
-}
-
-
 int
 IO::save_automation (const string& path)
 {
@@ -2699,10 +2560,7 @@ IO::set_gain (gain_t val, void *src)
        }
 
        gain_changed (src);
-
-       if (_session.get_midi_feedback()) {
-               _midi_gain_control.send_feedback (_desired_gain);
-       }
+       _gain_control.Changed (); /* EMIT SIGNAL */
        
        if (_session.transport_stopped() && src != 0 && src != this && gain_automation_recording()) {
                _gain_automation_curve.add (_session.transport_frame(), val);
@@ -2712,30 +2570,6 @@ IO::set_gain (gain_t val, void *src)
        _session.set_dirty();
 }
 
-void
-IO::send_all_midi_feedback ()
-{
-       if (_session.get_midi_feedback()) {
-               _midi_gain_control.send_feedback (_effective_gain);
-
-               // panners
-               _panner->send_all_midi_feedback();
-       }
-}
-
-MIDI::byte*
-IO::write_midi_feedback (MIDI::byte* buf, int32_t& bufsize)
-{
-       if (_session.get_midi_feedback()) {
-               if (gain_automation_playback ()) {
-                       buf = _midi_gain_control.write_feedback (buf, bufsize, _effective_gain);
-               }
-               buf = _panner->write_midi_feedback (buf, bufsize);
-       }
-
-       return buf;
-}
-
 void
 IO::start_gain_touch ()
 {
index 11001655d2974efa014c1d5f5ec3377665397872..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
@@ -133,20 +133,9 @@ LadspaPlugin::init (void *mod, uint32_t index, jack_nframes_t rate)
                }
        }
 
-       Plugin::setup_midi_controls ();
+       Plugin::setup_controls ();
 
        latency_compute_run ();
-
-       MIDI::Controllable *mcontrol;
-
-       for (uint32_t i = 0; i < parameter_count(); ++i) {
-               if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) &&
-                   LADSPA_IS_PORT_CONTROL(port_descriptor (i))) {
-                       if ((mcontrol = get_nth_midi_control (i)) != 0) {
-                               mcontrol->midi_rebind (_session.midi_port(), 0);
-                       }
-               }
-       }
 }
 
 LadspaPlugin::~LadspaPlugin ()
@@ -318,17 +307,14 @@ LadspaPlugin::set_parameter (uint32_t which, float val)
                shadow_data[which] = (LADSPA_Data) val;
                ParameterChanged (which, val); /* EMIT SIGNAL */
 
-               if (session().get_midi_feedback()) {
-
-                       if (which < parameter_count() && midi_controls[which]) {
-                               midi_controls[which]->send_feedback (val);
-                       }
+               if (which < parameter_count() && controls[which]) {
+                       controls[which]->Changed ();
                }
-
+               
        } else {
                warning << string_compose (_("illegal parameter number used with plugin \"%1\". This may"
-                                     "indicate a change in the plugin design, and presets may be"
-                                     "invalid"), name())
+                                            "indicate a change in the plugin design, and presets may be"
+                                            "invalid"), name())
                        << endmsg;
        }
 }
@@ -380,28 +366,6 @@ LadspaPlugin::get_state()
                        snprintf(buf, sizeof(buf), "%+f", shadow_data[i]);
                        child->add_property("value", string(buf));
                        root->add_child_nocopy (*child);
-
-                       MIDI::Controllable *pcontrol = get_nth_midi_control (i);
-                       
-                       if (pcontrol) {
-
-                               MIDI::eventType ev;
-                               MIDI::byte      additional;
-                               MIDI::channel_t chn;
-                               XMLNode*        midi_node;
-
-                               if (pcontrol->get_control_info (chn, ev, additional)) {
-
-                                       midi_node = child->add_child ("midi-control");
-               
-                                       snprintf (buf, sizeof(buf), "0x%x", ev);
-                                       midi_node->add_property ("event", buf);
-                                       snprintf (buf, sizeof(buf), "%d", chn);
-                                       midi_node->add_property ("channel", buf);
-                                       snprintf (buf, sizeof(buf), "0x%x", additional);
-                                       midi_node->add_property ("additional", buf);
-                               }
-                       }
                }
        }
 
@@ -452,52 +416,6 @@ LadspaPlugin::set_state(const XMLNode& node)
 
                sscanf (port, "%" PRIu32, &port_id);
                set_parameter (port_id, atof(data));
-
-               XMLNodeList midi_kids;
-               XMLNodeConstIterator iter;
-               
-               midi_kids = child->children ("midi-control");
-               
-               for (iter = midi_kids.begin(); iter != midi_kids.end(); ++iter) {
-                       
-                       child = *iter;
-
-                       MIDI::eventType ev = MIDI::on; /* initialize to keep gcc happy */
-                       MIDI::byte additional = 0; /* initialize to keep gcc happy */
-                       MIDI::channel_t chn = 0; /* initialize to keep gcc happy */
-                       bool ok = true;
-                       int xx;
-                       
-                       if ((prop = child->property ("event")) != 0) {
-                               sscanf (prop->value().c_str(), "0x%x", &xx);
-                               ev = (MIDI::eventType) xx;
-                       } else {
-                               ok = false;
-                       }
-                       
-                       if (ok && ((prop = child->property ("channel")) != 0)) {
-                               sscanf (prop->value().c_str(), "%d", &xx);
-                               chn = (MIDI::channel_t) xx;
-                       } else {
-                               ok = false;
-                       }
-                       
-                       if (ok && ((prop = child->property ("additional")) != 0)) {
-                               sscanf (prop->value().c_str(), "0x%x", &xx);
-                               additional = (MIDI::byte) xx;
-                       }
-                       
-                       if (ok) {
-                               MIDI::Controllable* pcontrol = get_nth_midi_control (port_id);
-
-                               if (pcontrol) {
-                                       pcontrol->set_control_type (chn, ev, additional);
-                               }
-
-                       } else {
-                               error << string_compose(_("LADSPA LadspaPlugin MIDI control specification for port %1 is incomplete, so it has been ignored"), port) << endl;
-                       }
-               }
        }
 
        latency_compute_run ();
@@ -723,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 b2af52284e91bfa232e575cbcd69addc23fec91d..5b5f73313884cdcde02c37f36ba43837407afe65 100644 (file)
@@ -30,6 +30,7 @@
 #include <pbd/xml++.h>
 
 #include <ardour/location.h>
+#include <ardour/audiofilesource.h>
 
 #include "i18n.h"
 
@@ -44,6 +45,10 @@ Location::Location (const Location& other)
          _end (other._end),
          _flags (other._flags)
 {
+       /* start and end flags can never be copied, because there can only ever be one of each */
+
+       _flags = Flags (_flags & ~IsStart);
+       _flags = Flags (_flags & ~IsEnd);
 }
 
 Location*
@@ -71,6 +76,9 @@ Location::set_start (jack_nframes_t s)
                        _start = s;
                        _end = s;
                        start_changed(this); /* EMIT SIGNAL */
+                       if ( is_start() ) {
+                               AudioFileSource::set_header_position_offset ( s );
+                       }
                }
                return 0;
        }
index ab0d1dde59bba46e1849e49b659c9eda790ad858..c6e234d87bb4997b33e375c89496e6b89328a148 100644 (file)
@@ -22,6 +22,7 @@
 #include <ardour/types.h>
 #include <ardour/utils.h>
 #include <ardour/mix.h>
+#include <stdint.h>
 
 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
 
@@ -119,8 +120,9 @@ mix_buffers_no_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, jack_nframes_t nf
 float
 veclib_compute_peak (ARDOUR::Sample *buf, jack_nframes_t nsamples, float current)
 {
-        vDSP_maxv(buf, 1, &current, nsamples);
-        return current;
+       float tmpmax = 0.0f;
+        vDSP_maxmgv(buf, 1, &tmpmax, nsamples);
+        return f_max(current, tmpmax);
 }
 
 void
index 83c9e6eb4d7f48854bb4cbc8246451172b52f9a9..8336c4697c5fcd48906aab843509968454dcd4aa 100644 (file)
@@ -53,21 +53,21 @@ float Panner::current_automation_version_number = 1.0;
 string EqualPowerStereoPanner::name = "Equal Power Stereo";
 string Multi2dPanner::name = "Multiple (2D)";
 
-/* this is a default mapper of MIDI control values to a pan position
-   others can be imagined. see Panner::set_midi_to_pan_function().
+/* this is a default mapper of  control values to a pan position
+   others can be imagined. 
 */
 
-static pan_t direct_midi_to_pan (double fract) { 
+static pan_t direct_control_to_pan (double fract) { 
        return fract;
 }
 
-static double direct_pan_to_midi (pan_t val) { 
+static double direct_pan_to_control (pan_t val) { 
        return val;
 }
 
 StreamPanner::StreamPanner (Panner& p)
        : parent (p),
-         _midi_control (*this, (MIDI::Port*) 0)
+         _control (*this)
 {
        _muted = false;
 
@@ -80,84 +80,30 @@ StreamPanner::~StreamPanner ()
 {
 }
 
-StreamPanner::MIDIControl::MIDIControl (StreamPanner& s, MIDI::Port* port)
-       : MIDI::Controllable (port, 0), sp (s), setting(false)
-{
-       midi_to_pan = direct_midi_to_pan;
-       pan_to_midi = direct_pan_to_midi;
-       last_written = 0; /* XXX need a good out-of-bound-value */
-}
-
 void
-StreamPanner::MIDIControl::set_value (float val)
+StreamPanner::PanControllable::set_value (float val)
 {
-       setting = true;
-       sp.set_position (midi_to_pan (val));
-       setting = false;
-}
-
-void
-StreamPanner::MIDIControl::send_feedback (pan_t value)
-{
-
-       if (!setting && get_midi_feedback() && pan_to_midi) {
-               MIDI::byte val = (MIDI::byte) (pan_to_midi (value) * 127.0f);
-               MIDI::channel_t ch = 0;
-               MIDI::eventType ev = MIDI::none;
-               MIDI::byte additional = 0;
-               MIDI::EventTwoBytes data;
-           
-               if (get_control_info (ch, ev, additional)) {
-                       data.controller_number = additional;
-                       data.value = val;
-                       last_written = val;
-                       
-                       sp.get_parent().session().send_midi_message (get_port(), ev, ch, data);
-               }
-
-               // send_midi_feedback (pan_to_midi (val));
-       }
-       
+       panner.set_position (direct_control_to_pan (val));
 }
 
-MIDI::byte*
-StreamPanner::MIDIControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, pan_t val, bool force)
+float
+StreamPanner::PanControllable::get_value (void) const
 {
-       if (get_midi_feedback() && pan_to_midi && bufsize > 2) {
-               MIDI::channel_t ch = 0;
-               MIDI::eventType ev = MIDI::none;
-               MIDI::byte additional = 0;
-               MIDI::byte pm;
-               if (get_control_info (ch, ev, additional)) {
-
-                       pm = (MIDI::byte) (pan_to_midi (val) * 127.0);
-
-                       if (pm != last_written || force) {
-                               *buf++ = (0xF0 & ev) | (0xF & ch);
-                               *buf++ = additional; /* controller number */
-                               *buf++ = pm;
-                               last_written = pm;
-                               bufsize -= 3;
-                       }
-               }
-       }
-
-       return buf;
+       float xpos;
+       panner.get_effective_position (xpos);
+       return direct_pan_to_control (xpos);
 }
 
-
-void
-StreamPanner::reset_midi_control (MIDI::Port* port, bool on)
+bool
+StreamPanner::PanControllable::can_send_feedback () const
 {
-       MIDI::channel_t chn;
-       MIDI::eventType ev;
-       MIDI::byte extra;
+       AutoState astate = panner.get_parent().automation_state ();
 
-       _midi_control.get_control_info (chn, ev, extra);
-       if (!on) {
-               chn = -1;
+       if ((astate == Play) || (astate == Touch && !panner.get_parent().touching())) {
+               return true;
        }
-       _midi_control.midi_rebind (port, chn);
+
+       return false;
 }
 
 void
@@ -180,10 +126,7 @@ StreamPanner::set_position (float xpos, bool link_call)
                x = xpos;
                update ();
                Changed ();
-
-               if (parent.session().get_midi_feedback()) {
-                       _midi_control.send_feedback (x);
-               }
+               _control.Changed ();
        }
 }
 
@@ -224,42 +167,11 @@ StreamPanner::set_state (const XMLNode& node)
 {
        const XMLProperty* prop;
        XMLNodeConstIterator iter;
-       XMLNodeList midi_kids;
 
        if ((prop = node.property (X_("muted")))) {
                set_muted (prop->value() == "yes");
        }
 
-       midi_kids = node.children ("MIDI");
-       
-       for (iter = midi_kids.begin(); iter != midi_kids.end(); ++iter) {
-       
-               XMLNodeList kids;
-               XMLNodeConstIterator miter;
-               XMLNode*    child;
-
-               kids = (*iter)->children ();
-
-               for (miter = kids.begin(); miter != kids.end(); ++miter) {
-
-                       child =* miter;
-
-                       if (child->name() == "pan") {
-                       
-                               MIDI::eventType ev = MIDI::on; /* initialize to keep gcc happy */
-                               MIDI::byte additional = 0;  /* ditto */
-                               MIDI::channel_t chn = 0;    /* ditto */
-
-                               if (get_midi_node_info (child, ev, chn, additional)) {
-                                       _midi_control.set_control_type (chn, ev, additional);
-                               } else {
-                                       error << _("MIDI pan control specification is incomplete, so it has been ignored") << endmsg;
-                               }
-                       }
-               }
-       }
-
-       
        return 0;
 }
 
@@ -267,68 +179,6 @@ void
 StreamPanner::add_state (XMLNode& node)
 {
        node.add_property (X_("muted"), (muted() ? "yes" : "no"));
-
-       /* MIDI control */
-
-       MIDI::channel_t chn;
-       MIDI::eventType ev;
-       MIDI::byte      additional;
-       XMLNode*        midi_node = 0;
-       XMLNode*        child;
-
-       if (_midi_control.get_control_info (chn, ev, additional)) {
-
-               midi_node = node.add_child ("MIDI");
-
-               child = midi_node->add_child ("pan");
-               set_midi_node_info (child, ev, chn, additional);
-       }
-
-}
-
-
-bool
-StreamPanner::get_midi_node_info (XMLNode * node, MIDI::eventType & ev, MIDI::channel_t & chan, MIDI::byte & additional)
-{
-       bool ok = true;
-       const XMLProperty* prop;
-       int xx;
-
-       if ((prop = node->property ("event")) != 0) {
-               sscanf (prop->value().c_str(), "0x%x", &xx);
-               ev = (MIDI::eventType) xx;
-       } else {
-               ok = false;
-       }
-
-       if (ok && ((prop = node->property ("channel")) != 0)) {
-               sscanf (prop->value().c_str(), "%d", &xx);
-               chan = (MIDI::channel_t) xx;
-       } else {
-               ok = false;
-       }
-
-       if (ok && ((prop = node->property ("additional")) != 0)) {
-               sscanf (prop->value().c_str(), "0x%x", &xx);
-               additional = (MIDI::byte) xx;
-       }
-
-       return ok;
-}
-
-bool
-StreamPanner::set_midi_node_info (XMLNode * node, MIDI::eventType ev, MIDI::channel_t chan, MIDI::byte additional)
-{
-       char buf[32];
-
-       snprintf (buf, sizeof(buf), "0x%x", ev);
-       node->add_property ("event", buf);
-       snprintf (buf, sizeof(buf), "%d", chan);
-       node->add_property ("channel", buf);
-       snprintf (buf, sizeof(buf), "0x%x", additional);
-       node->add_property ("additional", buf);
-
-       return true;
 }
 
 /*---------------------------------------------------------------------- */
@@ -679,7 +529,7 @@ EqualPowerStereoPanner::state (bool full_state)
        char buf[64];
        LocaleGuard lg (X_("POSIX"));
 
-       snprintf (buf, sizeof (buf), "%f", x); 
+       snprintf (buf, sizeof (buf), "%.12g", x); 
        root->add_property (X_("x"), buf);
        root->add_property (X_("type"), EqualPowerStereoPanner::name);
        if (full_state) {
@@ -913,9 +763,9 @@ Multi2dPanner::state (bool full_state)
        char buf[64];
        LocaleGuard lg (X_("POSIX"));
 
-       snprintf (buf, sizeof (buf), "%f", x); 
+       snprintf (buf, sizeof (buf), "%.12g", x); 
        root->add_property (X_("x"), buf);
-       snprintf (buf, sizeof (buf), "%f", y); 
+       snprintf (buf, sizeof (buf), "%.12g", y); 
        root->add_property (X_("y"), buf);
        root->add_property (X_("type"), Multi2dPanner::name);
 
@@ -959,8 +809,6 @@ Panner::Panner (string name, Session& s)
        _linked = false;
        _link_direction = SameDirection;
        _bypassed = false;
-
-       reset_midi_control (_session.mmc_port(), _session.get_mmc_control());
 }
 
 Panner::~Panner ()
@@ -1107,8 +955,6 @@ Panner::reset (uint32_t nouts, uint32_t npans)
                (*x)->update ();
        }
 
-       reset_midi_control (_session.mmc_port(), _session.get_mmc_control());
-
        /* force hard left/right panning in a common case: 2in/2out 
        */
        
@@ -1333,7 +1179,7 @@ struct PanPlugins {
 PanPlugins pan_plugins[] = {
        { EqualPowerStereoPanner::name, 2, EqualPowerStereoPanner::factory },
        { Multi2dPanner::name, 3, Multi2dPanner::factory },
-       { string (""), 0 }
+       { string (""), 0, 0 }
 };
 
 XMLNode&
@@ -1361,9 +1207,9 @@ Panner::state (bool full)
 
        for (vector<Panner::Output>::iterator o = outputs.begin(); o != outputs.end(); ++o) {
                XMLNode* onode = new XMLNode (X_("Output"));
-               snprintf (buf, sizeof (buf), "%f", (*o).x);
+               snprintf (buf, sizeof (buf), "%.12g", (*o).x);
                onode->add_property (X_("x"), buf);
-               snprintf (buf, sizeof (buf), "%f", (*o).y);
+               snprintf (buf, sizeof (buf), "%.12g", (*o).y);
                onode->add_property (X_("y"), buf);
                root->add_child_nocopy (*onode);
        }
@@ -1412,10 +1258,10 @@ Panner::set_state (const XMLNode& node)
                        float x, y;
                        
                        prop = (*niter)->property (X_("x"));
-                       sscanf (prop->value().c_str(), "%f", &x);
+                       sscanf (prop->value().c_str(), "%.12g", &x);
                        
                        prop = (*niter)->property (X_("y"));
-                       sscanf (prop->value().c_str(), "%f", &y);
+                       sscanf (prop->value().c_str(), "%.12g", &y);
                        
                        outputs.push_back (Output (x, y));
                }
@@ -1489,14 +1335,6 @@ Panner::touching () const
        return false;
 }
 
-void
-Panner::reset_midi_control (MIDI::Port* port, bool on)
-{
-       for (vector<StreamPanner*>::const_iterator i = begin(); i != end(); ++i) {
-               (*i)->reset_midi_control (port, on);
-       }
-}      
-
 void
 Panner::set_position (float xpos, StreamPanner& orig)
 {
@@ -1639,42 +1477,3 @@ Panner::set_position (float xpos, float ypos, float zpos, StreamPanner& orig)
                }
        }
 }
-
-void
-Panner::send_all_midi_feedback ()
-{
-       if (_session.get_midi_feedback()) {
-               float xpos;
-               
-               // do feedback for all panners
-               for (vector<StreamPanner*>::iterator i = begin(); i != end(); ++i) {
-                       (*i)->get_effective_position (xpos);
-
-                       (*i)->midi_control().send_feedback (xpos);
-               }
-               
-       }
-}
-
-MIDI::byte*
-Panner::write_midi_feedback (MIDI::byte* buf, int32_t& bufsize)
-{
-       AutoState astate = automation_state ();
-
-       if (_session.get_midi_feedback() && 
-           (astate == Play || (astate == Touch && !touching()))) {
-               
-               float xpos;
-               
-               // do feedback for all panners
-               for (vector<StreamPanner*>::iterator i = begin(); i != end(); ++i) {
-                       (*i)->get_effective_position (xpos);
-                       
-                       buf = (*i)->midi_control().write_feedback (buf, bufsize, xpos);
-               }
-               
-       }
-
-       return buf;
-}
-
index 7dee8667673a2a1bcd5ccebc24afff66cee8fd48..6d5e8f7847d5f0287cb96bbc21f540810b8d2a98 100644 (file)
@@ -77,7 +77,6 @@ Playlist::Playlist (Session& sess, string nom, bool hide)
 {
        init (hide);
        _name = nom;
-       _orig_diskstream_id = 0;
        
 }
 
@@ -86,7 +85,6 @@ Playlist::Playlist (Session& sess, const XMLNode& node, bool hide)
 {
        init (hide);
        _name = "unnamed"; /* reset by set_state */
-       _orig_diskstream_id = 0;
        
        if (set_state (node)) {
                throw failed_constructor();
@@ -600,6 +598,31 @@ Playlist::remove_region_internal (Region *region, bool delay_sort)
        return -1;
 }
 
+void
+Playlist::get_equivalent_regions (const Region& other, vector<Region*>& results)
+{
+       for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+               if (Config->get_use_overlap_equivalency()) {
+                       if ((*i)->overlap_equivalent (other)) {
+                               results.push_back ((*i));
+                       } else if ((*i)->equivalent (other)) {
+                               results.push_back ((*i));
+                       }
+               }
+       }
+}
+
+void
+Playlist::get_region_list_equivalent_regions (const Region& other, vector<Region*>& results)
+{
+       for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+
+               if ((*i) && (*i)->region_list_equivalent (other)) {
+                       results.push_back (*i);
+               }
+       }
+}
+
 void
 Playlist::partition (jack_nframes_t start, jack_nframes_t end, bool just_top_level)
 {
@@ -1343,7 +1366,7 @@ Playlist::set_state (const XMLNode& node)
                if (prop->name() == X_("name")) {
                        _name = prop->value();
                } else if (prop->name() == X_("orig_diskstream_id")) {
-                       sscanf (prop->value().c_str(), "%" PRIu64, &_orig_diskstream_id);
+                       _orig_diskstream_id = prop->value ();
                } else if (prop->name() == X_("frozen")) {
                        _frozen = (prop->value() == X_("yes"));
                }
@@ -1404,7 +1427,7 @@ Playlist::state (bool full_state)
        
        node->add_property (X_("name"), _name);
 
-       snprintf (buf, sizeof(buf), "%" PRIu64, _orig_diskstream_id);
+       _orig_diskstream_id.print (buf);
        node->add_property (X_("orig_diskstream_id"), buf);
        node->add_property (X_("frozen"), _frozen ? "yes" : "no");
 
@@ -1725,7 +1748,7 @@ Playlist::nudge_after (jack_nframes_t start, jack_nframes_t distance, bool forwa
 }
 
 Region*
-Playlist::find_region (id_t id) const
+Playlist::find_region (const ID& id) const
 {
        RegionLock rlock (const_cast<Playlist*> (this));
        RegionList::const_iterator i;
index 2d1f8ffcbd06c888626865b65728b8eddf99482b..8ea95b89037db9333fdd1713fe32d667fc67ff1e 100644 (file)
 #include <pbd/pathscanner.h>
 #include <pbd/xml++.h>
 
-#include <midi++/manager.h>
-
 #include <ardour/ardour.h>
 #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>
 
@@ -61,64 +61,59 @@ Plugin::Plugin (const Plugin& other)
 }
 
 void
-Plugin::setup_midi_controls ()
+Plugin::setup_controls ()
 {
-       uint32_t port_cnt;
-
-       port_cnt = parameter_count();
+       uint32_t port_cnt = parameter_count();
 
-       /* set up a vector of null pointers for the MIDI controls.
+       /* set up a vector of null pointers for the controls.
           we'll fill this in on an as-needed basis.
        */
 
        for (uint32_t i = 0; i < port_cnt; ++i) {
-               midi_controls.push_back (0);
+               controls.push_back (0);
        }
 }
 
 Plugin::~Plugin ()
 {
-       for (vector<MIDIPortControl*>::iterator i = midi_controls.begin(); i != midi_controls.end(); ++i) {
+       for (vector<PortControllable*>::iterator i = controls.begin(); i != controls.end(); ++i) {
                if (*i) {
                        delete *i;
                }
        }
 }
 
-MIDI::Controllable *
-Plugin::get_nth_midi_control (uint32_t n)
+Controllable *
+Plugin::get_nth_control (uint32_t n)
 {
        if (n >= parameter_count()) {
                return 0;
        }
 
-       if (midi_controls[n] == 0) {
+       if (controls[n] == 0) {
 
                Plugin::ParameterDescriptor desc;
 
                get_parameter_descriptor (n, desc);
-
-               midi_controls[n] = new MIDIPortControl (*this, n, _session.midi_port(), desc.lower, desc.upper, desc.toggled, desc.logarithmic);
+               
+               controls[n] = new PortControllable (*this, n, desc.lower, desc.upper, desc.toggled, desc.logarithmic);
        } 
 
-       return midi_controls[n];
+       return controls[n];
 }
 
-Plugin::MIDIPortControl::MIDIPortControl (Plugin& p, uint32_t port_id, MIDI::Port *port,
-                                         float low, float up, bool t, bool loga)
-       : MIDI::Controllable (port, 0), plugin (p), absolute_port (port_id)
+Plugin::PortControllable::PortControllable (Plugin& p, uint32_t port_id, float low, float up, bool t, bool loga)
+       : plugin (p), absolute_port (port_id)
 {
        toggled = t;
        logarithmic = loga;
        lower = low;
        upper = up;
        range = upper - lower;
-       last_written = 0; /* XXX need a good out-of-bound-value */
-       setting = false;
 }
 
 void
-Plugin::MIDIPortControl::set_value (float value)
+Plugin::PortControllable::set_value (float value)
 {
        if (toggled) {
                if (value > 0.5) {
@@ -127,145 +122,40 @@ Plugin::MIDIPortControl::set_value (float value)
                        value = 0.0;
                }
        } else {
-               value = lower + (range * value);
-               
-               if (logarithmic) {
-                       value = exp(value);
-               }
-       }
 
-       setting = true;
-       plugin.set_parameter (absolute_port, value);
-       setting = false;
-}
-
-void
-Plugin::MIDIPortControl::send_feedback (float value)
-{
-
-       if (!setting && get_midi_feedback()) {
-               MIDI::byte val;
-               MIDI::channel_t ch = 0;
-               MIDI::eventType ev = MIDI::none;
-               MIDI::byte additional = 0;
-               MIDI::EventTwoBytes data;
-
-               if (toggled) {
-                       val = (MIDI::byte) (value * 127.0f);
+               if (!logarithmic) {
+                       value = lower + (range * value);
                } else {
-                       if (logarithmic) {
-                               value = log(value);
-                       }
-
-                       val = (MIDI::byte) (((value - lower) / range) * 127.0f);
-               }
-               
-               if (get_control_info (ch, ev, additional)) {
-                       data.controller_number = additional;
-                       data.value = val;
-                       last_written = val;
-                       
-                       plugin.session().send_midi_message (get_port(), ev, ch, data);
-               }
-       }
-       
-}
-
-MIDI::byte*
-Plugin::MIDIPortControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, float value, bool force)
-{
-       if (get_midi_feedback() && bufsize > 2) {
-               MIDI::channel_t ch = 0;
-               MIDI::eventType ev = MIDI::none;
-               MIDI::byte additional = 0;
-
-               if (get_control_info (ch, ev, additional)) {
-
-                       MIDI::byte val;
-
-                       if (toggled) {
-
-                               val = (MIDI::byte) (value * 127.0f);
-
-                       } else {
-
-                               if (logarithmic) {
-                                       value = log(value);
-                               }
-                               
-                               val = (MIDI::byte) (((value - lower) / range) * 127.0f);
+                       float _lower = 0.0f;
+                       if (lower > 0.0f) {
+                               _lower = log(lower);
                        }
 
-                       if (val != last_written || force)  {
-                               *buf++ = MIDI::controller & ch;
-                               *buf++ = additional; /* controller number */
-                               *buf++ = val;
-                               last_written = val;
-                               bufsize -= 3;
-                       }
+                       value = exp(_lower + log(range) * value);
                }
        }
 
-       return buf;
+       plugin.set_parameter (absolute_port, value);
 }
 
-
-void
-Plugin::reset_midi_control (MIDI::Port* port, bool on)
+float
+Plugin::PortControllable::get_value (void) const
 {
-       MIDI::channel_t chn;
-       MIDI::eventType ev;
-       MIDI::byte extra;
-       
-       for (vector<MIDIPortControl*>::iterator i = midi_controls.begin(); i != midi_controls.end(); ++i) {
-               if (*i == 0)
-                       continue;
-               (*i)->get_control_info (chn, ev, extra);
-               if (!on) {
-                       chn = -1;
-               }
-               (*i)->midi_rebind (port, chn);
-       }
-}
+       float val = plugin.get_parameter (absolute_port);
 
-void
-Plugin::send_all_midi_feedback ()
-{
-       if (_session.get_midi_feedback()) {
-               float val = 0.0;
-               uint32_t n = 0;
+       if (toggled) {
                
-               for (vector<MIDIPortControl*>::iterator i = midi_controls.begin(); i != midi_controls.end(); ++i, ++n) {
-                       if (*i == 0) {
-                               continue;
-                       }
-
-                       val = (*i)->plugin.get_parameter (n);
-                       (*i)->send_feedback (val);
-               }
+               return val;
                
-       }
-}
-
-MIDI::byte*
-Plugin::write_midi_feedback (MIDI::byte* buf, int32_t& bufsize)
-{
-       if (_session.get_midi_feedback()) {
-               float val = 0.0;
-               uint32_t n = 0;
+       } else {
                
-               for (vector<MIDIPortControl*>::iterator i = midi_controls.begin(); i != midi_controls.end(); ++i, ++n) {
-                       if (*i == 0) {
-                               continue;
-                       }
-
-                       val = (*i)->plugin.get_parameter (n);
-                       buf = (*i)->write_feedback (buf, bufsize, val);
+               if (logarithmic) {
+                       val = log(val);
                }
+               
+               return ((val - lower) / range);
        }
-
-       return buf;
-}
+}      
 
 vector<string>
 Plugin::get_presets()
@@ -352,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 b096e817857e65e5fa9dcdab258cf59ef0a55e03..096696aca56dc67b8bf97522eef03b648a85a041 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
@@ -27,7 +27,7 @@
 #include <fst.h>
 #include <pbd/basename.h>
 #include <string.h>
-#endif
+#endif // VST_SUPPORT
 
 #include <pbd/pathscanner.h>
 
 #include <ardour/plugin_manager.h>
 #include <ardour/plugin.h>
 #include <ardour/ladspa_plugin.h>
+
+#ifdef VST_SUPPORT
 #include <ardour/vst_plugin.h>
+#endif
 
 #include <pbd/error.h>
 #include <pbd/stl_delete.h>
@@ -48,8 +51,7 @@ using namespace PBD;
 
 PluginManager* PluginManager::_manager = 0;
 
-PluginManager::PluginManager (AudioEngine& e)
-       : _engine (e)
+PluginManager::PluginManager ()
 {
        char* s;
        string lrdf_path;
@@ -95,16 +97,12 @@ PluginManager::refresh ()
        if (Config->get_use_vst()) {
                vst_refresh ();
        }
-#endif
+#endif // VST_SUPPORT
 }
 
 void
 PluginManager::ladspa_refresh ()
 {
-       for (std::list<PluginInfo*>::iterator i = _ladspa_plugin_info.begin(); i != _ladspa_plugin_info.end(); ++i) {
-               delete *i;
-       }
-
        _ladspa_plugin_info.clear ();
 
        if (ladspa_path.length() == 0) {
@@ -225,7 +223,6 @@ PluginManager::add_lrdf_data (const string &path)
 int 
 PluginManager::ladspa_discover (string path)
 {
-       PluginInfo *info;
        void *module;
        const LADSPA_Descriptor *descriptor;
        LADSPA_Descriptor_Function dfunc;
@@ -250,7 +247,7 @@ PluginManager::ladspa_discover (string path)
                        break;
                }
 
-               info = new PluginInfo;
+               PluginInfoPtr info(new LadspaPluginInfo);
                info->name = descriptor->Name;
                info->category = get_ladspa_category(descriptor->UniqueID);
                info->path = path;
@@ -280,82 +277,6 @@ PluginManager::ladspa_discover (string path)
        return 0;
 }
 
-Plugin *
-PluginManager::load (Session& session, PluginInfo *info)
-{
-       void *module;
-       Plugin *plugin = 0;
-
-       try {
-               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 = new VSTPlugin (_engine, session, handle);
-                               }
-                       } else {
-                               error << _("You asked ardour to not use any VST plugins") << endmsg;
-                       }
-#else
-                       error << _("This version of ardour has no support for VST plugins") << endmsg;
-                       return 0;
-#endif                 
-                               
-               } 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 = new LadspaPlugin (module, _engine, session, info->index, session.frame_rate());
-                       }
-               }
-
-               plugin->set_info(*info);
-       }
-
-       catch (failed_constructor &err) {
-               plugin = 0;
-       }
-       
-       return plugin;
-}
-
-Plugin *
-ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginInfo::Type type)
-{
-       PluginManager *mgr = PluginManager::the_manager();
-       list<PluginInfo *>::iterator i;
-       list<PluginInfo *>* 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:
-       default:
-               return 0;
-       }
-
-       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 0;
-}
-
 string
 PluginManager::get_ladspa_category (uint32_t plugin_id)
 {
@@ -397,10 +318,6 @@ PluginManager::get_ladspa_category (uint32_t plugin_id)
 void
 PluginManager::vst_refresh ()
 {
-       for (std::list<PluginInfo*>::iterator i = _vst_plugin_info.begin(); i != _vst_plugin_info.end(); ++i) {
-               delete *i;
-       }
-
        _vst_plugin_info.clear ();
 
        if (vst_path.length() == 0) {
@@ -454,7 +371,6 @@ int
 PluginManager::vst_discover (string path)
 {
        FSTInfo* finfo;
-       PluginInfo* info;
 
        if ((finfo = fst_get_info (const_cast<char *> (path.c_str()))) == 0) {
                return -1;
@@ -466,7 +382,7 @@ PluginManager::vst_discover (string path)
                        << endl;
        }
        
-       info = new PluginInfo;
+       PluginInfoPtr info(new PluginInfo);
 
        /* what a goddam joke freeware VST is */
 
@@ -489,4 +405,4 @@ PluginManager::vst_discover (string path)
        return 0;
 }
 
-#endif
+#endif // VST_SUPPORT
index 33c1bb6e8563f3bb9058837a32163183b8475327..5d8adef7d0be6c25e412e8d78af595bfdd2de3fc 100644 (file)
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: libardour 0.664.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-06-27 13:00-0400\n"
+"POT-Creation-Date: 2006-06-29 21:03-0400\n"
 "PO-Revision-Date: 2003-05-21 12:50+0500\n"
 "Last-Translator: Muadibas\n"
 "Language-Team: Hellenic(Greek)\n"
@@ -56,47 +56,47 @@ msgid "AudioDiskstream \"%1\": cannot flush captured data to disk!"
 msgstr ""
 "DiskStream \"%1\": δεν γίνεται να απορριφθούν δειγματοληψίες στο δίσκο!"
 
-#: libs/ardour/audio_diskstream.cc:1795
+#: libs/ardour/audio_diskstream.cc:1796
 msgid "%1: could not create region for complete audio file"
 msgstr "%1: δεν μπόρεσα να δημιουργήσω περιοχή για ολόκληρο audio file"
 
-#: libs/ardour/audio_diskstream.cc:1818
+#: libs/ardour/audio_diskstream.cc:1819
 #, fuzzy
 msgid "AudioDiskstream: could not create region for captured audio!"
 msgstr "DiskStream: δεν μπόρεσα να δημιουργήσω περιοχή για δειγματοληψίες!"
 
-#: libs/ardour/audio_diskstream.cc:1873
+#: libs/ardour/audio_diskstream.cc:1874
 #, fuzzy
 msgid "programmer error: %1"
 msgstr "σφάλμα προγραμματισμού: %1"
 
-#: libs/ardour/audio_diskstream.cc:2145
+#: libs/ardour/audio_diskstream.cc:2146
 #, fuzzy
 msgid "AudioDiskstream: channel %1 out of range"
 msgstr "DiskStream: κανάλι εκτός διαστήματος"
 
-#: libs/ardour/audio_diskstream.cc:2170
+#: libs/ardour/audio_diskstream.cc:2171
 msgid "%1:%2 new capture file not initialized correctly"
 msgstr "%1:%2 νέα δειγματοληψία δεν εκκινήθη σωστά"
 
-#: libs/ardour/audio_diskstream.cc:2403
+#: libs/ardour/audio_diskstream.cc:2404
 msgid "Location \"%1\" not valid for track loop (start >= end)"
 msgstr "Η Τοποθεσία \"%1\" δεν είναι ικανή για track loop (αρχή >= τέλος)"
 
-#: libs/ardour/audio_diskstream.cc:2484
+#: libs/ardour/audio_diskstream.cc:2485
 #, fuzzy
 msgid "%1: cannot restore pending capture source file %2"
 msgstr "Εισαγωγή: δεν μπορώ να ανοίξω το εισαγμένο αρχείο ήχου \"%1\""
 
-#: libs/ardour/audio_diskstream.cc:2506
+#: libs/ardour/audio_diskstream.cc:2507
 msgid "%1: incorrect number of pending sources listed - ignoring them all"
 msgstr ""
 
-#: libs/ardour/audio_diskstream.cc:2522
+#: libs/ardour/audio_diskstream.cc:2523
 msgid "%1: cannot create whole-file region from pending capture sources"
 msgstr ""
 
-#: libs/ardour/audio_diskstream.cc:2534
+#: libs/ardour/audio_diskstream.cc:2535
 #, fuzzy
 msgid "%1: cannot create region from pending capture sources"
 msgstr "%1: δεν μπόρεσα να δημιουργήσω περιοχή για ολόκληρο audio file"
@@ -155,36 +155,36 @@ msgstr "αλλαγή xfade"
 msgid "region modified"
 msgstr "η περιοχή μετεβλήθη"
 
-#: libs/ardour/audio_track.cc:133 libs/ardour/io.cc:1716
+#: libs/ardour/audio_track.cc:125 libs/ardour/io.cc:1716
 #: libs/ardour/io.cc:1826
 msgid "Unknown connection \"%1\" listed for input of %2"
 msgstr "Άγνωστη σύνδεση \"%1\" στη λίστα εισόδου του %2"
 
-#: libs/ardour/audio_track.cc:135 libs/ardour/io.cc:1718
+#: libs/ardour/audio_track.cc:127 libs/ardour/io.cc:1718
 #: libs/ardour/io.cc:1828
 #, fuzzy
 msgid "in 1"
 msgstr "in %lu"
 
-#: libs/ardour/audio_track.cc:136 libs/ardour/io.cc:1719
+#: libs/ardour/audio_track.cc:128 libs/ardour/io.cc:1719
 #: libs/ardour/io.cc:1829
 msgid "No input connections available as a replacement"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:140 libs/ardour/io.cc:1723
+#: libs/ardour/audio_track.cc:132 libs/ardour/io.cc:1723
 #: libs/ardour/io.cc:1833
 msgid "Connection %1 was not available - \"in 1\" used instead"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:149 libs/ardour/io.cc:1842
+#: libs/ardour/audio_track.cc:141 libs/ardour/io.cc:1842
 msgid "improper input channel list in XML node (%1)"
 msgstr "ακατάλληλη λίστα καναλιών εισόδου στον κόμβο XML (%1)"
 
-#: libs/ardour/audio_track.cc:194 libs/ardour/audio_track.cc:207
+#: libs/ardour/audio_track.cc:186 libs/ardour/audio_track.cc:199
 msgid "AudioTrack: diskstream \"%1\" not known by session"
 msgstr "AudioTrack: το diskstream \"%1\" είναι μή αναγνωρίσιμο από τη συνεδρία"
 
-#: libs/ardour/audio_track.cc:305
+#: libs/ardour/audio_track.cc:297
 #, fuzzy
 msgid ""
 "MIDI rec_enable control specification for %1 is incomplete, so it has been "
@@ -193,7 +193,7 @@ msgstr ""
 "Η προδιαγραφή ελέγχου του MIDI gain για το %1 είναι ημιτελής, με αποτέλεσμα "
 "να αγνοηθεί"
 
-#: libs/ardour/audio_track.cc:317
+#: libs/ardour/audio_track.cc:309
 msgid "programming error: AudioTrack given state without diskstream!"
 msgstr ""
 "σφάλμα προγραμματισμού: εδόθη κατάσταση στην AudioTrack δίχως diskstream!"
@@ -272,24 +272,24 @@ msgstr "Σφάλμα: δεν μπόρεσα να γράψω %1"
 msgid "could not reconnect %1 and %2 (err = %3)"
 msgstr ""
 
-#: libs/ardour/audiofilesource.cc:445 libs/ardour/session_state.cc:3095
+#: libs/ardour/audiofilesource.cc:444 libs/ardour/session_state.cc:3095
 msgid ""
 "there are already 1000 files with names like %1; versioning discontinued"
 msgstr "Υπάρχουν ήδη 1000 αρχεία με ονόματα όπως %1; μη-συνεχές versioning"
 
-#: libs/ardour/audiofilesource.cc:459 libs/ardour/session_state.cc:3109
+#: libs/ardour/audiofilesource.cc:458 libs/ardour/session_state.cc:3109
 msgid "cannot rename audio file source from %1 to %2 (%3)"
 msgstr "δεν μπορώ να μετονομάσω την πηγή του audio file από %1 σε %2 (%3)"
 
-#: libs/ardour/audiofilesource.cc:466 libs/ardour/session_state.cc:3124
+#: libs/ardour/audiofilesource.cc:465 libs/ardour/session_state.cc:3124
 msgid "cannot remove peakfile %1 for %2 (%3)"
 msgstr "δεν μπορώ να απαλοίψω το peakfile %1 για %2 (%3)"
 
-#: libs/ardour/audiofilesource.cc:510
+#: libs/ardour/audiofilesource.cc:509
 msgid "FileSource: search path not set"
 msgstr "FileSource: μονοπάτι αναζητήσεως δεν ετέθη"
 
-#: libs/ardour/audiofilesource.cc:534
+#: libs/ardour/audiofilesource.cc:533
 msgid ""
 "FileSource: \"%1\" is ambigous when searching %2\n"
 "\t"
@@ -297,25 +297,25 @@ msgstr ""
 "FileSource: \"%1\" είναι αμφίβολο κατά την αναζήτηση του %2\n"
 "\t"
 
-#: libs/ardour/audiofilesource.cc:540
+#: libs/ardour/audiofilesource.cc:539
 #, fuzzy
 msgid "Filesource: cannot find required file (%1): while searching %2"
 msgstr "Filesource: δεν ευρέθη το απαιτούμενο αρχείο (%1): %2"
 
-#: libs/ardour/audiofilesource.cc:563
+#: libs/ardour/audiofilesource.cc:562
 msgid "Filesource: cannot find required file (%1): %2"
 msgstr "Filesource: δεν ευρέθη το απαιτούμενο αρχείο (%1): %2"
 
-#: libs/ardour/audiofilesource.cc:568
+#: libs/ardour/audiofilesource.cc:567
 msgid "Filesource: cannot check for existing file (%1): %2"
 msgstr "Filesource: δεν μπορώ να ελέγξω για το υπάρχον αρχείο (%1): %2"
 
-#: libs/ardour/audiofilesource.cc:640 libs/ardour/insert.cc:525
-#: libs/ardour/sndfilesource.cc:112
+#: libs/ardour/audiofilesource.cc:636 libs/ardour/insert.cc:525
+#: libs/ardour/sndfilesource.cc:113
 msgid "programming error: %1"
 msgstr "σφάλμα προγραμματισμού: %1"
 
-#: libs/ardour/audiofilesource.cc:645
+#: libs/ardour/audiofilesource.cc:641
 #, fuzzy
 msgid "cannot rename audio file for %1 to %2"
 msgstr "δεν μπορώ να μετονομάσω την πηγή του audio file από %1 σε %2 (%3)"
@@ -1837,7 +1837,7 @@ msgstr ""
 msgid "cannot remove dead sound file %1 (%2)"
 msgstr "δεν μπορώ να απαλοίψω το 'νεκρο' ηχο-αρχείο %1 (%2)"
 
-#: libs/ardour/session_time.cc:375
+#: libs/ardour/session_time.cc:374
 msgid "Unknown JACK transport state %1 in sync callback"
 msgstr "Άγνωστη κατάσταση του JACK transport %1 στην ανάκληση sync"
 
@@ -1979,24 +1979,24 @@ msgstr "Little-endian (Intel)"
 msgid "Big-endian (Mac)"
 msgstr "Big-endian (Mac)"
 
-#: libs/ardour/sndfilesource.cc:146
+#: libs/ardour/sndfilesource.cc:147
 msgid "FileSource: cannot get host information for BWF header (%1)"
 msgstr ""
 "FileSource: δεν μπορώ να βρώ πληροφορίες οικοδεσπότη(host) για επικεφαλίδα "
 "BWF (%1)"
 
-#: libs/ardour/sndfilesource.cc:168
+#: libs/ardour/sndfilesource.cc:169
 msgid ""
 "cannot set broadcast info for audio file %1 (%2); dropping broadcast info "
 "for this file"
 msgstr ""
 
-#: libs/ardour/sndfilesource.cc:224
+#: libs/ardour/sndfilesource.cc:220
 #, fuzzy
 msgid "SndFileSource: cannot open file \"%1\" for %2 (%3)"
 msgstr "SndFileSource: δεν μπορώ να ανοίξω το αρχείο \"%1\" (%2)"
 
-#: libs/ardour/sndfilesource.cc:230
+#: libs/ardour/sndfilesource.cc:226
 msgid ""
 "SndFileSource: file only contains %1 channels; %2 is invalid as a channel "
 "number"
@@ -2004,22 +2004,22 @@ msgstr ""
 "SndFileSource: το αρχείο περιέχει μόνο %1 κανάλια; %2 δεν έχει αξία σαν "
 "κανάλι number"
 
-#: libs/ardour/sndfilesource.cc:307
+#: libs/ardour/sndfilesource.cc:327
 msgid "SndFileSource: could not seek to frame %1 within %2 (%3)"
 msgstr "SndFileSource: δεν μπορούσα να αναζητήσω στο frame %1 μέσα στο %2 (%3)"
 
-#: libs/ardour/sndfilesource.cc:358
+#: libs/ardour/sndfilesource.cc:378
 #, fuzzy
 msgid "programming error: %1 %2"
 msgstr "σφάλμα προγραμματισμού: %1"
 
-#: libs/ardour/sndfilesource.cc:458
+#: libs/ardour/sndfilesource.cc:487 libs/ardour/sndfilesource.cc:533
 msgid ""
 "cannot set broadcast info for audio file %1; Dropping broadcast info for "
 "this file"
 msgstr ""
 
-#: libs/ardour/sndfilesource.cc:500
+#: libs/ardour/sndfilesource.cc:544
 #, fuzzy
 msgid "%1: cannot seek to %2"
 msgstr "%1: δεν μπορώ να αναζητήσω στο %2 για εξαγωγή"
@@ -2166,7 +2166,7 @@ msgid "no support for presets using chunks at this time"
 msgstr ""
 "καμμία υποστήριξη αυτή τη στιγμή για ρυθμίσεις που χρησιμοποιούν κομμάτια"
 
-#: libs/ardour/coreaudio_source.cc:99
+#: libs/ardour/coreaudiosource.cc:97
 #, fuzzy
 msgid ""
 "CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel "
@@ -2175,7 +2175,7 @@ msgstr ""
 "SndFileSource: το αρχείο περιέχει μόνο %1 κανάλια; %2 δεν έχει αξία σαν "
 "κανάλι number"
 
-#: libs/ardour/coreaudio_source.cc:164
+#: libs/ardour/coreaudiosource.cc:162
 #, fuzzy
 msgid "CoreAudioSource: could not seek to frame %1 within %2 (%3)"
 msgstr "SndFileSource: δεν μπορούσα να αναζητήσω στο frame %1 μέσα στο %2 (%3)"
index 63089ea77f52abd568402e0b0d74fb797c484655..2ce02827bd83eab31ae68f1dcda71e4a2bbcc03d 100644 (file)
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: libardour 0.664.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-06-27 13:00-0400\n"
+"POT-Creation-Date: 2006-06-29 21:03-0400\n"
 "PO-Revision-Date: 2003-05-21 12:50+0500\n"
 "Last-Translator: Filippo Pappalardo <filippo@email.it>\n"
 "Language-Team: Italian\n"
@@ -50,48 +50,48 @@ msgstr "DiskStream %1: impossibile scrivere sul disco"
 msgid "AudioDiskstream \"%1\": cannot flush captured data to disk!"
 msgstr "DiskStream \"%1\": impossibile scaricare i dati acquisiti sul disco!"
 
-#: libs/ardour/audio_diskstream.cc:1795
+#: libs/ardour/audio_diskstream.cc:1796
 msgid "%1: could not create region for complete audio file"
 msgstr "%1: impossibile creare una regione per il file audio completo"
 
-#: libs/ardour/audio_diskstream.cc:1818
+#: libs/ardour/audio_diskstream.cc:1819
 #, fuzzy
 msgid "AudioDiskstream: could not create region for captured audio!"
 msgstr "DiskStream: impossibile creare una regione per l'audio registrato!"
 
-#: libs/ardour/audio_diskstream.cc:1873
+#: libs/ardour/audio_diskstream.cc:1874
 #, fuzzy
 msgid "programmer error: %1"
 msgstr "errore di programmazione: %1"
 
-#: libs/ardour/audio_diskstream.cc:2145
+#: libs/ardour/audio_diskstream.cc:2146
 #, fuzzy
 msgid "AudioDiskstream: channel %1 out of range"
 msgstr "DiskStream: canale fuori margine"
 
-#: libs/ardour/audio_diskstream.cc:2170
+#: libs/ardour/audio_diskstream.cc:2171
 msgid "%1:%2 new capture file not initialized correctly"
 msgstr "%1:%2 nuovo file di registrazione non � stato avviato correttamente"
 
-#: libs/ardour/audio_diskstream.cc:2403
+#: libs/ardour/audio_diskstream.cc:2404
 msgid "Location \"%1\" not valid for track loop (start >= end)"
 msgstr "La Location \"%1\" non  valida per il loop (inizio >= fine)"
 
-#: libs/ardour/audio_diskstream.cc:2484
+#: libs/ardour/audio_diskstream.cc:2485
 #, fuzzy
 msgid "%1: cannot restore pending capture source file %2"
 msgstr "Import: impossibile aprire il file audio di input \"%1\""
 
-#: libs/ardour/audio_diskstream.cc:2506
+#: libs/ardour/audio_diskstream.cc:2507
 msgid "%1: incorrect number of pending sources listed - ignoring them all"
 msgstr ""
 
-#: libs/ardour/audio_diskstream.cc:2522
+#: libs/ardour/audio_diskstream.cc:2523
 #, fuzzy
 msgid "%1: cannot create whole-file region from pending capture sources"
 msgstr "Playlist: impossibile creare la Regione dal file di stato"
 
-#: libs/ardour/audio_diskstream.cc:2534
+#: libs/ardour/audio_diskstream.cc:2535
 #, fuzzy
 msgid "%1: cannot create region from pending capture sources"
 msgstr "Playlist: impossibile creare la Regione dal file di stato"
@@ -145,41 +145,41 @@ msgstr "cambio dello smorzamento incrociato"
 msgid "region modified"
 msgstr "regione modificata"
 
-#: libs/ardour/audio_track.cc:133 libs/ardour/io.cc:1716
+#: libs/ardour/audio_track.cc:125 libs/ardour/io.cc:1716
 #: libs/ardour/io.cc:1826
 msgid "Unknown connection \"%1\" listed for input of %2"
 msgstr "Connessione sconosciuta \"%1\" come input di %2"
 
-#: libs/ardour/audio_track.cc:135 libs/ardour/io.cc:1718
+#: libs/ardour/audio_track.cc:127 libs/ardour/io.cc:1718
 #: libs/ardour/io.cc:1828
 msgid "in 1"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:136 libs/ardour/io.cc:1719
+#: libs/ardour/audio_track.cc:128 libs/ardour/io.cc:1719
 #: libs/ardour/io.cc:1829
 msgid "No input connections available as a replacement"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:140 libs/ardour/io.cc:1723
+#: libs/ardour/audio_track.cc:132 libs/ardour/io.cc:1723
 #: libs/ardour/io.cc:1833
 msgid "Connection %1 was not available - \"in 1\" used instead"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:149 libs/ardour/io.cc:1842
+#: libs/ardour/audio_track.cc:141 libs/ardour/io.cc:1842
 msgid "improper input channel list in XML node (%1)"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:194 libs/ardour/audio_track.cc:207
+#: libs/ardour/audio_track.cc:186 libs/ardour/audio_track.cc:199
 msgid "AudioTrack: diskstream \"%1\" not known by session"
 msgstr "AudioTrack: diskstream \"%1\" non riconosciuto dalla sessione"
 
-#: libs/ardour/audio_track.cc:305
+#: libs/ardour/audio_track.cc:297
 msgid ""
 "MIDI rec_enable control specification for %1 is incomplete, so it has been "
 "ignored"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:317
+#: libs/ardour/audio_track.cc:309
 msgid "programming error: AudioTrack given state without diskstream!"
 msgstr ""
 
@@ -268,25 +268,25 @@ msgstr "Esportazione: impossibile scrivere dati sul file di output (%1)"
 msgid "could not reconnect %1 and %2 (err = %3)"
 msgstr ""
 
-#: libs/ardour/audiofilesource.cc:445 libs/ardour/session_state.cc:3095
+#: libs/ardour/audiofilesource.cc:444 libs/ardour/session_state.cc:3095
 msgid ""
 "there are already 1000 files with names like %1; versioning discontinued"
 msgstr ""
 "ci sono gia' 1000 file con nomi come %1; tracciamento di versione interrotto"
 
-#: libs/ardour/audiofilesource.cc:459 libs/ardour/session_state.cc:3109
+#: libs/ardour/audiofilesource.cc:458 libs/ardour/session_state.cc:3109
 msgid "cannot rename audio file source from %1 to %2 (%3)"
 msgstr "impossibile rinominare file audio sorgente da %1 a %2 (%3)"
 
-#: libs/ardour/audiofilesource.cc:466 libs/ardour/session_state.cc:3124
+#: libs/ardour/audiofilesource.cc:465 libs/ardour/session_state.cc:3124
 msgid "cannot remove peakfile %1 for %2 (%3)"
 msgstr "impossibile eliminare il peakfile %1 per %2 (%3)"
 
-#: libs/ardour/audiofilesource.cc:510
+#: libs/ardour/audiofilesource.cc:509
 msgid "FileSource: search path not set"
 msgstr "FileSource: percorso di ricerca non specificato"
 
-#: libs/ardour/audiofilesource.cc:534
+#: libs/ardour/audiofilesource.cc:533
 msgid ""
 "FileSource: \"%1\" is ambigous when searching %2\n"
 "\t"
@@ -294,25 +294,25 @@ msgstr ""
 "FileSource: \"%1\" � risultato ambiguo nel cercare %2\n"
 "\t"
 
-#: libs/ardour/audiofilesource.cc:540
+#: libs/ardour/audiofilesource.cc:539
 #, fuzzy
 msgid "Filesource: cannot find required file (%1): while searching %2"
 msgstr "FileSource: impossibile trovare il file richiesto (%1): %2"
 
-#: libs/ardour/audiofilesource.cc:563
+#: libs/ardour/audiofilesource.cc:562
 msgid "Filesource: cannot find required file (%1): %2"
 msgstr "FileSource: impossibile trovare il file richiesto (%1): %2"
 
-#: libs/ardour/audiofilesource.cc:568
+#: libs/ardour/audiofilesource.cc:567
 msgid "Filesource: cannot check for existing file (%1): %2"
 msgstr "FileSource: impossibile controllare il file esistente (%1): %2"
 
-#: libs/ardour/audiofilesource.cc:640 libs/ardour/insert.cc:525
-#: libs/ardour/sndfilesource.cc:112
+#: libs/ardour/audiofilesource.cc:636 libs/ardour/insert.cc:525
+#: libs/ardour/sndfilesource.cc:113
 msgid "programming error: %1"
 msgstr "errore di programmazione: %1"
 
-#: libs/ardour/audiofilesource.cc:645
+#: libs/ardour/audiofilesource.cc:641
 #, fuzzy
 msgid "cannot rename audio file for %1 to %2"
 msgstr "impossibile rinominare file audio sorgente da %1 a %2 (%3)"
@@ -1782,7 +1782,7 @@ msgstr "Nodo sconosciuto \"%1\" trovato in Connections list dal file di stato"
 msgid "cannot remove dead sound file %1 (%2)"
 msgstr "impossibile accedere al file audio per il click %1 (%2)"
 
-#: libs/ardour/session_time.cc:375
+#: libs/ardour/session_time.cc:374
 msgid "Unknown JACK transport state %1 in sync callback"
 msgstr ""
 
@@ -1915,22 +1915,22 @@ msgstr ""
 msgid "Big-endian (Mac)"
 msgstr ""
 
-#: libs/ardour/sndfilesource.cc:146
+#: libs/ardour/sndfilesource.cc:147
 msgid "FileSource: cannot get host information for BWF header (%1)"
 msgstr "FileSource: impossibile ottenere info sull'host dall'header BWF (%1)"
 
-#: libs/ardour/sndfilesource.cc:168
+#: libs/ardour/sndfilesource.cc:169
 msgid ""
 "cannot set broadcast info for audio file %1 (%2); dropping broadcast info "
 "for this file"
 msgstr ""
 
-#: libs/ardour/sndfilesource.cc:224
+#: libs/ardour/sndfilesource.cc:220
 #, fuzzy
 msgid "SndFileSource: cannot open file \"%1\" for %2 (%3)"
 msgstr "SndFileSource: impossibile accedere al file \"%1\" (%2)"
 
-#: libs/ardour/sndfilesource.cc:230
+#: libs/ardour/sndfilesource.cc:226
 msgid ""
 "SndFileSource: file only contains %1 channels; %2 is invalid as a channel "
 "number"
@@ -1938,22 +1938,22 @@ msgstr ""
 "SndFileSource: il file contiene solo %1 canali; %2 non � valido come numero "
 "di canale"
 
-#: libs/ardour/sndfilesource.cc:307
+#: libs/ardour/sndfilesource.cc:327
 msgid "SndFileSource: could not seek to frame %1 within %2 (%3)"
 msgstr ""
 
-#: libs/ardour/sndfilesource.cc:358
+#: libs/ardour/sndfilesource.cc:378
 #, fuzzy
 msgid "programming error: %1 %2"
 msgstr "errore di programmazione: %1"
 
-#: libs/ardour/sndfilesource.cc:458
+#: libs/ardour/sndfilesource.cc:487 libs/ardour/sndfilesource.cc:533
 msgid ""
 "cannot set broadcast info for audio file %1; Dropping broadcast info for "
 "this file"
 msgstr ""
 
-#: libs/ardour/sndfilesource.cc:500
+#: libs/ardour/sndfilesource.cc:544
 msgid "%1: cannot seek to %2"
 msgstr ""
 
@@ -2100,7 +2100,7 @@ msgstr ""
 msgid "no support for presets using chunks at this time"
 msgstr ""
 
-#: libs/ardour/coreaudio_source.cc:99
+#: libs/ardour/coreaudiosource.cc:97
 #, fuzzy
 msgid ""
 "CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel "
@@ -2109,7 +2109,7 @@ msgstr ""
 "SndFileSource: il file contiene solo %1 canali; %2 non � valido come numero "
 "di canale"
 
-#: libs/ardour/coreaudio_source.cc:164
+#: libs/ardour/coreaudiosource.cc:162
 msgid "CoreAudioSource: could not seek to frame %1 within %2 (%3)"
 msgstr ""
 
index 2ca30cba5501c3cc9b8688a5d63a4f5d16359c7e..aeeb1bf547783c740797c217463d328a7df7e859 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: libardour 0.716.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-06-27 13:00-0400\n"
+"POT-Creation-Date: 2006-06-29 21:03-0400\n"
 "PO-Revision-Date: 2004-03-31 00:55+0300\n"
 "Last-Translator: Igor Blinov pitstop@nm.ru\n"
 "Language-Team: Russian\n"
@@ -43,44 +43,44 @@ msgstr ""
 msgid "AudioDiskstream \"%1\": cannot flush captured data to disk!"
 msgstr ""
 
-#: libs/ardour/audio_diskstream.cc:1795
+#: libs/ardour/audio_diskstream.cc:1796
 msgid "%1: could not create region for complete audio file"
 msgstr ""
 
-#: libs/ardour/audio_diskstream.cc:1818
+#: libs/ardour/audio_diskstream.cc:1819
 msgid "AudioDiskstream: could not create region for captured audio!"
 msgstr ""
 
-#: libs/ardour/audio_diskstream.cc:1873
+#: libs/ardour/audio_diskstream.cc:1874
 #, fuzzy
 msgid "programmer error: %1"
 msgstr "������ ���������: "
 
-#: libs/ardour/audio_diskstream.cc:2145
+#: libs/ardour/audio_diskstream.cc:2146
 msgid "AudioDiskstream: channel %1 out of range"
 msgstr ""
 
-#: libs/ardour/audio_diskstream.cc:2170
+#: libs/ardour/audio_diskstream.cc:2171
 msgid "%1:%2 new capture file not initialized correctly"
 msgstr ""
 
-#: libs/ardour/audio_diskstream.cc:2403
+#: libs/ardour/audio_diskstream.cc:2404
 msgid "Location \"%1\" not valid for track loop (start >= end)"
 msgstr ""
 
-#: libs/ardour/audio_diskstream.cc:2484
+#: libs/ardour/audio_diskstream.cc:2485
 msgid "%1: cannot restore pending capture source file %2"
 msgstr ""
 
-#: libs/ardour/audio_diskstream.cc:2506
+#: libs/ardour/audio_diskstream.cc:2507
 msgid "%1: incorrect number of pending sources listed - ignoring them all"
 msgstr ""
 
-#: libs/ardour/audio_diskstream.cc:2522
+#: libs/ardour/audio_diskstream.cc:2523
 msgid "%1: cannot create whole-file region from pending capture sources"
 msgstr ""
 
-#: libs/ardour/audio_diskstream.cc:2534
+#: libs/ardour/audio_diskstream.cc:2535
 msgid "%1: cannot create region from pending capture sources"
 msgstr ""
 
@@ -133,41 +133,41 @@ msgstr ""
 msgid "region modified"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:133 libs/ardour/io.cc:1716
+#: libs/ardour/audio_track.cc:125 libs/ardour/io.cc:1716
 #: libs/ardour/io.cc:1826
 msgid "Unknown connection \"%1\" listed for input of %2"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:135 libs/ardour/io.cc:1718
+#: libs/ardour/audio_track.cc:127 libs/ardour/io.cc:1718
 #: libs/ardour/io.cc:1828
 msgid "in 1"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:136 libs/ardour/io.cc:1719
+#: libs/ardour/audio_track.cc:128 libs/ardour/io.cc:1719
 #: libs/ardour/io.cc:1829
 msgid "No input connections available as a replacement"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:140 libs/ardour/io.cc:1723
+#: libs/ardour/audio_track.cc:132 libs/ardour/io.cc:1723
 #: libs/ardour/io.cc:1833
 msgid "Connection %1 was not available - \"in 1\" used instead"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:149 libs/ardour/io.cc:1842
+#: libs/ardour/audio_track.cc:141 libs/ardour/io.cc:1842
 msgid "improper input channel list in XML node (%1)"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:194 libs/ardour/audio_track.cc:207
+#: libs/ardour/audio_track.cc:186 libs/ardour/audio_track.cc:199
 msgid "AudioTrack: diskstream \"%1\" not known by session"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:305
+#: libs/ardour/audio_track.cc:297
 msgid ""
 "MIDI rec_enable control specification for %1 is incomplete, so it has been "
 "ignored"
 msgstr ""
 
-#: libs/ardour/audio_track.cc:317
+#: libs/ardour/audio_track.cc:309
 msgid "programming error: AudioTrack given state without diskstream!"
 msgstr ""
 
@@ -243,48 +243,48 @@ msgstr ""
 msgid "could not reconnect %1 and %2 (err = %3)"
 msgstr ""
 
-#: libs/ardour/audiofilesource.cc:445 libs/ardour/session_state.cc:3095
+#: libs/ardour/audiofilesource.cc:444 libs/ardour/session_state.cc:3095
 msgid ""
 "there are already 1000 files with names like %1; versioning discontinued"
 msgstr ""
 
-#: libs/ardour/audiofilesource.cc:459 libs/ardour/session_state.cc:3109
+#: libs/ardour/audiofilesource.cc:458 libs/ardour/session_state.cc:3109
 msgid "cannot rename audio file source from %1 to %2 (%3)"
 msgstr ""
 
-#: libs/ardour/audiofilesource.cc:466 libs/ardour/session_state.cc:3124
+#: libs/ardour/audiofilesource.cc:465 libs/ardour/session_state.cc:3124
 msgid "cannot remove peakfile %1 for %2 (%3)"
 msgstr ""
 
-#: libs/ardour/audiofilesource.cc:510
+#: libs/ardour/audiofilesource.cc:509
 msgid "FileSource: search path not set"
 msgstr ""
 
-#: libs/ardour/audiofilesource.cc:534
+#: libs/ardour/audiofilesource.cc:533
 msgid ""
 "FileSource: \"%1\" is ambigous when searching %2\n"
 "\t"
 msgstr ""
 
-#: libs/ardour/audiofilesource.cc:540
+#: libs/ardour/audiofilesource.cc:539
 msgid "Filesource: cannot find required file (%1): while searching %2"
 msgstr ""
 
-#: libs/ardour/audiofilesource.cc:563
+#: libs/ardour/audiofilesource.cc:562
 msgid "Filesource: cannot find required file (%1): %2"
 msgstr ""
 
-#: libs/ardour/audiofilesource.cc:568
+#: libs/ardour/audiofilesource.cc:567
 msgid "Filesource: cannot check for existing file (%1): %2"
 msgstr ""
 
-#: libs/ardour/audiofilesource.cc:640 libs/ardour/insert.cc:525
-#: libs/ardour/sndfilesource.cc:112
+#: libs/ardour/audiofilesource.cc:636 libs/ardour/insert.cc:525
+#: libs/ardour/sndfilesource.cc:113
 #, fuzzy
 msgid "programming error: %1"
 msgstr "������ ���������: "
 
-#: libs/ardour/audiofilesource.cc:645
+#: libs/ardour/audiofilesource.cc:641
 msgid "cannot rename audio file for %1 to %2"
 msgstr ""
 
@@ -1684,7 +1684,7 @@ msgstr ""
 msgid "cannot remove dead sound file %1 (%2)"
 msgstr ""
 
-#: libs/ardour/session_time.cc:375
+#: libs/ardour/session_time.cc:374
 msgid "Unknown JACK transport state %1 in sync callback"
 msgstr ""
 
@@ -1816,42 +1816,42 @@ msgstr ""
 msgid "Big-endian (Mac)"
 msgstr ""
 
-#: libs/ardour/sndfilesource.cc:146
+#: libs/ardour/sndfilesource.cc:147
 msgid "FileSource: cannot get host information for BWF header (%1)"
 msgstr ""
 
-#: libs/ardour/sndfilesource.cc:168
+#: libs/ardour/sndfilesource.cc:169
 msgid ""
 "cannot set broadcast info for audio file %1 (%2); dropping broadcast info "
 "for this file"
 msgstr ""
 
-#: libs/ardour/sndfilesource.cc:224
+#: libs/ardour/sndfilesource.cc:220
 msgid "SndFileSource: cannot open file \"%1\" for %2 (%3)"
 msgstr ""
 
-#: libs/ardour/sndfilesource.cc:230
+#: libs/ardour/sndfilesource.cc:226
 msgid ""
 "SndFileSource: file only contains %1 channels; %2 is invalid as a channel "
 "number"
 msgstr ""
 
-#: libs/ardour/sndfilesource.cc:307
+#: libs/ardour/sndfilesource.cc:327
 msgid "SndFileSource: could not seek to frame %1 within %2 (%3)"
 msgstr ""
 
-#: libs/ardour/sndfilesource.cc:358
+#: libs/ardour/sndfilesource.cc:378
 #, fuzzy
 msgid "programming error: %1 %2"
 msgstr "������ ���������: "
 
-#: libs/ardour/sndfilesource.cc:458
+#: libs/ardour/sndfilesource.cc:487 libs/ardour/sndfilesource.cc:533
 msgid ""
 "cannot set broadcast info for audio file %1; Dropping broadcast info for "
 "this file"
 msgstr ""
 
-#: libs/ardour/sndfilesource.cc:500
+#: libs/ardour/sndfilesource.cc:544
 msgid "%1: cannot seek to %2"
 msgstr ""
 
@@ -1989,12 +1989,12 @@ msgstr ""
 msgid "no support for presets using chunks at this time"
 msgstr ""
 
-#: libs/ardour/coreaudio_source.cc:99
+#: libs/ardour/coreaudiosource.cc:97
 msgid ""
 "CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel "
 "number"
 msgstr ""
 
-#: libs/ardour/coreaudio_source.cc:164
+#: libs/ardour/coreaudiosource.cc:162
 msgid "CoreAudioSource: could not seek to frame %1 within %2 (%3)"
 msgstr ""
index c5c03d0a05948255066a4dccda538db478324228..7ec0d5a05ab2824827b29b965ca30ff16dbada79 100644 (file)
@@ -24,15 +24,15 @@ using namespace ARDOUR;
 using namespace std;
 
 Port::Port (jack_port_t *p) 
-       : port (p)
+       : _port (p)
 {
-       if (port == 0) {
+       if (_port == 0) {
                throw failed_constructor();
        }
        
-       _flags = JackPortFlags (jack_port_flags (port));
-       _type  = jack_port_type (port); 
-       _name = jack_port_name (port);
+       _flags = JackPortFlags (jack_port_flags (_port));
+       _type  = jack_port_type (_port); 
+       _name = jack_port_name (_port);
 
        reset ();
 }
@@ -42,9 +42,9 @@ Port::reset ()
 {
        reset_buffer ();
        
-       last_monitor = false;
-       silent = false;
-       metering = 0;
+       _last_monitor = false;
+       _silent = false;
+       _metering = 0;
        
        reset_meters ();
 }
@@ -54,7 +54,7 @@ Port::set_name (string str)
 {
        int ret;
 
-       if ((ret = jack_port_set_name (port, str.c_str())) == 0) {
+       if ((ret = jack_port_set_name (_port, str.c_str())) == 0) {
                _name = str;
        }
        
index 33fec5088f189ebe08693b2d0007426df9319dd3..1ab2f91cf0a8cbdd1e1435ece13fab8017ad6a57 100644 (file)
@@ -60,25 +60,25 @@ Redirect::~Redirect ()
 {
 }
 
-Redirect*
-Redirect::clone (const Redirect& other)
+boost::shared_ptr<Redirect>
+Redirect::clone (boost::shared_ptr<const Redirect> other)
 {
-       const Send *send;
-       const PortInsert *port_insert;
-       const PluginInsert *plugin_insert;
-
-       if ((send = dynamic_cast<const Send*>(&other)) != 0) {
-               return new Send (*send);
-       } else if ((port_insert = dynamic_cast<const PortInsert*>(&other)) != 0) {
-               return new PortInsert (*port_insert);
-       } else if ((plugin_insert = dynamic_cast<const PluginInsert*>(&other)) != 0) {
-               return new PluginInsert (*plugin_insert);
+       boost::shared_ptr<const Send> send;
+       boost::shared_ptr<const PortInsert> port_insert;
+       boost::shared_ptr<const PluginInsert> plugin_insert;
+
+       if ((send = boost::dynamic_pointer_cast<const Send>(other)) != 0) {
+               return boost::shared_ptr<Redirect> (new Send (*send));
+       } else if ((port_insert = boost::dynamic_pointer_cast<const PortInsert>(other)) != 0) {
+               return boost::shared_ptr<Redirect> (new PortInsert (*port_insert));
+       } else if ((plugin_insert = boost::dynamic_pointer_cast<const PluginInsert>(other)) != 0) {
+               return boost::shared_ptr<Redirect> (new PluginInsert (*plugin_insert));
        } else {
                fatal << _("programming error: unknown Redirect type in Redirect::Clone!\n")
                      << endmsg;
                /*NOTREACHED*/
        }
-       return 0;
+       return boost::shared_ptr<Redirect>();
 }
 
 void
@@ -231,9 +231,9 @@ Redirect::state (bool full_state)
                string path;
                string legal_name;
                
-               snprintf (buf, sizeof(buf), "%" PRIu64, id());
                path = _session.snap_name();
                path += "-redirect-";
+               id().print (buf);
                path += buf;
                path += ".automation";
                
index 8c27a3bebc699732449943c0cf7bf9d6a959a0b9..037c84432470ef068e5d79d71cd7be922ad472e2 100644 (file)
@@ -39,13 +39,13 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-Change Region::FadeChanged = ARDOUR::new_change ();
+Change Region::FadeChanged       = ARDOUR::new_change ();
 Change Region::SyncOffsetChanged = ARDOUR::new_change ();
-Change Region::MuteChanged = ARDOUR::new_change ();
-Change Region::OpacityChanged = ARDOUR::new_change ();
-Change Region::LockChanged = ARDOUR::new_change ();
-Change Region::LayerChanged = ARDOUR::new_change ();
-Change Region::HiddenChanged = ARDOUR::new_change ();
+Change Region::MuteChanged       = ARDOUR::new_change ();
+Change Region::OpacityChanged    = ARDOUR::new_change ();
+Change Region::LockChanged       = ARDOUR::new_change ();
+Change Region::LayerChanged      = ARDOUR::new_change ();
+Change Region::HiddenChanged     = ARDOUR::new_change ();
 
 sigc::signal<void,Region *> Region::CheckNewRegion;
 
@@ -53,7 +53,6 @@ Region::Region (jack_nframes_t start, jack_nframes_t length, const string& name,
 {
        /* basic Region constructor */
 
-       _id = ARDOUR::new_id();
        _flags = flags;
        _playlist = 0;
        _read_data_count = 0;
@@ -76,7 +75,6 @@ Region::Region (const Region& other, jack_nframes_t offset, jack_nframes_t lengt
 {
        /* create a new Region from part of an existing one */
 
-       _id = ARDOUR::new_id();
        _frozen = 0;
        pending_changed = Change (0);
        _playlist = 0;
@@ -102,7 +100,6 @@ Region::Region (const Region &other)
 {
        /* Pure copy constructor */
 
-       _id = ARDOUR::new_id();
        _frozen = 0;
        pending_changed = Change (0);
        _playlist = 0;
@@ -130,7 +127,6 @@ Region::Region (const Region &other)
 
 Region::Region (const XMLNode& node)
 {
-       _id = 0;
        _frozen = 0;
        pending_changed = Change (0);
        _playlist = 0;
@@ -844,7 +840,7 @@ Region::state (bool full_state)
        XMLNode *node = new XMLNode ("Region");
        char buf[64];
        
-       snprintf (buf, sizeof (buf), "%" PRIu64, _id);
+       _id.print (buf);
        node->add_property ("id", buf);
        node->add_property ("name", _name);
        snprintf (buf, sizeof (buf), "%u", _start);
@@ -886,7 +882,7 @@ Region::set_state (const XMLNode& node)
                return -1;
        }
 
-       sscanf (prop->value().c_str(), "%" PRIu64, &_id);
+       _id = prop->value();
 
        if ((prop = node.property ("name")) == 0) {
                error << _("Session: XMLNode describing a Region is incomplete (no name)") << endmsg;
@@ -994,3 +990,30 @@ Region::set_last_layer_op (uint64_t when)
 {
        _last_layer_op = when;
 }
+
+bool
+Region::overlap_equivalent (const Region& other) const
+{
+       return coverage (other.first_frame(), other.last_frame()) != OverlapNone;
+}
+
+bool
+Region::equivalent (const Region& other) const
+{
+       return _start == other._start &&
+               _position == other._position &&
+               _length == other._length;
+}
+
+bool
+Region::size_equivalent (const Region& other) const
+{
+       return _start == other._start &&
+               _length == other._length;
+}
+
+bool
+Region::region_list_equivalent (const Region& other) const
+{
+       return size_equivalent (other) && source_equivalent (other) && _name == other._name;
+}
index 3f51b2f140d78cfc3e810399ab6f35ea1f321033..b47981a47eff732c1025dd838eb33c368ec441c1 100644 (file)
 
 #include <cmath>
 #include <fstream>
+#include <cassert>
 
 #include <sigc++/bind.h>
 #include <pbd/xml++.h>
 
 #include <ardour/timestamps.h>
+#include <ardour/buffer.h>
 #include <ardour/audioengine.h>
 #include <ardour/route.h>
 #include <ardour/insert.h>
@@ -50,19 +52,19 @@ using namespace PBD;
 uint32_t Route::order_key_cnt = 0;
 
 
-Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg)
-       : IO (sess, name, input_min, input_max, output_min, output_max),
+Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg, DataType default_type)
+       : IO (sess, name, input_min, input_max, output_min, output_max, default_type),
          _flags (flg),
-         _midi_solo_control (*this, MIDIToggleControl::SoloControl, _session.midi_port()),
-         _midi_mute_control (*this, MIDIToggleControl::MuteControl, _session.midi_port())
+         _solo_control (*this, ToggleControllable::SoloControl),
+         _mute_control (*this, ToggleControllable::MuteControl)
 {
        init ();
 }
 
 Route::Route (Session& sess, const XMLNode& node)
        : IO (sess, "route"),
-         _midi_solo_control (*this, MIDIToggleControl::SoloControl, _session.midi_port()),
-         _midi_mute_control (*this, MIDIToggleControl::MuteControl, _session.midi_port())
+         _solo_control (*this, ToggleControllable::SoloControl),
+         _mute_control (*this, ToggleControllable::MuteControl)
 {
        init ();
        set_state (node);
@@ -105,8 +107,6 @@ Route::init ()
 
        input_changed.connect (mem_fun (this, &Route::input_change_handler));
        output_changed.connect (mem_fun (this, &Route::output_change_handler));
-
-       reset_midi_control (_session.midi_port(), _session.get_midi_control());
 }
 
 Route::~Route ()
@@ -712,11 +712,8 @@ Route::set_solo (bool yn, void *src)
 
        if (_soloed != yn) {
                _soloed = yn;
-                solo_changed (src); /* EMIT SIGNAL */
-
-                if (_session.get_midi_feedback()) {
-                        _midi_solo_control.send_feedback (_soloed);
-                }
+               solo_changed (src); /* EMIT SIGNAL */
+               _solo_control.Changed (); /* EMIT SIGNAL */
        }
 }
 
@@ -753,9 +750,7 @@ Route::set_mute (bool yn, void *src)
                _muted = yn;
                mute_changed (src); /* EMIT SIGNAL */
                
-               if (_session.get_midi_feedback()) {
-                       _midi_mute_control.send_feedback (_muted);
-               }
+               _mute_control.Changed (); /* EMIT SIGNAL */
                
                Glib::Mutex::Lock lm (declick_lock);
                desired_mute_gain = (yn?0.0f:1.0f);
@@ -763,7 +758,7 @@ Route::set_mute (bool yn, void *src)
 }
 
 int
-Route::add_redirect (Redirect *redirect, void *src, uint32_t* err_streams)
+Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t* err_streams)
 {
        uint32_t old_rmo = redirect_max_outs;
 
@@ -774,12 +769,12 @@ Route::add_redirect (Redirect *redirect, void *src, uint32_t* err_streams)
        {
                Glib::RWLock::WriterLock lm (redirect_lock);
 
-               PluginInsert* pi;
-               PortInsert* porti;
+               boost::shared_ptr<PluginInsert> pi;
+               boost::shared_ptr<PortInsert> porti;
 
                uint32_t potential_max_streams = 0;
 
-               if ((pi = dynamic_cast<PluginInsert*>(redirect)) != 0) {
+               if ((pi = boost::dynamic_pointer_cast<PluginInsert>(redirect)) != 0) {
                        pi->set_count (1);
 
                        if (pi->input_streams() == 0) {
@@ -788,8 +783,8 @@ Route::add_redirect (Redirect *redirect, void *src, uint32_t* err_streams)
                        }
 
                        potential_max_streams = max(pi->input_streams(), pi->output_streams());
-
-               } else if ((porti = dynamic_cast<PortInsert*>(redirect)) != 0) {
+                       
+               } else if ((porti = boost::dynamic_pointer_cast<PortInsert>(redirect)) != 0) {
 
                        /* force new port inserts to start out with an i/o configuration
                           that matches this route's i/o configuration.
@@ -854,9 +849,9 @@ Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_strea
 
                for (RedirectList::const_iterator i = others.begin(); i != others.end(); ++i) {
                        
-                       PluginInsert* pi;
+                       boost::shared_ptr<PluginInsert> pi;
                        
-                       if ((pi = dynamic_cast<PluginInsert*>(*i)) != 0) {
+                       if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
                                pi->set_count (1);
                                
                                uint32_t m = max(pi->input_streams(), pi->output_streams());
@@ -905,11 +900,6 @@ Route::clear_redirects (void *src)
 
        {
                Glib::RWLock::WriterLock lm (redirect_lock);
-
-               for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
-                       delete *i;
-               }
-
                _redirects.clear ();
        }
 
@@ -923,7 +913,7 @@ Route::clear_redirects (void *src)
 }
 
 int
-Route::remove_redirect (Redirect *redirect, void *src, uint32_t* err_streams)
+Route::remove_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t* err_streams)
 {
        uint32_t old_rmo = redirect_max_outs;
 
@@ -955,13 +945,13 @@ Route::remove_redirect (Redirect *redirect, void *src, uint32_t* err_streams)
                                   run.
                                */
 
-                               Send* send;
-                               PortInsert* port_insert;
+                               boost::shared_ptr<Send> send;
+                               boost::shared_ptr<PortInsert> port_insert;
                                
-                               if ((send = dynamic_cast<Send*> (*i)) != 0) {
+                               if ((send = boost::dynamic_pointer_cast<Send> (*i)) != 0) {
                                        send->disconnect_inputs (this);
                                        send->disconnect_outputs (this);
-                               } else if ((port_insert = dynamic_cast<PortInsert*> (*i)) != 0) {
+                               } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (*i)) != 0) {
                                        port_insert->disconnect_inputs (this);
                                        port_insert->disconnect_outputs (this);
                                }
@@ -990,9 +980,9 @@ Route::remove_redirect (Redirect *redirect, void *src, uint32_t* err_streams)
                bool foo = false;
 
                for (i = _redirects.begin(); i != _redirects.end(); ++i) {
-                       PluginInsert* pi;
-
-                       if ((pi = dynamic_cast<PluginInsert*>(*i)) != 0) {
+                       boost::shared_ptr<PluginInsert> pi;
+                       
+                       if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
                                if (pi->is_generator()) {
                                        foo = true;
                                }
@@ -1039,7 +1029,7 @@ Route::_reset_plugin_counts (uint32_t* err_streams)
        
        for (r = _redirects.begin(); r != _redirects.end(); ++r) {
 
-               Insert *insert;
+               boost::shared_ptr<Insert> insert;
 
                /* do this here in case we bomb out before we get to the end of
                   this function.
@@ -1047,22 +1037,22 @@ Route::_reset_plugin_counts (uint32_t* err_streams)
 
                redirect_max_outs = max ((*r)->output_streams (), redirect_max_outs);
 
-               if ((insert = dynamic_cast<Insert*>(*r)) != 0) {
+               if ((insert = boost::dynamic_pointer_cast<Insert>(*r)) != 0) {
                        ++i_cnt;
-                       insert_map[insert->placement()].push_back (InsertCount (*insert));
+                       insert_map[insert->placement()].push_back (InsertCount (insert));
 
                        /* reset plugin counts back to one for now so
                           that we have a predictable, controlled
                           state to try to configure.
                        */
 
-                       PluginInsert* pi;
+                       boost::shared_ptr<PluginInsert> pi;
                
-                       if ((pi = dynamic_cast<PluginInsert*>(insert)) != 0) {
+                       if ((pi = boost::dynamic_pointer_cast<PluginInsert>(insert)) != 0) {
                                pi->set_count (1);
                        }
 
-               } else if (dynamic_cast<Send*> (*r) != 0) {
+               } else if (boost::dynamic_pointer_cast<Send> (*r) != 0) {
                        ++s_cnt;
                }
        }
@@ -1089,7 +1079,7 @@ Route::_reset_plugin_counts (uint32_t* err_streams)
 
        if (!insert_map[PreFader].empty()) {
                InsertCount& ic (insert_map[PreFader].back());
-               initial_streams = ic.insert.compute_output_streams (ic.cnt);
+               initial_streams = ic.insert->compute_output_streams (ic.cnt);
        } else {
                initial_streams = n_inputs ();
        }
@@ -1113,9 +1103,9 @@ Route::_reset_plugin_counts (uint32_t* err_streams)
        RedirectList::iterator prev = _redirects.end();
 
        for (r = _redirects.begin(); r != _redirects.end(); prev = r, ++r) {
-               Send* s;
+               boost::shared_ptr<Send> s;
 
-               if ((s = dynamic_cast<Send*> (*r)) != 0) {
+               if ((s = boost::dynamic_pointer_cast<Send> (*r)) != 0) {
                        if (r == _redirects.begin()) {
                                s->expect_inputs (n_inputs());
                        } else {
@@ -1138,11 +1128,11 @@ Route::apply_some_plugin_counts (list<InsertCount>& iclist)
 
        for (i = iclist.begin(); i != iclist.end(); ++i) {
                
-               if ((*i).insert.configure_io ((*i).cnt, (*i).in, (*i).out)) {
+               if ((*i).insert->configure_io ((*i).cnt, (*i).in, (*i).out)) {
                        return -1;
                }
                /* make sure that however many we have, they are all active */
-               (*i).insert.activate ();
+               (*i).insert->activate ();
        }
 
        return 0;
@@ -1155,7 +1145,7 @@ Route::check_some_plugin_counts (list<InsertCount>& iclist, int32_t required_inp
        
        for (i = iclist.begin(); i != iclist.end(); ++i) {
 
-               if (((*i).cnt = (*i).insert.can_support_input_configuration (required_inputs)) < 0) {
+               if (((*i).cnt = (*i).insert->can_support_input_configuration (required_inputs)) < 0) {
                        if (err_streams) {
                                *err_streams = required_inputs;
                        }
@@ -1163,7 +1153,7 @@ Route::check_some_plugin_counts (list<InsertCount>& iclist, int32_t required_inp
                }
                
                (*i).in = required_inputs;
-               (*i).out = (*i).insert.compute_output_streams ((*i).cnt);
+               (*i).out = (*i).insert->compute_output_streams ((*i).cnt);
 
                required_inputs = (*i).out;
        }
@@ -1207,7 +1197,7 @@ Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_st
                
                for (RedirectList::const_iterator i = other._redirects.begin(); i != other._redirects.end(); ++i) {
                        if ((*i)->placement() == placement) {
-                               _redirects.push_back (Redirect::clone (**i));
+                               _redirects.push_back (Redirect::clone (*i));
                        }
                }
 
@@ -1225,7 +1215,6 @@ Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_st
                                ++tmp;
 
                                if ((*i)->placement() == placement) {
-                                       delete *i;
                                        _redirects.erase (i);
                                }
                                
@@ -1244,10 +1233,7 @@ Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_st
                } else {
                        
                        /* SUCCESSFUL COPY ATTEMPT: delete the redirects we removed pre-copy */
-
-                       for (RedirectList::iterator i = to_be_deleted.begin(); i != to_be_deleted.end(); ++i) {
-                               delete *i;
-                       }
+                       to_be_deleted.clear ();
                }
        }
 
@@ -1290,7 +1276,7 @@ Route::all_redirects_active (bool state)
 }
 
 struct RedirectSorter {
-    bool operator() (const Redirect *a, const Redirect *b) {
+    bool operator() (boost::shared_ptr<const Redirect> a, boost::shared_ptr<const Redirect> b) {
            return a->sort_key() < b->sort_key();
     }
 };
@@ -1346,6 +1332,9 @@ Route::state(bool full_state)
                snprintf (buf, sizeof (buf), "0x%x", _flags);
                node->add_property("flags", buf);
        }
+       
+       node->add_property("default-type", _default_type.to_string());
+
        node->add_property("active", _active?"yes":"no");
        node->add_property("muted", _muted?"yes":"no");
        node->add_property("soloed", _soloed?"yes":"no");
@@ -1362,26 +1351,6 @@ Route::state(bool full_state)
                node->add_property("mix-group", _mix_group->name());
        }
 
-       /* MIDI control */
-
-       MIDI::channel_t chn;
-       MIDI::eventType ev;
-       MIDI::byte      additional;
-       XMLNode*        midi_node = 0;
-       XMLNode*        child;
-
-       midi_node = node->add_child ("MIDI");
-       
-       if (_midi_mute_control.get_control_info (chn, ev, additional)) {
-               child = midi_node->add_child ("mute");
-               set_midi_node_info (child, ev, chn, additional);
-       }
-       if (_midi_solo_control.get_control_info (chn, ev, additional)) {
-               child = midi_node->add_child ("solo");
-               set_midi_node_info (child, ev, chn, additional);
-       }
-
-       
        string order_string;
        OrderKeys::iterator x = order_keys.begin(); 
 
@@ -1469,13 +1438,13 @@ void
 Route::add_redirect_from_xml (const XMLNode& node)
 {
        const XMLProperty *prop;
-       Insert *insert = 0;
-       Send *send = 0;
 
        if (node.name() == "Send") {
                
+
                try {
-                       send = new Send (_session, node);
+                       boost::shared_ptr<Send> send (new Send (_session, node));
+                       add_redirect (send, this);
                } 
                
                catch (failed_constructor &err) {
@@ -1483,21 +1452,21 @@ Route::add_redirect_from_xml (const XMLNode& node)
                        return;
                }
                
-               add_redirect (send, this);
-               
        } else if (node.name() == "Insert") {
                
                try {
                        if ((prop = node.property ("type")) != 0) {
 
+                               boost::shared_ptr<Insert> insert;
+
                                if (prop->value() == "ladspa" || prop->value() == "Ladspa" || prop->value() == "vst") {
 
-                                       insert = new PluginInsert(_session, node);
+                                       insert.reset (new PluginInsert(_session, node));
                                        
                                } else if (prop->value() == "port") {
 
 
-                                       insert = new PortInsert (_session, node);
+                                       insert.reset (new PortInsert (_session, node));
 
                                } else {
 
@@ -1526,8 +1495,6 @@ Route::set_state (const XMLNode& node)
        XMLNode *child;
        XMLPropertyList plist;
        const XMLProperty *prop;
-       XMLNodeList midi_kids;
-
 
        if (node.name() != "Route"){
                error << string_compose(_("Bad node sent to Route::set_state() [%1]"), node.name()) << endmsg;
@@ -1541,6 +1508,11 @@ Route::set_state (const XMLNode& node)
        } else {
                _flags = Flag (0);
        }
+       
+       if ((prop = node.property ("default-type")) != 0) {
+               _default_type = DataType(prop->value());
+               assert(_default_type != DataType::NIL);
+       }
 
        if ((prop = node.property ("phase-invert")) != 0) {
                set_phase_invert(prop->value()=="yes"?true:false, this);
@@ -1716,45 +1688,6 @@ Route::set_state (const XMLNode& node)
                }
        }
 
-       midi_kids = node.children ("MIDI");
-       
-       for (niter = midi_kids.begin(); niter != midi_kids.end(); ++niter) {
-       
-               XMLNodeList kids;
-               XMLNodeConstIterator miter;
-               XMLNode*    child;
-
-               kids = (*niter)->children ();
-
-               for (miter = kids.begin(); miter != kids.end(); ++miter) {
-
-                       child =* miter;
-
-                       MIDI::eventType ev = MIDI::on; /* initialize to keep gcc happy */
-                       MIDI::byte additional = 0;  /* ditto */
-                       MIDI::channel_t chn = 0;    /* ditto */
-                       
-                       if (child->name() == "mute") {
-                       
-                               if (get_midi_node_info (child, ev, chn, additional)) {
-                                       _midi_mute_control.set_control_type (chn, ev, additional);
-                               } else {
-                                       error << string_compose(_("MIDI mute control specification for %1 is incomplete, so it has been ignored"), _name) << endmsg;
-                               }
-                       }
-                       else if (child->name() == "solo") {
-                       
-                               if (get_midi_node_info (child, ev, chn, additional)) {
-                                       _midi_solo_control.set_control_type (chn, ev, additional);
-                               } else {
-                                       error << string_compose(_("MIDI mute control specification for %1 is incomplete, so it has been ignored"), _name) << endmsg;
-                               }
-                       }
-
-               }
-       }
-
-       
        return 0;
 }
 
@@ -1783,8 +1716,8 @@ Route::silence (jack_nframes_t nframes, jack_nframes_t offset)
                        
                        if (lm.locked()) {
                                for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
-                                       PluginInsert* pi;
-                                       if (!_active && (pi = dynamic_cast<PluginInsert*> (*i)) != 0) {
+                                       boost::shared_ptr<PluginInsert> pi;
+                                       if (!_active && (pi = boost::dynamic_pointer_cast<PluginInsert> (*i)) != 0) {
                                                // skip plugins, they don't need anything when we're not active
                                                continue;
                                        }
@@ -1895,18 +1828,17 @@ Route::set_comment (string cmt, void *src)
 }
 
 bool
-Route::feeds (Route *o)
+Route::feeds (boost::shared_ptr<Route> other)
 {
        uint32_t i, j;
 
-       IO& other = *o;
        IO& self = *this;
        uint32_t no = self.n_outputs();
-       uint32_t ni = other.n_inputs ();
+       uint32_t ni = other->n_inputs ();
 
        for (i = 0; i < no; ++i) {
                for (j = 0; j < ni; ++j) {
-                       if (self.output(i)->connected_to (other.input(j)->name())) {
+                       if (self.output(i)->connected_to (other->input(j)->name())) {
                                return true;
                        }
                }
@@ -1920,7 +1852,7 @@ Route::feeds (Route *o)
 
                for (i = 0; i < no; ++i) {
                        for (j = 0; j < ni; ++j) {
-                               if ((*r)->output(i)->connected_to (other.input (j)->name())) {
+                               if ((*r)->output(i)->connected_to (other->input (j)->name())) {
                                        return true;
                                }
                        }
@@ -1935,7 +1867,7 @@ Route::feeds (Route *o)
                
                for (i = 0; i < no; ++i) {
                        for (j = 0; j < ni; ++j) {
-                               if (_control_outs->output(i)->connected_to (other.input (j)->name())) {
+                               if (_control_outs->output(i)->connected_to (other->input (j)->name())) {
                                        return true;
                                }
                        }
@@ -2186,10 +2118,10 @@ Route::toggle_monitor_input ()
 bool
 Route::has_external_redirects () const
 {
-       const PortInsert* pi;
+       boost::shared_ptr<const PortInsert> pi;
        
        for (RedirectList::const_iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
-               if ((pi = dynamic_cast<const PortInsert*>(*i)) != 0) {
+               if ((pi = boost::dynamic_pointer_cast<const PortInsert>(*i)) != 0) {
 
                        uint32_t no = pi->n_outputs();
 
@@ -2210,67 +2142,6 @@ Route::has_external_redirects () const
        return false;
 }
 
-void
-Route::reset_midi_control (MIDI::Port* port, bool on)
-{
-       MIDI::channel_t chn;
-       MIDI::eventType ev;
-       MIDI::byte extra;
-
-       for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
-                       (*i)->reset_midi_control (port, on);
-       }
-
-       IO::reset_midi_control (port, on);
-       
-       _midi_solo_control.get_control_info (chn, ev, extra);
-       if (!on) {
-               chn = -1;
-       }
-       _midi_solo_control.midi_rebind (port, chn);
-       
-       _midi_mute_control.get_control_info (chn, ev, extra);
-       if (!on) {
-               chn = -1;
-       }
-       _midi_mute_control.midi_rebind (port, chn);
-}
-
-void
-Route::send_all_midi_feedback ()
-{
-       if (_session.get_midi_feedback()) {
-
-               {
-                       Glib::RWLock::ReaderLock lm (redirect_lock);
-                       for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
-                               (*i)->send_all_midi_feedback ();
-                       }
-               }
-
-               IO::send_all_midi_feedback();
-
-               _midi_solo_control.send_feedback (_soloed);
-               _midi_mute_control.send_feedback (_muted);
-       }
-}
-
-MIDI::byte*
-Route::write_midi_feedback (MIDI::byte* buf, int32_t& bufsize)
-{
-       buf = _midi_solo_control.write_feedback (buf, bufsize, _soloed);
-       buf = _midi_mute_control.write_feedback (buf, bufsize, _muted);
-
-       {
-               Glib::RWLock::ReaderLock lm (redirect_lock);
-               for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
-                       buf = (*i)->write_midi_feedback (buf, bufsize);
-               }
-       }
-
-       return IO::write_midi_feedback (buf, bufsize);
-}
-
 void
 Route::flush_redirects ()
 {
@@ -2341,106 +2212,46 @@ Route::automation_snapshot (jack_nframes_t now)
        }
 }
 
-Route::MIDIToggleControl::MIDIToggleControl (Route& s, ToggleType tp, MIDI::Port* port)
-       : MIDI::Controllable (port, true), route (s), type(tp), setting(false)
+Route::ToggleControllable::ToggleControllable (Route& s, ToggleType tp)
+       : route (s), type(tp)
 {
-       last_written = false; /* XXX need a good out-of-bound-value */
+       
 }
 
 void
-Route::MIDIToggleControl::set_value (float val)
+Route::ToggleControllable::set_value (float val)
 {
-       MIDI::eventType et;
-       MIDI::channel_t chn;
-       MIDI::byte additional;
-
-       get_control_info (chn, et, additional);
-
-       setting = true;
-
-#ifdef HOLD_TOGGLE_VALUES
-       if (et == MIDI::off || et == MIDI::on) {
-
-               /* literal toggle */
-
-               switch (type) {
-               case MuteControl:
-                       route.set_mute (!route.muted(), this);
-                       break;
-               case SoloControl:
-                       route.set_solo (!route.soloed(), this);
-                       break;
-               default:
-                       break;
-               }
-
-       } else {
-#endif
-
-               /* map full control range to a boolean */
-
-               bool bval = ((val >= 0.5f) ? true: false);
-               
-               switch (type) {
-               case MuteControl:
-                       route.set_mute (bval, this);
-                       break;
-               case SoloControl:
-                       route.set_solo (bval, this);
-                       break;
-               default:
-                       break;
-               }
-
-#ifdef HOLD_TOGGLE_VALUES
+       bool bval = ((val >= 0.5f) ? true: false);
+       
+       switch (type) {
+       case MuteControl:
+               route.set_mute (bval, this);
+               break;
+       case SoloControl:
+               route.set_solo (bval, this);
+               break;
+       default:
+               break;
        }
-#endif
-
-       setting = false;
 }
 
-void
-Route::MIDIToggleControl::send_feedback (bool value)
+float
+Route::ToggleControllable::get_value (void) const
 {
-
-       if (!setting && get_midi_feedback()) {
-               MIDI::byte val = (MIDI::byte) (value ? 127: 0);
-               MIDI::channel_t ch = 0;
-               MIDI::eventType ev = MIDI::none;
-               MIDI::byte additional = 0;
-               MIDI::EventTwoBytes data;
-           
-               if (get_control_info (ch, ev, additional)) {
-                       data.controller_number = additional;
-                       data.value = val;
-                       last_written = value;
-                       
-                       route._session.send_midi_message (get_port(), ev, ch, data);
-               }
-       }
+       float val = 0.0f;
        
-}
-
-MIDI::byte*
-Route::MIDIToggleControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool val, bool force)
-{
-       if (get_midi_feedback() && bufsize > 2) {
-               MIDI::channel_t ch = 0;
-               MIDI::eventType ev = MIDI::none;
-               MIDI::byte additional = 0;
-
-               if (get_control_info (ch, ev, additional)) {
-                       if (val != last_written || force) {
-                               *buf++ = (0xF0 & ev) | (0xF & ch);
-                               *buf++ = additional; /* controller number */
-                               *buf++ = (MIDI::byte) (val ? 127 : 0);
-                               bufsize -= 3;
-                               last_written = val;
-                       }
-               }
+       switch (type) {
+       case MuteControl:
+               val = route.muted() ? 1.0f : 0.0f;
+               break;
+       case SoloControl:
+               val = route.soloed() ? 1.0f : 0.0f;
+               break;
+       default:
+               break;
        }
 
-       return buf;
+       return val;
 }
 
 void 
@@ -2479,8 +2290,8 @@ Route::protect_automation ()
        }
        
        for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
-               PluginInsert* pi;
-               if ((pi = dynamic_cast<PluginInsert*> (*i)) != 0) {
+               boost::shared_ptr<PluginInsert> pi;
+               if ((pi = boost::dynamic_pointer_cast<PluginInsert> (*i)) != 0) {
                        pi->protect_automation ();
                }
        }
index 864e6178d2fc9f9c4e123ae530d0b1752f0bd1d5..806ec3b17f09843cab6a7f3b441efd2874d6e6f5 100644 (file)
@@ -64,6 +64,7 @@
 #include <ardour/crossfade.h>
 #include <ardour/playlist.h>
 #include <ardour/click.h>
+#include <ardour/data_type.h>
 
 #ifdef HAVE_LIBLO
 #include <ardour/osc.h>
@@ -74,6 +75,7 @@
 using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
+using boost::shared_ptr;
 
 const char* Session::_template_suffix = X_(".template");
 const char* Session::_statefile_suffix = X_(".ardour");
@@ -90,6 +92,8 @@ Session::mix_buffers_no_gain_t                Session::mix_buffers_no_gain    = 0;
 
 sigc::signal<int> Session::AskAboutPendingState;
 sigc::signal<void> Session::SMPTEOffsetChanged;
+sigc::signal<void> Session::SendFeedback;
+
 
 int
 Session::find_session (string str, string& path, string& snapshot, bool& isnew)
@@ -252,6 +256,9 @@ Session::Session (AudioEngine &eng,
          _midi_port (default_midi_port),
          pending_events (2048),
          midi_requests (128), // the size of this should match the midi request pool size
+         routes (new RouteList),
+         auditioner ((Auditioner*) 0),
+         _click_io ((IO*) 0),
          main_outs (0)
 {
        bool new_session;
@@ -299,6 +306,7 @@ Session::Session (AudioEngine &eng,
          _midi_port (default_midi_port),
          pending_events (2048),
          midi_requests (16),
+         routes (new RouteList),
          main_outs (0)
 
 {
@@ -316,15 +324,13 @@ Session::Session (AudioEngine &eng,
        }
 
        if (control_out_channels) {
-               Route* r;
-               r = new Route (*this, _("monitor"), -1, control_out_channels, -1, control_out_channels, Route::ControlOut);
+               shared_ptr<Route> r (new Route (*this, _("monitor"), -1, control_out_channels, -1, control_out_channels, Route::ControlOut));
                add_route (r);
                _control_out = r;
        }
 
        if (master_out_channels) {
-               Route* r;
-               r = new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut);
+               shared_ptr<Route> r (new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut));
                add_route (r);
                _master_out = r;
        } else {
@@ -376,15 +382,6 @@ Session::~Session ()
 
        clear_clicks ();
 
-       if (_click_io) {
-               delete _click_io;
-       }
-
-
-       if (auditioner) {
-               delete auditioner;
-       }
-
        for (vector<Sample*>::iterator i = _passthru_buffers.begin(); i != _passthru_buffers.end(); ++i) {
                free(*i);
        }
@@ -401,6 +398,8 @@ Session::~Session ()
                delete [] (i->second);
        }
        
+       AudioDiskstream::free_working_buffers();
+       
 #undef TRACK_DESTRUCTION
 #ifdef TRACK_DESTRUCTION
        cerr << "delete named selections\n";
@@ -438,27 +437,16 @@ Session::~Session ()
                tmp =i;
                ++tmp;
 
-               delete (*i).second;
+               delete i->second;
 
                i = tmp;
        }
        
 #ifdef TRACK_DESTRUCTION
-       cerr << "delete routes\n";
-#endif /* TRACK_DESTRUCTION */
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ) {
-               RouteList::iterator tmp;
-               tmp = i;
-               ++tmp;
-               delete *i;
-               i = tmp;
-       }
-
-#ifdef TRACK_DESTRUCTION
-       cerr << "delete audio_diskstreams\n";
+       cerr << "delete diskstreams\n";
 #endif /* TRACK_DESTRUCTION */
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ) {
-               AudioDiskstreamList::iterator tmp;
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ) {
+               DiskstreamList::iterator tmp;
 
                tmp = i;
                ++tmp;
@@ -477,7 +465,7 @@ Session::~Session ()
                tmp = i;
                ++tmp;
 
-               delete (*i).second;
+               delete i->second;
 
                i = tmp;
        }
@@ -544,7 +532,7 @@ Session::~Session ()
 }
 
 void
-Session::set_worst_io_latencies (bool take_lock)
+Session::set_worst_io_latencies ()
 {
        _worst_output_latency = 0;
        _worst_input_latency = 0;
@@ -553,18 +541,12 @@ Session::set_worst_io_latencies (bool take_lock)
                return;
        }
 
-       if (take_lock) {
-               route_lock.reader_lock ();
-       }
+       boost::shared_ptr<RouteList> r = routes.reader ();
        
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                _worst_output_latency = max (_worst_output_latency, (*i)->output_latency());
                _worst_input_latency = max (_worst_input_latency, (*i)->input_latency());
        }
-
-       if (take_lock) {
-               route_lock.reader_unlock ();
-       }
 }
 
 void
@@ -581,7 +563,7 @@ Session::when_engine_running ()
 
        /* every time we reconnect, recompute worst case output latencies */
 
-       _engine.Running.connect (sigc::bind (mem_fun (*this, &Session::set_worst_io_latencies), true));
+       _engine.Running.connect (mem_fun (*this, &Session::set_worst_io_latencies));
 
        if (synced_to_jack()) {
                _engine.transport_stop ();
@@ -596,7 +578,7 @@ Session::when_engine_running ()
        try {
                XMLNode* child = 0;
                
-               _click_io = new ClickIO (*this, "click", 0, 0, -1, -1);
+               _click_io.reset (new ClickIO (*this, "click", 0, 0, -1, -1));
 
                if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
 
@@ -632,7 +614,7 @@ Session::when_engine_running ()
                error << _("cannot setup Click I/O") << endmsg;
        }
 
-       set_worst_io_latencies (true);
+       set_worst_io_latencies ();
 
        if (_clicking) {
                 ControlChanged (Clicking); /* EMIT SIGNAL */
@@ -647,7 +629,7 @@ Session::when_engine_running ()
                */
 
                try {
-                       auditioner = new Auditioner (*this);
+                       auditioner.reset (new Auditioner (*this));
                }
 
                catch (failed_constructor& err) {
@@ -881,7 +863,7 @@ Session::playlist_length_changed (Playlist* pl)
 }
 
 void
-Session::diskstream_playlist_changed (AudioDiskstream* dstream)
+Session::diskstream_playlist_changed (Diskstream* dstream)
 {
        Playlist *playlist;
 
@@ -961,7 +943,7 @@ Session::set_auto_input (bool yn)
                           The rarity and short potential lock duration makes this "OK"
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
                                        (*i)->monitor_input (!auto_input);   
@@ -979,7 +961,7 @@ Session::reset_input_monitor_state ()
 {
        if (transport_rolling()) {
                Glib::RWLock::ReaderLock dsm (diskstream_lock);
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if ((*i)->record_enabled ()) {
                                //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
                                (*i)->monitor_input (Config->get_use_hardware_monitoring() && !auto_input);
@@ -987,7 +969,7 @@ Session::reset_input_monitor_state ()
                }
        } else {
                Glib::RWLock::ReaderLock dsm (diskstream_lock);
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if ((*i)->record_enabled ()) {
                                //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
                                (*i)->monitor_input (Config->get_use_hardware_monitoring());
@@ -1068,7 +1050,7 @@ Session::auto_loop_changed (Location* location)
                }
                else if (seamless_loop && !loop_changing) {
                        
-                       // schedule a locate-roll to refill the audio_diskstreams at the
+                       // schedule a locate-roll to refill the diskstreams at the
                        // previous loop end
                        loop_changing = true;
 
@@ -1265,7 +1247,7 @@ Session::enable_record ()
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
                        
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        (*i)->monitor_input (true);   
                                }
@@ -1300,7 +1282,7 @@ Session::disable_record (bool rt_context, bool force)
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
                        
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        (*i)->monitor_input (false);   
                                }
@@ -1327,7 +1309,7 @@ Session::step_back_from_record ()
                */
                Glib::RWLock::ReaderLock dsm (diskstream_lock);
                
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if (auto_input && (*i)->record_enabled ()) {
                                //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
                                (*i)->monitor_input (false);   
@@ -1450,7 +1432,6 @@ Session::set_block_size (jack_nframes_t nframes)
        */
 
        { 
-               Glib::RWLock::ReaderLock lm (route_lock);
                Glib::RWLock::ReaderLock dsm (diskstream_lock);
                vector<Sample*>::iterator i;
                uint32_t np;
@@ -1492,15 +1473,17 @@ Session::set_block_size (jack_nframes_t nframes)
 
                allocate_pan_automation_buffers (nframes, _npan_buffers, true);
 
-               for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+               boost::shared_ptr<RouteList> r = routes.reader ();
+
+               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                        (*i)->set_block_size (nframes);
                }
                
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        (*i)->set_block_size (nframes);
                }
 
-               set_worst_io_latencies (false);
+               set_worst_io_latencies ();
        }
 }
 
@@ -1542,7 +1525,7 @@ Session::set_default_fade (float steepness, float fade_msecs)
 }
 
 struct RouteSorter {
-    bool operator() (Route* r1, Route* r2) {
+    bool operator() (boost::shared_ptr<Route> r1, boost::shared_ptr<Route> r2) {
            if (r1->fed_by.find (r2) != r1->fed_by.end()) {
                    return false;
            } else if (r2->fed_by.find (r1) != r2->fed_by.end()) {
@@ -1564,9 +1547,9 @@ struct RouteSorter {
 };
 
 static void
-trace_terminal (Route* r1, Route* rbase)
+trace_terminal (shared_ptr<Route> r1, shared_ptr<Route> rbase)
 {
-       Route* r2;
+       shared_ptr<Route> r2;
 
        if ((r1->fed_by.find (rbase) != r1->fed_by.end()) && (rbase->fed_by.find (r1) != rbase->fed_by.end())) {
                info << string_compose(_("feedback loop setup between %1 and %2"), r1->name(), rbase->name()) << endmsg;
@@ -1575,13 +1558,13 @@ trace_terminal (Route* r1, Route* rbase)
 
        /* make a copy of the existing list of routes that feed r1 */
 
-       set<Route *> existing = r1->fed_by;
+       set<shared_ptr<Route> > existing = r1->fed_by;
 
        /* for each route that feeds r1, recurse, marking it as feeding
           rbase as well.
        */
 
-       for (set<Route *>::iterator i = existing.begin(); i != existing.end(); ++i) {
+       for (set<shared_ptr<Route> >::iterator i = existing.begin(); i != existing.end(); ++i) {
                r2 =* i;
 
                /* r2 is a route that feeds r1 which somehow feeds base. mark
@@ -1611,7 +1594,7 @@ trace_terminal (Route* r1, Route* rbase)
 }
 
 void
-Session::resort_routes (void* src)
+Session::resort_routes ()
 {
        /* don't do anything here with signals emitted
           by Routes while we are being destroyed.
@@ -1621,54 +1604,64 @@ Session::resort_routes (void* src)
                return;
        }
 
-       /* Caller MUST hold the route_lock */
 
-       RouteList::iterator i, j;
+       {
 
-       for (i = routes.begin(); i != routes.end(); ++i) {
+               RCUWriter<RouteList> writer (routes);
+               shared_ptr<RouteList> r = writer.get_copy ();
+               resort_routes_using (r);
+               /* writer goes out of scope and forces update */
+       }
 
+}
+void
+Session::resort_routes_using (shared_ptr<RouteList> r)
+{
+       RouteList::iterator i, j;
+       
+       for (i = r->begin(); i != r->end(); ++i) {
+               
                (*i)->fed_by.clear ();
                
-               for (j = routes.begin(); j != routes.end(); ++j) {
-
+               for (j = r->begin(); j != r->end(); ++j) {
+                       
                        /* although routes can feed themselves, it will
                           cause an endless recursive descent if we
                           detect it. so don't bother checking for
                           self-feeding.
                        */
-
+                       
                        if (*j == *i) {
                                continue;
                        }
-
+                       
                        if ((*j)->feeds (*i)) {
                                (*i)->fed_by.insert (*j);
                        } 
                }
        }
        
-       for (i = routes.begin(); i != routes.end(); ++i) {
+       for (i = r->begin(); i != r->end(); ++i) {
                trace_terminal (*i, *i);
        }
-
+       
        RouteSorter cmp;
-       routes.sort (cmp);
-
+       r->sort (cmp);
+       
 #if 0
        cerr << "finished route resort\n";
        
-       for (i = routes.begin(); i != routes.end(); ++i) {
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                cerr << " " << (*i)->name() << " signal order = " << (*i)->order_key ("signal") << endl;
        }
        cerr << endl;
 #endif
-
+       
 }
 
-AudioTrack*
+shared_ptr<AudioTrack>
 Session::new_audio_track (int input_channels, int output_channels, TrackMode mode)
 {
-       AudioTrack *track;
        char track_name[32];
        uint32_t n = 0;
        uint32_t channels_used = 0;
@@ -1679,9 +1672,10 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
        /* count existing audio tracks */
 
        {
-               Glib::RWLock::ReaderLock lm (route_lock);
-               for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
-                       if (dynamic_cast<AudioTrack*>(*i) != 0) {
+               shared_ptr<RouteList> r = routes.reader ();
+
+               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+                       if (dynamic_cast<AudioTrack*>((*i).get()) != 0) {
                                if (!(*i)->hidden()) {
                                        n++;
                                        channels_used += (*i)->n_inputs();
@@ -1718,7 +1712,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
        }
 
        try {
-               track = new AudioTrack (*this, track_name, Route::Flag (0), mode);
+               shared_ptr<AudioTrack> track (new AudioTrack (*this, track_name, Route::Flag (0), mode));
 
                if (track->ensure_io (input_channels, output_channels, false, this)) {
                        error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
@@ -1769,25 +1763,23 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
                        track->set_control_outs (cports);
                }
 
-               track->diskstream_changed.connect (mem_fun (this, &Session::resort_routes));
+               track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
 
                add_route (track);
 
                track->set_remote_control_id (ntracks());
+               return track;
        }
 
        catch (failed_constructor &err) {
                error << _("Session: could not create new audio track.") << endmsg;
-               return 0;
+               return shared_ptr<AudioTrack> ((AudioTrack*) 0);
        }
-
-       return track;
 }
 
-Route*
+shared_ptr<Route>
 Session::new_audio_route (int input_channels, int output_channels)
 {
-       Route *bus;
        char bus_name[32];
        uint32_t n = 0;
        string port;
@@ -1795,9 +1787,10 @@ Session::new_audio_route (int input_channels, int output_channels)
        /* count existing audio busses */
 
        {
-               Glib::RWLock::ReaderLock lm (route_lock);
-               for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
-                       if (dynamic_cast<AudioTrack*>(*i) == 0) {
+               shared_ptr<RouteList> r = routes.reader ();
+
+               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+                       if (dynamic_cast<AudioTrack*>((*i).get()) == 0) {
                                if (!(*i)->hidden()) {
                                        n++;
                                }
@@ -1815,7 +1808,7 @@ Session::new_audio_route (int input_channels, int output_channels)
        } while (n < (UINT_MAX-1));
 
        try {
-               bus = new Route (*this, bus_name, -1, -1, -1, -1);
+               shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), DataType::AUDIO));
 
                if (bus->ensure_io (input_channels, output_channels, false, this)) {
                        error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
@@ -1864,23 +1857,23 @@ Session::new_audio_route (int input_channels, int output_channels)
                }
                
                add_route (bus);
+               return bus;
        }
 
        catch (failed_constructor &err) {
-               error << _("Session: could not create new route.") << endmsg;
-               return 0;
+               error << _("Session: could not create new audio route.") << endmsg;
+               return shared_ptr<Route> ((Route*) 0);
        }
-
-       return bus;
 }
 
 void
-Session::add_route (Route* route)
+Session::add_route (shared_ptr<Route> route)
 {
        { 
-               Glib::RWLock::WriterLock lm (route_lock);
-               routes.push_front (route);
-               resort_routes(0);
+               RCUWriter<RouteList> writer (routes);
+               shared_ptr<RouteList> r = writer.get_copy ();
+               r->push_front (route);
+               resort_routes_using (r);
        }
 
        route->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), route));
@@ -1903,14 +1896,14 @@ Session::add_route (Route* route)
 }
 
 void
-Session::add_diskstream (AudioDiskstream* dstream)
+Session::add_diskstream (Diskstream* dstream)
 {
        /* need to do this in case we're rolling at the time, to prevent false underruns */
-       dstream->do_refill(0, 0, 0);
+       dstream->do_refill_with_alloc();
        
        { 
                Glib::RWLock::WriterLock lm (diskstream_lock);
-               audio_diskstreams.push_back (dstream);
+               diskstreams.push_back (dstream);
        }
 
        /* take a reference to the diskstream, preventing it from
@@ -1930,52 +1923,56 @@ Session::add_diskstream (AudioDiskstream* dstream)
        set_dirty();
        save_state (_current_snapshot_name);
 
-       AudioDiskstreamAdded (dstream); /* EMIT SIGNAL */
+       DiskstreamAdded (dstream); /* EMIT SIGNAL */
 }
 
 void
-Session::remove_route (Route& route)
+Session::remove_route (shared_ptr<Route> route)
 {
        {       
-               Glib::RWLock::WriterLock lm (route_lock);
-               routes.remove (&route);
+               RCUWriter<RouteList> writer (routes);
+               shared_ptr<RouteList> rs = writer.get_copy ();
+               rs->remove (route);
                
                /* deleting the master out seems like a dumb
                   idea, but its more of a UI policy issue
                   than our concern.
                */
 
-               if (&route == _master_out) {
-                       _master_out = 0;
+               if (route == _master_out) {
+                       _master_out = shared_ptr<Route> ((Route*) 0);
                }
 
-               if (&route == _control_out) {
-                       _control_out = 0;
+               if (route == _control_out) {
+                       _control_out = shared_ptr<Route> ((Route*) 0);
 
                        /* cancel control outs for all routes */
 
                        vector<string> empty;
 
-                       for (RouteList::iterator r = routes.begin(); r != routes.end(); ++r) {
+                       for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
                                (*r)->set_control_outs (empty);
                        }
                }
 
                update_route_solo_state ();
+               
+               /* writer goes out of scope, forces route list update */
        }
 
+       // FIXME: audio specific
        AudioTrack* at;
        AudioDiskstream* ds = 0;
        
-       if ((at = dynamic_cast<AudioTrack*>(&route)) != 0) {
-               ds = &at->disk_stream();
+       if ((at = dynamic_cast<AudioTrack*>(route.get())) != 0) {
+               ds = &at->audio_diskstream();
        }
        
        if (ds) {
 
                {
                        Glib::RWLock::WriterLock lm (diskstream_lock);
-                       audio_diskstreams.remove (ds);
+                       diskstreams.remove (ds);
                }
 
                ds->unref ();
@@ -1990,7 +1987,7 @@ Session::remove_route (Route& route)
 
        save_state (_current_snapshot_name);
 
-       delete &route;
+       /* all shared ptrs to route should go out of scope here */
 }      
 
 void
@@ -2000,19 +1997,20 @@ Session::route_mute_changed (void* src)
 }
 
 void
-Session::route_solo_changed (void* src, Route* route)
+Session::route_solo_changed (void* src, shared_ptr<Route> route)
 {      
        if (solo_update_disabled) {
                // We know already
                return;
        }
        
-       Glib::RWLock::ReaderLock lm (route_lock);
        bool is_track;
        
-       is_track = (dynamic_cast<AudioTrack*>(route) != 0);
+       is_track = (dynamic_cast<AudioTrack*>(route.get()) != 0);
        
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       shared_ptr<RouteList> r = routes.reader ();
+
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                
                /* soloing a track mutes all other tracks, soloing a bus mutes all other busses */
                
@@ -2020,7 +2018,7 @@ Session::route_solo_changed (void* src, Route* route)
                        
                        /* don't mess with busses */
                        
-                       if (dynamic_cast<AudioTrack*>(*i) == 0) {
+                       if (dynamic_cast<AudioTrack*>((*i).get()) == 0) {
                                continue;
                        }
                        
@@ -2028,7 +2026,7 @@ Session::route_solo_changed (void* src, Route* route)
                        
                        /* don't mess with tracks */
                        
-                       if (dynamic_cast<AudioTrack*>(*i) != 0) {
+                       if (dynamic_cast<AudioTrack*>((*i).get()) != 0) {
                                continue;
                        }
                }
@@ -2061,10 +2059,10 @@ Session::route_solo_changed (void* src, Route* route)
        bool same_thing_soloed = false;
        bool signal = false;
 
-        for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                if ((*i)->soloed()) {
                        something_soloed = true;
-                       if (dynamic_cast<AudioTrack*>(*i)) {
+                       if (dynamic_cast<AudioTrack*>((*i).get())) {
                                if (is_track) {
                                        same_thing_soloed = true;
                                        break;
@@ -2115,11 +2113,13 @@ Session::update_route_solo_state ()
        /* this is where we actually implement solo by changing
           the solo mute setting of each track.
        */
-               
-        for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       
+       shared_ptr<RouteList> r = routes.reader ();
+
+        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                if ((*i)->soloed()) {
                        mute = true;
-                       if (dynamic_cast<AudioTrack*>(*i)) {
+                       if (dynamic_cast<AudioTrack*>((*i).get())) {
                                is_track = true;
                        }
                        break;
@@ -2135,7 +2135,7 @@ Session::update_route_solo_state ()
 
                /* nothing is soloed */
 
-               for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                        (*i)->set_solo_mute (false);
                }
                
@@ -2156,13 +2156,15 @@ Session::update_route_solo_state ()
 void
 Session::modify_solo_mute (bool is_track, bool mute)
 {
-        for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       shared_ptr<RouteList> r = routes.reader ();
+
+        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                
                if (is_track) {
                        
                        /* only alter track solo mute */
                        
-                       if (dynamic_cast<AudioTrack*>(*i)) {
+                       if (dynamic_cast<AudioTrack*>((*i).get())) {
                                if ((*i)->soloed()) {
                                        (*i)->set_solo_mute (!mute);
                                } else {
@@ -2174,7 +2176,7 @@ Session::modify_solo_mute (bool is_track, bool mute)
 
                        /* only alter bus solo mute */
 
-                       if (!dynamic_cast<AudioTrack*>(*i)) {
+                       if (!dynamic_cast<AudioTrack*>((*i).get())) {
 
                                if ((*i)->soloed()) {
 
@@ -2206,36 +2208,35 @@ Session::catch_up_on_solo ()
           basis, but needs the global overview that only the session
           has.
        */
-        Glib::RWLock::ReaderLock lm (route_lock);
        update_route_solo_state();
 }      
                
-Route *
+shared_ptr<Route>
 Session::route_by_name (string name)
 {
-       Glib::RWLock::ReaderLock lm (route_lock);
+       shared_ptr<RouteList> r = routes.reader ();
 
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                if ((*i)->name() == name) {
-                       returni;
+                       return *i;
                }
        }
 
-       return 0;
+       return shared_ptr<Route> ((Route*) 0);
 }
 
-Route *
+shared_ptr<Route>
 Session::route_by_remote_id (uint32_t id)
 {
-       Glib::RWLock::ReaderLock lm (route_lock);
+       shared_ptr<RouteList> r = routes.reader ();
 
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                if ((*i)->remote_control_id() == id) {
-                       returni;
+                       return *i;
                }
        }
 
-       return 0;
+       return shared_ptr<Route> ((Route*) 0);
 }
 
 void
@@ -2264,7 +2265,7 @@ Session::get_maximum_extent () const
           ensure atomicity.
        */
 
-       for (AudioDiskstreamList::const_iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                Playlist* pl = (*i)->playlist();
                if ((me = pl->get_maximum_extent()) > max) {
                        max = me;
@@ -2274,12 +2275,12 @@ Session::get_maximum_extent () const
        return max;
 }
 
-AudioDiskstream *
+Diskstream *
 Session::diskstream_by_name (string name)
 {
        Glib::RWLock::ReaderLock lm (diskstream_lock);
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if ((*i)->name() == name) {
                        return* i;
                }
@@ -2288,12 +2289,12 @@ Session::diskstream_by_name (string name)
        return 0;
 }
 
-AudioDiskstream *
-Session::diskstream_by_id (id_t id)
+Diskstream *
+Session::diskstream_by_id (const PBD::ID& id)
 {
        Glib::RWLock::ReaderLock lm (diskstream_lock);
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if ((*i)->id() == id) {
                        return *i;
                }
@@ -2337,7 +2338,7 @@ Session::new_region_name (string old)
                sbuf = buf;
 
                for (i = audio_regions.begin(); i != audio_regions.end(); ++i) {
-                       if ((*i).second->name() == sbuf) {
+                       if (i->second->name() == sbuf) {
                                break;
                        }
                }
@@ -2402,7 +2403,7 @@ Session::region_name (string& result, string base, bool newlevel) const
                                name_taken = false;
                                
                                for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
-                                       if ((*i).second->name() == result) {
+                                       if (i->second->name() == result) {
                                                name_taken = true;
                                                break;
                                        }
@@ -2447,8 +2448,8 @@ Session::add_region (Region* region)
 
                        if (x == audio_regions.end()) {
 
-                               pair<AudioRegionList::key_type, AudioRegionList::mapped_type> entry;
-       
+                               pair<AudioRegionList::key_type,AudioRegionList::mapped_type> entry;
+
                                entry.first = region->id();
                                entry.second = ar;
 
@@ -2505,16 +2506,18 @@ Session::remove_region (Region* region)
        AudioRegionList::iterator i;
        AudioRegion* ar = 0;
        bool removed = false;
-
+       
        { 
                Glib::Mutex::Lock lm (region_lock);
 
-               if ((ar = dynamic_cast<AudioRegion*> (region)) != 0) {
+               if ((ar = dynamic_cast<AudioRegion*> (region)) != 0) {
                        if ((i = audio_regions.find (region->id())) != audio_regions.end()) {
                                audio_regions.erase (i);
                                removed = true;
-                       } 
+                       }
+
                } else {
+
                        fatal << _("programming error: ") 
                              << X_("unknown region type passed to Session::remove_region()")
                              << endmsg;
@@ -2542,7 +2545,7 @@ Session::find_whole_file_parent (AudioRegion& child)
 
        for (i = audio_regions.begin(); i != audio_regions.end(); ++i) {
 
-               region = (*i).second;
+               region = i->second;
 
                if (region->whole_file()) {
 
@@ -2556,18 +2559,10 @@ Session::find_whole_file_parent (AudioRegion& child)
 }      
 
 void
-Session::find_equivalent_playlist_regions (AudioRegion& region, vector<AudioRegion*>& result)
+Session::find_equivalent_playlist_regions (Region& region, vector<Region*>& result)
 {
-       for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
-
-               AudioPlaylist* pl;
-
-               if ((pl = dynamic_cast<AudioPlaylist*>(*i)) == 0) {
-                       continue;
-               }
-
-               pl->get_region_list_equivalent_regions (region, result);
-       }
+       for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i)
+               (*i)->get_region_list_equivalent_regions (region, result);
 }
 
 int
@@ -2619,7 +2614,7 @@ Session::remove_last_capture ()
 
        Glib::RWLock::ReaderLock lm (diskstream_lock);
        
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                list<Region*>& l = (*i)->last_capture_regions();
                
                if (!l.empty()) {
@@ -2646,12 +2641,12 @@ Session::add_audio_source (AudioSource* source)
 {
        pair<AudioSourceList::key_type, AudioSourceList::mapped_type> entry;
 
-       {
-               Glib::Mutex::Lock lm (audio_source_lock);
+       {
+               Glib::Mutex::Lock lm (audio_source_lock);
                entry.first = source->id();
                entry.second = source;
                audio_sources.insert (entry);
-       }
+       }
        
        source->GoingAway.connect (mem_fun (this, &Session::remove_source));
        set_dirty();
@@ -2669,7 +2664,7 @@ Session::remove_source (Source* source)
 
                if ((i = audio_sources.find (source->id())) != audio_sources.end()) {
                        audio_sources.erase (i);
-               }
+               } 
        }
 
        if (!_state_of_the_state & InCleanup) {
@@ -2685,23 +2680,19 @@ Session::remove_source (Source* source)
 }
 
 Source *
-Session::get_source (ARDOUR::id_t id)
+Session::source_by_id (const PBD::ID& id)
 {
        Glib::Mutex::Lock lm (audio_source_lock);
        AudioSourceList::iterator i;
        Source* source = 0;
 
        if ((i = audio_sources.find (id)) != audio_sources.end()) {
-               source = (*i).second;
-       }
-
-       if (source) {
-               return source;
+               source = i->second;
        }
 
        /* XXX search MIDI or other searches here */
        
-       return 0;
+       return source;
 }
 
 string
@@ -2776,12 +2767,13 @@ Session::change_audio_path_by_name (string path, string oldname, string newname,
                    the task here is to replace NAME with the new name.
                */
                
-               /* find last slash */
-
                string dir;
                string suffix;
                string::size_type slash;
                string::size_type dash;
+               string::size_type postfix;
+
+               /* find last slash */
 
                if ((slash = path.find_last_of ('/')) == string::npos) {
                        return "";
@@ -2795,11 +2787,41 @@ Session::change_audio_path_by_name (string path, string oldname, string newname,
                        return "";
                }
 
-               suffix = path.substr (dash);
+               suffix = path.substr (dash+1);
+               
+               // Suffix is now everything after the dash. Now we need to eliminate
+               // the nnnnn part, which is done by either finding a '%' or a '.'
+
+               postfix = suffix.find_last_of ("%");
+               if (postfix == string::npos) {
+                       postfix = suffix.find_last_of ('.');
+               }
+
+               if (postfix != string::npos) {
+                       suffix = suffix.substr (postfix);
+               } else {
+                       error << "Logic error in Session::change_audio_path_by_name(), please report to the developers" << endl;
+                       return "";
+               }
+
+               const uint32_t limit = 10000;
+               char buf[PATH_MAX+1];
+
+               for (uint32_t cnt = 1; cnt <= limit; ++cnt) {
+
+                       snprintf (buf, sizeof(buf), "%s%s-%u%s", dir.c_str(), newname.c_str(), cnt, suffix.c_str());
+
+                       if (access (buf, F_OK) != 0) {
+                               path = buf;
+                               break;
+                       }
+                       path = "";
+               }
+
+               if (path == "") {
+                       error << "FATAL ERROR! Could not find a " << endl;
+               }
 
-               path = dir;
-               path += new_legalized;
-               path += suffix;
        }
 
        return path;
@@ -2822,20 +2844,20 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
        */
 
        for (cnt = (destructive ? ++destructive_index : 1); cnt <= limit; ++cnt) {
-               
+
                vector<space_and_path>::iterator i;
                uint32_t existing = 0;
-               
+
                for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
-                       
+
                        spath = (*i).path;
-                       
+
                        if (destructive) {
                                spath += tape_dir_name;
                        } else {
                                spath += sound_dir_name;
                        }
-                       
+
                        if (destructive) {
                                if (nchan < 2) {
                                        snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
@@ -2851,10 +2873,10 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
                                        snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
                                }
                        } else {
-                               
+
                                spath += '/';
                                spath += legalized;
-                                       
+
                                if (nchan < 2) {
                                        snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
                                } else if (nchan == 2) {
@@ -2874,7 +2896,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
                                existing++;
                        }
                }
-                       
+
                if (existing == 0) {
                        break;
                }
@@ -2930,18 +2952,6 @@ Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bo
 
 /* Playlist management */
 
-Playlist *
-Session::get_playlist (string name)
-{
-       Playlist* ret = 0;
-
-       if ((ret = playlist_by_name (name)) == 0) {
-               ret = new AudioPlaylist (*this, name);
-       }
-
-       return ret;
-}
-
 Playlist *
 Session::playlist_by_name (string name)
 {
@@ -3071,11 +3081,14 @@ Session::audition_playlist ()
 }
 
 void
-Session::audition_region (AudioRegion& r)
+Session::audition_region (Region& r)
 {
-       Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
-       ev->set_ptr (&r);
-       queue_event (ev);
+       AudioRegion* ar = dynamic_cast<AudioRegion*>(&r);
+       if (ar) {
+               Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
+               ev->set_ptr (ar);
+               queue_event (ev);
+       }
 }
 
 void
@@ -3088,7 +3101,7 @@ Session::cancel_audition ()
 }
 
 bool
-Session::RoutePublicOrderSorter::operator() (Route* a, Route* b)
+Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b)
 {
        return a->order_key(N_("signal")) < b->order_key(N_("signal"));
 }
@@ -3134,13 +3147,11 @@ Session::is_auditioning () const
 void
 Session::set_all_solo (bool yn)
 {
-       {
-               Glib::RWLock::ReaderLock lm (route_lock);
-               
-               for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
-                       if (!(*i)->hidden()) {
-                               (*i)->set_solo (yn, this);
-                       }
+       shared_ptr<RouteList> r = routes.reader ();
+       
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+               if (!(*i)->hidden()) {
+                       (*i)->set_solo (yn, this);
                }
        }
 
@@ -3150,13 +3161,11 @@ Session::set_all_solo (bool yn)
 void
 Session::set_all_mute (bool yn)
 {
-       {
-               Glib::RWLock::ReaderLock lm (route_lock);
-               
-               for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
-                       if (!(*i)->hidden()) {
-                               (*i)->set_mute (yn, this);
-                       }
+       shared_ptr<RouteList> r = routes.reader ();
+       
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+               if (!(*i)->hidden()) {
+                       (*i)->set_mute (yn, this);
                }
        }
 
@@ -3164,12 +3173,12 @@ Session::set_all_mute (bool yn)
 }
                
 uint32_t
-Session::n_audio_diskstreams () const
+Session::n_diskstreams () const
 {
        Glib::RWLock::ReaderLock lm (diskstream_lock);
        uint32_t n = 0;
 
-       for (AudioDiskstreamList::const_iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if (!(*i)->hidden()) {
                        n++;
                }
@@ -3177,17 +3186,6 @@ Session::n_audio_diskstreams () const
        return n;
 }
 
-void 
-Session::foreach_audio_diskstream (void (AudioDiskstream::*func)(void)) 
-{
-       Glib::RWLock::ReaderLock lm (diskstream_lock);
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
-               if (!(*i)->hidden()) {
-                       ((*i)->*func)();
-               }
-       }
-}
-
 void
 Session::graph_reordered ()
 {
@@ -3199,16 +3197,15 @@ Session::graph_reordered ()
                return;
        }
 
-       Glib::RWLock::WriterLock lm1 (route_lock);
        Glib::RWLock::ReaderLock lm2 (diskstream_lock);
 
-       resort_routes (0);
+       resort_routes ();
 
        /* force all diskstreams to update their capture offset values to 
           reflect any changes in latencies within the graph.
        */
        
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->set_capture_offset ();
        }
 }
@@ -3228,12 +3225,12 @@ Session::record_enable_all ()
 void
 Session::record_enable_change_all (bool yn)
 {
-       Glib::RWLock::ReaderLock lm1 (route_lock);
+       shared_ptr<RouteList> r = routes.reader ();
        
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                AudioTrack* at;
 
-               if ((at = dynamic_cast<AudioTrack*>(*i)) != 0) {
+               if ((at = dynamic_cast<AudioTrack*>((*i).get())) != 0) {
                        at->set_record_enable (yn, this);
                }
        }
@@ -3491,7 +3488,7 @@ Session::reset_native_file_format ()
        //RWLockMonitor lm1 (route_lock, true, __LINE__, __FILE__);
        Glib::RWLock::ReaderLock lm2 (diskstream_lock);
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->reset_write_sources (false);
        }
 }
@@ -3499,9 +3496,9 @@ Session::reset_native_file_format ()
 bool
 Session::route_name_unique (string n) const
 {
-       Glib::RWLock::ReaderLock lm (route_lock);
+       shared_ptr<RouteList> r = routes.reader ();
        
-       for (RouteList::const_iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
                if ((*i)->name() == n) {
                        return false;
                }
@@ -3558,23 +3555,16 @@ Session::allocate_pan_automation_buffers (jack_nframes_t nframes, uint32_t howma
        _npan_buffers = howmany;
 }
 
-void 
-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::freeze (InterThreadInfo& itt)
 {
-       Glib::RWLock::ReaderLock lm (route_lock);
+       shared_ptr<RouteList> r = routes.reader ();
 
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
 
                AudioTrack *at;
 
-               if ((at = dynamic_cast<AudioTrack*>(*i)) != 0) {
+               if ((at = dynamic_cast<AudioTrack*>((*i).get())) != 0) {
                        /* XXX this is wrong because itt.progress will keep returning to zero at the start
                           of every track.
                        */
@@ -3609,7 +3599,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
        
        /* call tree *MUST* hold route_lock */
        
-       if ((playlist = track.disk_stream().playlist()) == 0) {
+       if ((playlist = track.diskstream().playlist()) == 0) {
                goto out;
        }
 
@@ -3619,7 +3609,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
                goto out;
        }
 
-       nchans = track.disk_stream().n_channels();
+       nchans = track.audio_diskstream().n_channels();
        
        dir = discover_best_sound_dir ();
 
@@ -3763,10 +3753,10 @@ uint32_t
 Session::ntracks () const
 {
        uint32_t n = 0;
-       Glib::RWLock::ReaderLock lm (route_lock);
+       shared_ptr<RouteList> r = routes.reader ();
 
-       for (RouteList::const_iterator i = routes.begin(); i != routes.end(); ++i) {
-               if (dynamic_cast<AudioTrack*> (*i)) {
+       for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
+               if (dynamic_cast<AudioTrack*> ((*i).get())) {
                        ++n;
                }
        }
@@ -3778,10 +3768,10 @@ uint32_t
 Session::nbusses () const
 {
        uint32_t n = 0;
-       Glib::RWLock::ReaderLock lm (route_lock);
+       shared_ptr<RouteList> r = routes.reader ();
 
-       for (RouteList::const_iterator i = routes.begin(); i != routes.end(); ++i) {
-               if (dynamic_cast<AudioTrack*> (*i) == 0) {
+       for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
+               if (dynamic_cast<AudioTrack*> ((*i).get()) == 0) {
                        ++n;
                }
        }
index 4613bfccf9c2b4467b2ed8da5d43b6fb20ae581b..6509a783bb8ad8481050480cea09241087001c81 100644 (file)
@@ -168,15 +168,9 @@ Session::butler_thread_work ()
        struct timeval begin, end;
        struct pollfd pfd[1];
        bool disk_work_outstanding = false;
-       AudioDiskstreamList::iterator i;
-
-       butler_mixdown_buffer = new Sample[AudioDiskstream::disk_io_frames()];
-       butler_gain_buffer = new gain_t[AudioDiskstream::disk_io_frames()];
-       // this buffer is used for temp conversion purposes in filesources
-       char * conv_buffer = conversion_buffer(ButlerContext);
+       DiskstreamList::iterator i;
 
        while (true) {
-
                pfd[0].fd = butler_request_pipe[0];
                pfd[0].events = POLLIN|POLLERR|POLLHUP;
                
@@ -198,14 +192,13 @@ Session::butler_thread_work ()
                }
                
                if (pfd[0].revents & POLLIN) {
-                       
+
                        char req;
                        
                        /* empty the pipe of all current requests */
                        
                        while (1) {
                                size_t nread = ::read (butler_request_pipe[0], &req, sizeof (req));
-                               
                                if (nread == 1) {
                                        
                                        switch ((ButlerRequest::Type) req) {
@@ -240,10 +233,10 @@ Session::butler_thread_work ()
                                }
                        }
                }
-       
-               for (i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+
+               //for (i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        // cerr << "BEFORE " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
-               }
+               //}
 
                if (transport_work_requested()) {
                        butler_transport_work ();
@@ -257,16 +250,16 @@ Session::butler_thread_work ()
 
                Glib::RWLock::ReaderLock dsm (diskstream_lock);
                
-               for (i = audio_diskstreams.begin(); !transport_work_requested() && butler_should_run && i != audio_diskstreams.end(); ++i) {
-                       
-                       // cerr << "rah fondr " << (*i)->io()->name () << endl;
+               for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) {
+
+                       Diskstream* const ds = *i;
 
-                       switch ((*i)->do_refill (butler_mixdown_buffer, butler_gain_buffer, conv_buffer)) {
+                       switch (ds->do_refill ()) {
                        case 0:
-                               bytes += (*i)->read_data_count();
+                               bytes += ds->read_data_count();
                                break;
                        case 1:
-                               bytes += (*i)->read_data_count();
+                               bytes += ds->read_data_count();
                                disk_work_outstanding = true;
                                break;
                                
@@ -278,7 +271,7 @@ Session::butler_thread_work ()
 
                }
 
-               if (i != audio_diskstreams.end()) {
+               if (i != diskstreams.end()) {
                        /* we didn't get to all the streams */
                        disk_work_outstanding = true;
                }
@@ -299,12 +292,11 @@ Session::butler_thread_work ()
                bytes = 0;
                compute_io = true;
                gettimeofday (&begin, 0);
-               
-               for (i = audio_diskstreams.begin(); !transport_work_requested() && butler_should_run && i != audio_diskstreams.end(); ++i) {
-                       
+
+               for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) {
                        // cerr << "write behind for " << (*i)->name () << endl;
                        
-                       switch ((*i)->do_flush (conv_buffer)) {
+                       switch ((*i)->do_flush (Session::ButlerContext)) {
                        case 0:
                                bytes += (*i)->write_data_count();
                                break;
@@ -330,7 +322,7 @@ Session::butler_thread_work ()
                        request_stop ();
                }
 
-               if (i != audio_diskstreams.end()) {
+               if (i != diskstreams.end()) {
                        /* we didn't get to all the streams */
                        disk_work_outstanding = true;
                }
@@ -357,7 +349,7 @@ Session::butler_thread_work ()
                        Glib::Mutex::Lock lm (butler_request_lock);
 
                        if (butler_should_run && (disk_work_outstanding || transport_work_requested())) {
-//                             for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+//                             for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
 //                                     cerr << "AFTER " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
 //                             }
 
@@ -375,18 +367,17 @@ Session::butler_thread_work ()
 
 
 void
-Session::request_overwrite_buffer (AudioDiskstream* stream)
+Session::request_overwrite_buffer (Diskstream* stream)
 {
        Event *ev = new Event (Event::Overwrite, Event::Add, Event::Immediate, 0, 0, 0.0);
        ev->set_ptr (stream);
        queue_event (ev);
 }
 
+/** Process thread. */
 void
-Session::overwrite_some_buffers (AudioDiskstream* ds)
+Session::overwrite_some_buffers (Diskstream* ds)
 {
-       /* executed by the audio thread */
-
        if (actively_recording()) {
                return;
        }
@@ -398,7 +389,7 @@ Session::overwrite_some_buffers (AudioDiskstream* ds)
        } else {
 
                Glib::RWLock::ReaderLock dm (diskstream_lock);
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        (*i)->set_pending_overwrite (true);
                }
        }
index ddced9cc5f85f169169d036a6c2f25f11647747e..b39c4f22185cb4398c181b3400420dd76d28f0b9 100644 (file)
@@ -485,8 +485,9 @@ Session::prepare_to_export (AudioExportSpecification& spec)
        /* take everyone out of awrite to avoid disasters */
 
        {
-               Glib::RWLock::ReaderLock lm (route_lock);
-               for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+               boost::shared_ptr<RouteList> r = routes.reader ();
+
+               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                        (*i)->protect_automation ();
                }
        }
@@ -495,7 +496,7 @@ Session::prepare_to_export (AudioExportSpecification& spec)
 
        {
                Glib::RWLock::ReaderLock lm (diskstream_lock);
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if ((*i)-> seek (spec.start_frame, true)) {
                                error << string_compose (_("%1: cannot seek to %2 for export"),
                                                  (*i)->name(), spec.start_frame)
index 60bd95464fa8669d13e0123b772acaaeb7ac7a21..821f894eeb1f4cb64d803c87c90c896c1e1fa16f 100644 (file)
@@ -109,13 +109,6 @@ Session::set_midi_control (bool yn)
        set_dirty();
        poke_midi_thread ();
 
-       if (_midi_port) {
-               Glib::RWLock::ReaderLock guard (route_lock);
-               for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
-                       (*i)->reset_midi_control (_midi_port, midi_control);
-               }
-       }
-
        ControlChanged (MidiControl); /* EMIT SIGNAL */
 }
 
@@ -783,12 +776,12 @@ Session::mmc_record_enable (MIDI::MachineControl &mmc, size_t trk, bool enabled)
        if (mmc_control) {
 
                RouteList::iterator i;
-               Glib::RWLock::ReaderLock guard (route_lock);
+               boost::shared_ptr<RouteList> r = routes.reader();
                
-               for (i = routes.begin(); i != routes.end(); ++i) {
+               for (i = r->begin(); i != r->end(); ++i) {
                        AudioTrack *at;
 
-                       if ((at = dynamic_cast<AudioTrack*>(*i)) != 0) {
+                       if ((at = dynamic_cast<AudioTrack*>((*i).get())) != 0) {
                                if (trk == at->remote_control_id()) {
                                        at->set_record_enable (enabled, &mmc);
                                        break;
index ad4e9a64bb0674281f9e1eecc47e13a4c2096fc3..88b111a1fbedb24fd8d1ea25b47065c2e60237b4 100644 (file)
@@ -59,12 +59,14 @@ Session::process (jack_nframes_t nframes)
        } 
        
        (this->*process_function) (nframes);
+
+       SendFeedback (); /* EMIT SIGNAL */
 }
 
 void
 Session::prepare_diskstreams ()
 {
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->prepare ();
        }
 }
@@ -75,23 +77,20 @@ Session::no_roll (jack_nframes_t nframes, jack_nframes_t offset)
        jack_nframes_t end_frame = _transport_frame + nframes;
        int ret = 0;
        bool declick = get_transport_declick_required();
+       boost::shared_ptr<RouteList> r = routes.reader ();
 
        if (_click_io) {
                _click_io->silence (nframes, offset);
        }
 
-       /* XXX we're supposed to have the route_lock while doing this.
-          this is really bad ...
-       */
-
        if (g_atomic_int_get (&processing_prohibited)) {
-               for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                        (*i)->silence (nframes, offset);
                }
                return 0;
        }
 
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                
                if ((*i)->hidden()) {
                        continue;
@@ -116,6 +115,7 @@ Session::process_routes (jack_nframes_t nframes, jack_nframes_t offset)
        bool record_active;
        int  declick = get_transport_declick_required();
        bool rec_monitors = get_rec_monitors_input();
+       boost::shared_ptr<RouteList> r = routes.reader ();
 
        if (transport_sub_state & StopPendingCapture) {
                /* force a declick out */
@@ -124,7 +124,7 @@ Session::process_routes (jack_nframes_t nframes, jack_nframes_t offset)
 
        record_active = actively_recording(); // || (get_record_enabled() && get_punch_in());
 
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
 
                int ret;
 
@@ -141,7 +141,7 @@ Session::process_routes (jack_nframes_t nframes, jack_nframes_t offset)
                           call path, so make sure we release any outstanding locks here before we return failure.
                        */
 
-                       for (AudioDiskstreamList::iterator ids = audio_diskstreams.begin(); ids != audio_diskstreams.end(); ++ids) {
+                       for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) {
                                (*ids)->recover ();
                        }
 
@@ -159,13 +159,14 @@ Session::silent_process_routes (jack_nframes_t nframes, jack_nframes_t offset)
        bool record_active = actively_recording();
        int  declick = get_transport_declick_required();
        bool rec_monitors = get_rec_monitors_input();
+       boost::shared_ptr<RouteList> r = routes.reader ();
 
        if (transport_sub_state & StopPendingCapture) {
                /* force a declick out */
                declick = -1;
        }
 
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
 
                int ret;
 
@@ -180,7 +181,7 @@ Session::silent_process_routes (jack_nframes_t nframes, jack_nframes_t offset)
                           call path, so make sure we release any outstanding locks here before we return failure.
                        */
 
-                       for (AudioDiskstreamList::iterator ids = audio_diskstreams.begin(); ids != audio_diskstreams.end(); ++ids) {
+                       for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) {
                                (*ids)->recover ();
                        }
 
@@ -199,7 +200,7 @@ Session::commit_diskstreams (jack_nframes_t nframes, bool &needs_butler)
        float pworst = 1.0f;
        float cworst = 1.0f;
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
 
                if ((*i)->hidden()) {
                        continue;
@@ -247,10 +248,14 @@ Session::process_with_events (jack_nframes_t nframes)
        jack_nframes_t stop_limit;
        long           frames_moved;
 
+       /* make sure the auditioner is silent */
+
        if (auditioner) {
                auditioner->silence (nframes, 0);
        }
 
+       /* handle any pending events */
+
        while (pending_events.read (&ev, 1) == 1) {
                merge_event (ev);
        }
@@ -279,13 +284,12 @@ Session::process_with_events (jack_nframes_t nframes)
        end_frame = _transport_frame + nframes;
 
        {
-               Glib::RWLock::ReaderLock rm (route_lock, Glib::TRY_LOCK);
                Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK);
        
                Event* this_event;
                Events::iterator the_next_one;
-
-               if (!rm.locked() || !dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
+               
+               if (!dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
                        no_roll (nframes, 0);
                        return;
                }
@@ -566,7 +570,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
                                bool ok = true;
                                jack_nframes_t frame_delta = slave_transport_frame - _transport_frame;
                                
-                               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                        if (!(*i)->can_internal_playback_seek (frame_delta)) {
                                                ok = false;
                                                break;
@@ -574,7 +578,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
                                }
 
                                if (ok) {
-                                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                                (*i)->internal_playback_seek (frame_delta);
                                        }
                                        _transport_frame += frame_delta;
@@ -692,7 +696,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
                        summon_butler ();
                }
                
-               jack_nframes_t frames_moved = (long) floor (_transport_speed * nframes);
+               int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
                
                if (frames_moved < 0) {
                        decrement_transport_position (-frames_moved);
@@ -729,10 +733,9 @@ Session::process_without_events (jack_nframes_t nframes)
        long frames_moved;
        
        {
-               Glib::RWLock::ReaderLock rm (route_lock, Glib::TRY_LOCK);
                Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK);
 
-               if (!rm.locked() || !dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
+               if (!dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
                        no_roll (nframes, 0);
                        return;
                }
@@ -801,21 +804,23 @@ Session::process_without_events (jack_nframes_t nframes)
 void
 Session::process_audition (jack_nframes_t nframes)
 {
-       Glib::RWLock::ReaderLock rm (route_lock, Glib::TRY_LOCK);
        Event* ev;
+       boost::shared_ptr<RouteList> r = routes.reader ();
 
-       if (rm.locked()) {
-               for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
-                       if (!(*i)->hidden()) {
-                               (*i)->silence (nframes, 0);
-                       }
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+               if (!(*i)->hidden()) {
+                       (*i)->silence (nframes, 0);
                }
        }
+
+       /* run the auditioner, and if it says we need butler service, ask for it */
        
        if (auditioner->play_audition (nframes) > 0) {
                summon_butler ();
        } 
 
+       /* handle pending events */
+
        while (pending_events.read (&ev, 1) == 1) {
                merge_event (ev);
        }
index 0ae73291e0953b50c3aeedf858e3369a77b02b44..9619e77ad1fed018e532bdea311ba795d9806791 100644 (file)
@@ -165,7 +165,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        _slave_type = None;
        butler_mixdown_buffer = 0;
        butler_gain_buffer = 0;
-       auditioner = 0;
        mmc_control = false;
        midi_control = true;
        mmc = 0;
@@ -180,8 +179,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        _edit_mode = Slide;
        pending_edit_mode = _edit_mode;
        _play_range = false;
-       _control_out = 0;
-       _master_out = 0;
        input_auto_connect = AutoConnectOption (0);
        output_auto_connect = AutoConnectOption (0);
        waiting_to_start = false;
@@ -197,6 +194,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        /* allocate conversion buffers */
        _conversion_buffers[ButlerContext] = new char[AudioDiskstream::disk_io_frames() * 4];
        _conversion_buffers[TransportContext] = new char[AudioDiskstream::disk_io_frames() * 4];
+       AudioDiskstream::allocate_working_buffers();
        
        /* default short fade = 15ms */
 
@@ -216,7 +214,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
           waveforms for clicks.
        */
        
-       _click_io = 0;
        _clicking = false;
        click_requested = false;
        click_data = 0;
@@ -270,9 +267,12 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        AudioSource::AudioSourceCreated.connect (mem_fun (*this, &Session::add_audio_source));
        Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
        Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
-       AudioDiskstream::AudioDiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
+       AudioDiskstream::DiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
        NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
 
+       Controllable::Created.connect (mem_fun (*this, &Session::add_controllable));
+       Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable));
+
        IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
 
        /* stop IO objects from doing stuff until we're ready for them */
@@ -1330,6 +1330,13 @@ Session::state(bool full_state)
                }
        }
 
+       /* save the ID counter */
+       
+       snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
+       node->add_property ("id-counter", buf);
+
+       /* various options */
+
        node->add_child_nocopy (get_options());
 
        child = node->add_child ("Sources");
@@ -1343,7 +1350,7 @@ Session::state(bool full_state)
                        
                        AudioFileSource* fs;
 
-                       if ((fs = dynamic_cast<AudioFileSource*> ((*siter).second)) != 0) {
+                       if ((fs = dynamic_cast<AudioFileSource*> (siter->second)) != 0) {
                                DestructiveFileSource* dfs = dynamic_cast<DestructiveFileSource*> (fs);
 
                                /* destructive file sources are OK if they are empty, because
@@ -1357,7 +1364,7 @@ Session::state(bool full_state)
                                }
                        }
                        
-                       child->add_child_nocopy ((*siter).second->get_state());
+                       child->add_child_nocopy (siter->second->get_state());
                }
        }
 
@@ -1370,7 +1377,7 @@ Session::state(bool full_state)
                        
                        /* only store regions not attached to playlists */
 
-                       if ((*i).second->playlist() == 0) {
+                       if (i->second->playlist() == 0) {
                                child->add_child_nocopy (i->second->state (true));
                        }
                }
@@ -1380,7 +1387,7 @@ Session::state(bool full_state)
 
        { 
                Glib::RWLock::ReaderLock dl (diskstream_lock);
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if (!(*i)->hidden()) {
                                child->add_child_nocopy ((*i)->get_state());
                        }
@@ -1401,10 +1408,10 @@ Session::state(bool full_state)
 
        child = node->add_child ("Routes");
        {
-               Glib::RWLock::ReaderLock lm (route_lock);
+               boost::shared_ptr<RouteList> r = routes.reader ();
                
                RoutePublicOrderSorter cmp;
-               RouteList public_order(routes);
+               RouteList public_order (*r);
                public_order.sort (cmp);
                
                for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
@@ -1489,7 +1496,7 @@ Session::set_state (const XMLNode& node)
 
        _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
        
-       if (node.name() != "Session"){
+       if (node.name() != X_("Session")){
                fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
                return -1;
        }
@@ -1499,6 +1506,21 @@ Session::set_state (const XMLNode& node)
        if ((prop = node.property ("name")) != 0) {
                _name = prop->value ();
        }
+
+       if ((prop = node.property (X_("id-counter"))) != 0) {
+               uint64_t x;
+               sscanf (prop->value().c_str(), "%" PRIu64, &x);
+               ID::init_counter (x);
+       } else {
+               /* old sessions used a timebased counter, so fake
+                  the startup ID counter based on a standard
+                  timestamp.
+               */
+               time_t now;
+               time (&now);
+               ID::init_counter (now);
+       }
+
        
        IO::disable_ports ();
        IO::disable_connecting ();
@@ -1685,7 +1707,6 @@ Session::load_routes (const XMLNode& node)
 {
        XMLNodeList nlist;
        XMLNodeConstIterator niter;
-       Route *route;
 
        nlist = node.children();
 
@@ -1693,7 +1714,9 @@ Session::load_routes (const XMLNode& node)
 
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
 
-               if ((route = XMLRouteFactory (**niter)) == 0) {
+               boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
+
+               if (route == 0) {
                        error << _("Session: cannot create Route from XML description.")                              << endmsg;
                        return -1;
                }
@@ -1704,17 +1727,19 @@ Session::load_routes (const XMLNode& node)
        return 0;
 }
 
-Route *
+boost::shared_ptr<Route>
 Session::XMLRouteFactory (const XMLNode& node)
 {
        if (node.name() != "Route") {
-               return 0;
+               return boost::shared_ptr<Route> ((Route*) 0);
        }
 
        if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
-               return new AudioTrack (*this, node);
+               boost::shared_ptr<Route> x (new AudioTrack (*this, node));
+               return x;
        } else {
-               return new Route (*this, node);
+               boost::shared_ptr<Route> x (new Route (*this, node));
+               return x;
        }
 }
 
@@ -1730,12 +1755,10 @@ Session::load_regions (const XMLNode& node)
        set_dirty();
 
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
-
                if ((region = XMLRegionFactory (**niter, false)) == 0) {
                        error << _("Session: cannot create Region from XML description.") << endmsg;
                }
        }
-
        return 0;
 }
 
@@ -1743,7 +1766,6 @@ AudioRegion *
 Session::XMLRegionFactory (const XMLNode& node, bool full)
 {
        const XMLProperty* prop;
-       id_t s_id;
        Source* source;
        AudioSource* as;
        AudioRegion::SourceList sources;
@@ -1766,9 +1788,9 @@ Session::XMLRegionFactory (const XMLNode& node, bool full)
                }
        }
 
-       sscanf (prop->value().c_str(), "%" PRIu64, &s_id);
+       PBD::ID s_id (prop->value());
 
-       if ((source = get_source (s_id)) == 0) {
+       if ((source = source_by_id (s_id)) == 0) {
                error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
                return 0;
        }
@@ -1786,23 +1808,23 @@ Session::XMLRegionFactory (const XMLNode& node, bool full)
        for (uint32_t n=1; n < nchans; ++n) {
                snprintf (buf, sizeof(buf), X_("source-%d"), n);
                if ((prop = node.property (buf)) != 0) {
-                       sscanf (prop->value().c_str(), "%" PRIu64, &s_id);
                        
-                       if ((source = get_source (s_id)) == 0) {
-                               error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
+                       PBD::ID id2 (prop->value());
+                       
+                       if ((source = source_by_id (id2)) == 0) {
+                               error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
                                return 0;
                        }
                        
                        as = dynamic_cast<AudioSource*>(source);
                        if (!as) {
-                               error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
+                               error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
                                return 0;
                        }
                        sources.push_back (as);
                }
        }
        
-       
        try {
                return new AudioRegion (sources, node);
        }
@@ -1820,7 +1842,7 @@ Session::get_sources_as_xml ()
        Glib::Mutex::Lock lm (audio_source_lock);
 
        for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
-               node->add_child_nocopy ((*i).second->get_state());
+               node->add_child_nocopy (i->second->get_state());
        }
 
        /* XXX get MIDI and other sources here */
@@ -2401,23 +2423,6 @@ Session::load_route_groups (const XMLNode& node, bool edit)
        return 0;
 }                              
 
-void
-Session::swap_configuration(Configuration** new_config)
-{
-       Glib::RWLock::WriterLock lm (route_lock); // jlc - WHY?
-       Configuration* tmp = *new_config;
-       *new_config = Config;
-       Config = tmp;
-       set_dirty();
-}
-
-void
-Session::copy_configuration(Configuration* new_config)
-{
-       Glib::RWLock::WriterLock lm (route_lock);
-       new_config = new Configuration(*Config);
-}
-
 static bool
 state_file_filter (const string &str, void *arg)
 {
@@ -2441,7 +2446,7 @@ remove_end(string* state)
                statename = statename.substr (start+1);
        }
                
-       if ((end = statename.rfind(".ardour")) < 0) {
+       if ((end = statename.rfind(".ardour")) == string::npos) {
                end = statename.length();
        }
 
@@ -2589,14 +2594,15 @@ Session::GlobalRouteBooleanState
 Session::get_global_route_boolean (bool (Route::*method)(void) const)
 {
        GlobalRouteBooleanState s;
-       Glib::RWLock::ReaderLock lm (route_lock);
+       boost::shared_ptr<RouteList> r = routes.reader ();
 
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                if (!(*i)->hidden()) {
                        RouteBooleanState v;
                        
                        v.first =* i;
-                       v.second = ((*i)->*method)();
+                       Route* r = (*i).get();
+                       v.second = (r->*method)();
                        
                        s.push_back (v);
                }
@@ -2609,9 +2615,9 @@ Session::GlobalRouteMeterState
 Session::get_global_route_metering ()
 {
        GlobalRouteMeterState s;
-       Glib::RWLock::ReaderLock lm (route_lock);
+       boost::shared_ptr<RouteList> r = routes.reader ();
 
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                if (!(*i)->hidden()) {
                        RouteMeterState v;
                        
@@ -2637,7 +2643,8 @@ void
 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
 {
        for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
-               (i->first->*method) (i->second, arg);
+               Route* r = i->first.get();
+               (r->*method) (i->second, arg);
        }
 }
 
@@ -2944,7 +2951,7 @@ Session::cleanup_sources (Session::cleanup_report& rep)
                   capture files.
                */
 
-               if ((*i).second->use_cnt() == 0 && (*i).second->length() > 0) {
+               if (i->second->use_cnt() == 0 && i->second->length() > 0) {
                        dead_sources.push_back (i->second);
 
                        /* remove this source from our own list to avoid us
@@ -2971,7 +2978,7 @@ Session::cleanup_sources (Session::cleanup_report& rep)
                        tmp = r;
                        ++tmp;
                        
-                       ar = (*r).second;
+                       ar = r->second;
 
                        for (uint32_t n = 0; n < ar->n_channels(); ++n) {
                                if (&ar->source (n) == (*i)) {
@@ -3024,7 +3031,7 @@ Session::cleanup_sources (Session::cleanup_report& rep)
        for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
                AudioFileSource* fs;
                
-               if ((fs = dynamic_cast<AudioFileSource*> ((*i).second)) != 0) {
+               if ((fs = dynamic_cast<AudioFileSource*> (i->second)) != 0) {
                        all_sources.insert (fs->path());
                } 
        }
@@ -3233,3 +3240,41 @@ Session::set_clean ()
        }
 }
 
+void
+Session::add_controllable (Controllable* c)
+{
+       Glib::Mutex::Lock lm (controllables_lock);
+       controllables.push_back (c);
+}
+
+void
+Session::remove_controllable (Controllable* c)
+{
+       if (_state_of_the_state | Deletion) {
+               return;
+       }
+
+       Glib::Mutex::Lock lm (controllables_lock);
+       controllables.remove (c);
+}      
+
+Controllable*
+Session::controllable_by_id (const PBD::ID& id)
+{
+       Glib::Mutex::Lock lm (controllables_lock);
+       
+       for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
+               if ((*i)->id() == id) {
+                       return *i;
+               }
+       }
+
+       return 0;
+}
+
+void 
+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());
+}
index 0e52c926fe601e99a79112d21070f7ed5be1ef31..bd2c992ff5b6706b9d8197fe4193d6a57a62f153 100644 (file)
@@ -32,7 +32,6 @@
 #include <ardour/audioengine.h>
 #include <ardour/session.h>
 #include <ardour/tempo.h>
-#include <ardour/audiofilesource.h>
 
 #include "i18n.h"
 
@@ -93,8 +92,6 @@ Session::set_smpte_offset (jack_nframes_t off)
        _smpte_offset = off;
        last_smpte_valid = false;
 
-       AudioFileSource::set_header_position_offset (_smpte_offset, _smpte_offset_negative);
-
        SMPTEOffsetChanged (); /* EMIT SIGNAL */
 }
 
@@ -104,8 +101,6 @@ Session::set_smpte_offset_negative (bool neg)
        _smpte_offset_negative = neg;
        last_smpte_valid = false;
 
-       AudioFileSource::set_header_position_offset (_smpte_offset, _smpte_offset_negative);
-
        SMPTEOffsetChanged (); /* EMIT SIGNAL */
 }
 
index 55bdac064b4fb6ab47fdcd4a7218b49565316f6e..3bd54aa69c054139ad2b884b2c8bb2d568e1a11b 100644 (file)
@@ -80,7 +80,7 @@ Session::request_transport_speed (float speed)
 }
 
 void
-Session::request_diskstream_speed (AudioDiskstream& ds, float speed)
+Session::request_diskstream_speed (Diskstream& ds, float speed)
 {
        Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
        ev->set_ptr (&ds);
@@ -192,17 +192,17 @@ Session::realtime_stop (bool abort)
 void
 Session::butler_transport_work ()
 {
-       Glib::RWLock::ReaderLock rm (route_lock);
        Glib::RWLock::ReaderLock dsm (diskstream_lock);
-               
+       boost::shared_ptr<RouteList> r = routes.reader ();
+
        if (post_transport_work & PostTransportCurveRealloc) {
-               for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                        (*i)->curve_reallocate();
                }
        }
 
        if (post_transport_work & PostTransportInputChange) {
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        (*i)->non_realtime_input_change ();
                }
        }
@@ -218,7 +218,7 @@ Session::butler_transport_work ()
                cumulative_rf_motion = 0;
                reset_rf_scale (0);
 
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if (!(*i)->hidden()) {
                                if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
                                        (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
@@ -250,7 +250,7 @@ Session::non_realtime_set_speed ()
 {
        Glib::RWLock::ReaderLock lm (diskstream_lock);
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->non_realtime_set_speed ();
        }
 }
@@ -260,7 +260,7 @@ Session::non_realtime_overwrite ()
 {
        Glib::RWLock::ReaderLock lm (diskstream_lock);
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if ((*i)->pending_overwrite) {
                        (*i)->overwrite_existing_buffers ();
                }
@@ -276,7 +276,7 @@ Session::non_realtime_stop (bool abort)
        
        did_record = false;
        
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if ((*i)->get_captured_frames () != 0) {
                        did_record = true;
                        break;
@@ -331,11 +331,13 @@ Session::non_realtime_stop (bool abort)
                _have_captured = true;
        }
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->transport_stopped (*now, xnow, abort);
        }
        
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       boost::shared_ptr<RouteList> r = routes.reader ();
+
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                if (!(*i)->hidden()) {
                        (*i)->set_pending_declick (0);
                }
@@ -368,7 +370,7 @@ Session::non_realtime_stop (bool abort)
        }
 #endif
 
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if (!(*i)->hidden()) {
                                if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
                                        (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
@@ -495,7 +497,7 @@ Session::set_auto_loop (bool yn)
 
                        if (seamless_loop) {
                                // set all diskstreams to use internal looping
-                               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                        if (!(*i)->hidden()) {
                                                (*i)->set_loop (loc);
                                        }
@@ -503,7 +505,7 @@ Session::set_auto_loop (bool yn)
                        }
                        else {
                                // set all diskstreams to NOT use internal looping
-                               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                        if (!(*i)->hidden()) {
                                                (*i)->set_loop (0);
                                        }
@@ -533,7 +535,7 @@ Session::set_auto_loop (bool yn)
                clear_events (Event::AutoLoop);
 
                // set all diskstreams to NOT use internal looping
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if (!(*i)->hidden()) {
                                (*i)->set_loop (0);
                        }
@@ -547,7 +549,9 @@ Session::set_auto_loop (bool yn)
 void
 Session::flush_all_redirects ()
 {
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       boost::shared_ptr<RouteList> r = routes.reader ();
+
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                (*i)->flush_redirects ();
        }
 }
@@ -649,7 +653,7 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
                           The rarity and short potential lock duration makes this "OK"
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
                                        (*i)->monitor_input (!auto_input);
@@ -664,7 +668,7 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
                           The rarity and short potential lock duration makes this "OK"
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
                                        (*i)->monitor_input (true);
@@ -708,7 +712,7 @@ Session::set_transport_speed (float speed, bool abort)
                           The rarity and short potential lock duration makes this "OK"
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if ((*i)->record_enabled ()) {
                                        //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
                                        (*i)->monitor_input (true);     
@@ -734,7 +738,7 @@ Session::set_transport_speed (float speed, bool abort)
                           The rarity and short potential lock duration makes this "OK"
                        */
                        Glib::RWLock::ReaderLock dsm (diskstream_lock);
-                       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+                       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                                if (auto_input && (*i)->record_enabled ()) {
                                        //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
                                        (*i)->monitor_input (false);    
@@ -785,7 +789,7 @@ Session::set_transport_speed (float speed, bool abort)
                _last_transport_speed = _transport_speed;
                _transport_speed = speed;
                
-               for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+               for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                        if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
                                post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
                        }
@@ -875,7 +879,7 @@ Session::actually_start_transport ()
        transport_sub_state |= PendingDeclickIn;
        _transport_speed = 1.0;
        
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->realtime_set_speed ((*i)->speed(), true);
        }
 
@@ -1005,7 +1009,7 @@ Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
        
        _slave_type = src;
 
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                if (!(*i)->hidden()) {
                        if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
                                non_rt_required = true;
@@ -1037,7 +1041,7 @@ Session::reverse_diskstream_buffers ()
 }
 
 void
-Session::set_diskstream_speed (AudioDiskstream* stream, float speed)
+Session::set_diskstream_speed (Diskstream* stream, float speed)
 {
        if (stream->realtime_set_speed (speed, false)) {
                post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
@@ -1196,11 +1200,12 @@ Session::update_latency_compensation (bool with_stop, bool abort)
                return;
        }
 
-       Glib::RWLock::ReaderLock lm (route_lock);
        Glib::RWLock::ReaderLock lm2 (diskstream_lock);
        _worst_track_latency = 0;
 
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       boost::shared_ptr<RouteList> r = routes.reader ();
+
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                if (with_stop) {
                        (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate), 
                                                        (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
@@ -1218,7 +1223,7 @@ Session::update_latency_compensation (bool with_stop, bool abort)
                }
        }
 
-       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                (*i)->set_latency_delay (_worst_track_latency);
        }
 
@@ -1228,12 +1233,12 @@ Session::update_latency_compensation (bool with_stop, bool abort)
                _engine.update_total_latencies ();
        }
 
-       set_worst_io_latencies (false);
+       set_worst_io_latencies ();
 
        /* reflect any changes in latencies into capture offsets
        */
        
-       for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
+       for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
                (*i)->set_capture_offset ();
        }
 }
index 443a24e3c2cfe1deeea83324ca1d840ec5e394af..5936f6257027eb77256e2ec2138f89b6dd88ca5b 100644 (file)
@@ -156,6 +156,8 @@ SndFileSource::SndFileSource (string idstr, SampleFormat sfmt, HeaderFormat hf,
                          utsinfo.version);
                
                _broadcast_info->version = 1;  
+               _broadcast_info->time_reference_low = 0;  
+               _broadcast_info->time_reference_high = 0;  
                
                /* XXX do something about this field */
                
@@ -183,6 +185,7 @@ SndFileSource::SndFileSource (string idstr, SampleFormat sfmt, HeaderFormat hf,
        }
 
        AudioSourceCreated (this); /* EMIT SIGNAL */
+
 }
 
 void 
@@ -246,21 +249,19 @@ SndFileSource::open ()
                        _flags = Flag (_flags & ~Broadcast);
                }
 
+               set_timeline_position (header_position_offset);
+
        } else {
        
                /* XXX 64 bit alert: when JACK switches to a 64 bit frame count, this needs to use the high bits
                   of the time reference.
                */
-               
-               set_timeline_position (_broadcast_info->time_reference_low);
+
+               set_timeline_position ( _broadcast_info->time_reference_low );
        }
 
        if (writable()) {
                sf_command (sf, SFC_SET_UPDATE_HEADER_AUTO, 0, SF_FALSE);
-
-               /* update header if header offset info changes */
-               
-               AudioFileSource::HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioFileSource::handle_header_position_change));
        }
 
        return 0;
@@ -280,7 +281,7 @@ SndFileSource::~SndFileSource ()
        }
 
        if (_broadcast_info) {
-               free (_broadcast_info);
+               delete _broadcast_info;
        }
 }
 
@@ -472,7 +473,7 @@ SndFileSource::setup_broadcast_info (jack_nframes_t when, struct tm& now, time_t
                  now.tm_mon,
                  now.tm_mday);
        
-       snprintf (_broadcast_info->origination_time, sizeof (_broadcast_info->origination_time), "%02d-%02d-%02d",
+       snprintf (_broadcast_info->origination_time, sizeof (_broadcast_info->origination_time), "%02d:%02d:%02d",
                  now.tm_hour,
                  now.tm_min,
                  now.tm_sec);
@@ -495,33 +496,12 @@ SndFileSource::setup_broadcast_info (jack_nframes_t when, struct tm& now, time_t
 void
 SndFileSource::set_header_timeline_position ()
 {
-       uint64_t pos;
-
        if (!(_flags & Broadcast)) {
                return;
        }
 
-       _broadcast_info->time_reference_high = 0;
-
-       if (header_position_negative) {
-
-               if (ULONG_LONG_MAX - header_position_offset < timeline_position) {
-                       pos = ULONG_LONG_MAX; // impossible
-               } else {
-                       pos = timeline_position + header_position_offset;
-               }
-
-       } else {
-
-               if (timeline_position < header_position_offset) {
-                       pos = 0;
-               } else {
-                       pos = timeline_position - header_position_offset;
-               }
-       }
-
-       _broadcast_info->time_reference_high = (pos >> 32);
-       _broadcast_info->time_reference_low = (pos & 0xffffffff);
+       _broadcast_info->time_reference_high = (timeline_position >> 32);
+       _broadcast_info->time_reference_low = (timeline_position & 0xffffffff);
 
        if (sf_command (sf, SFC_SET_BROADCAST_INFO, _broadcast_info, sizeof (*_broadcast_info)) != SF_TRUE) {
                error << string_compose (_("cannot set broadcast info for audio file %1; Dropping broadcast info for this file"), _path) << endmsg;
@@ -545,3 +525,9 @@ SndFileSource::write_float (Sample* data, jack_nframes_t frame_pos, jack_nframes
        
        return cnt;
 }
+
+jack_nframes_t
+SndFileSource::natural_position() const
+{
+       return timeline_position;
+}
index 0d32ea4a216ec6134dbb93281819747bd24ec8c5..eebc64d46392a52804a9e36c02d28c8309d9499c 100644 (file)
@@ -45,7 +45,6 @@ using namespace ARDOUR;
 Source::Source (string name)
 {
        _name = name;
-       _id = ARDOUR::new_id();
        _use_cnt = 0;
        _timestamp = 0;
 }
@@ -71,7 +70,7 @@ Source::get_state ()
        char buf[64];
 
        node->add_property ("name", _name);
-       snprintf (buf, sizeof(buf)-1, "%" PRIu64, _id);
+       _id.print (buf);
        node->add_property ("id", buf);
 
        if (_timestamp != 0) {
@@ -94,7 +93,7 @@ Source::set_state (const XMLNode& node)
        }
        
        if ((prop = node.property ("id")) != 0) {
-               sscanf (prop->value().c_str(), "%" PRIu64, &_id);
+               _id = prop->value ();
        } else {
                return -1;
        }
diff --git a/libs/ardour/stateful.cc b/libs/ardour/stateful.cc
deleted file mode 100644 (file)
index b8e301b..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
-    Copyright (C) 2000-2001 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$
-*/
-
-#include <cstdio>
-#include <unistd.h>
-
-#include <ardour/stateful.h>
-#include <ardour/utils.h>
-#include <pbd/xml++.h>
-
-#include "i18n.h"
-
-using namespace PBD;
-
-Stateful::Stateful ()
-{
-       _extra_xml = 0;
-       _instant_xml = 0;
-}
-
-Stateful::~Stateful ()
-{
-       // Do not delete _extra_xml.  The use of add_child_nocopy() 
-       // means it needs to live on indefinately.
-       delete _instant_xml;
-}
-
-void
-Stateful::add_extra_xml (XMLNode& node)
-{
-       if (_extra_xml == 0) {
-               _extra_xml = new XMLNode ("extra");
-       }
-
-       _extra_xml->remove_nodes (node.name());
-       _extra_xml->add_child_nocopy (node);
-}
-
-XMLNode *
-Stateful::extra_xml (const string& str)
-{
-       if (_extra_xml == 0) {
-               return 0;
-       }
-
-       const XMLNodeList& nlist = _extra_xml->children();
-       XMLNodeConstIterator i;
-
-       for (i = nlist.begin(); i != nlist.end(); ++i) {
-               if ((*i)->name() == str) {
-                       return (*i);
-               }
-       }
-
-       return 0;
-}
-
-void
-Stateful::add_instant_xml (XMLNode& node, const string& dir)
-{
-       if (_instant_xml == 0) {
-               _instant_xml = new XMLNode ("instant");
-       }
-
-       _instant_xml->remove_nodes_and_delete (node.name());
-       _instant_xml->add_child_copy (node);
-       
-       XMLTree tree;
-       tree.set_filename(dir+"/instant.xml");
-
-       /* Important: the destructor for an XMLTree deletes
-          all of its nodes, starting at _root. We therefore
-          cannot simply hand it our persistent _instant_xml 
-          node as its _root, because we will lose it whenever
-          the Tree goes out of scope.
-
-          So instead, copy the _instant_xml node (which does 
-          a deep copy), and hand that to the tree.
-       */
-
-       XMLNode* copy = new XMLNode (*_instant_xml);
-       tree.set_root (copy);
-
-       if (!tree.write()) {
-               error << string_compose(_("Error: could not write %1"), dir+"/instant.xml") << endmsg;
-       }
-}
-
-XMLNode *
-Stateful::instant_xml (const string& str, const string& dir)
-{
-       if (_instant_xml == 0) {
-               string instant_file = dir + "/instant.xml";
-               if (access(instant_file.c_str(), F_OK) == 0) {
-                       XMLTree tree;
-                       if (tree.read(dir+"/instant.xml")) {
-                               _instant_xml = new XMLNode(*(tree.root()));
-                       } else {
-                               warning << string_compose(_("Could not understand XML file %1"), instant_file) << endmsg;
-                               return 0;
-                       }
-               } else {
-                       return 0;
-               }
-       }
-
-       const XMLNodeList& nlist = _instant_xml->children();
-       XMLNodeConstIterator i;
-
-       for (i = nlist.begin(); i != nlist.end(); ++i) {
-               if ((*i)->name() == str) {
-                       return (*i);
-               }
-       }
-
-       return 0;
-}
-
diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc
new file mode 100644 (file)
index 0000000..3b3b705
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+    Copyright (C) 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
+    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 <pbd/error.h>
+#include <sigc++/retype.h>
+#include <sigc++/retype_return.h>
+#include <sigc++/bind.h>
+
+#include <ardour/track.h>
+#include <ardour/diskstream.h>
+#include <ardour/session.h>
+#include <ardour/redirect.h>
+#include <ardour/audioregion.h>
+#include <ardour/audiosource.h>
+#include <ardour/route_group_specialized.h>
+#include <ardour/insert.h>
+#include <ardour/audioplaylist.h>
+#include <ardour/panner.h>
+#include <ardour/utils.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+
+Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type)
+       : Route (sess, name, 1, -1, -1, -1, flag, default_type)
+       , _diskstream (0)
+       ,  _rec_enable_control (*this)
+{
+       _declickable = true;
+       _freeze_record.state = NoFreeze;
+       _saved_meter_point = _meter_point;
+       _mode = mode;
+}
+
+Track::Track (Session& sess, const XMLNode& node, DataType default_type)
+       : Route (sess, "to be renamed", 0, 0, -1, -1, Route::Flag(0), default_type)
+       , _diskstream (0)
+       , _rec_enable_control (*this)
+{
+       _freeze_record.state = NoFreeze;
+       _declickable = true;
+       _saved_meter_point = _meter_point;
+}
+
+Track::~Track ()
+{
+       if (_diskstream) {
+               _diskstream->unref();
+       }
+}
+
+void
+Track::set_meter_point (MeterPoint p, void *src)
+{
+       Route::set_meter_point (p, src);
+}
+
+XMLNode&
+Track::get_state ()
+{
+       return state (true);
+}
+
+XMLNode&
+Track::get_template ()
+{
+       return state (false);
+}
+
+void
+Track::toggle_monitor_input ()
+{
+       for (vector<Port*>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
+               (*i)->request_monitor_input(!(*i)->monitoring_input());
+       }
+}
+
+jack_nframes_t
+Track::update_total_latency ()
+{
+       _own_latency = 0;
+
+       for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+               if ((*i)->active ()) {
+                       _own_latency += (*i)->latency ();
+               }
+       }
+
+       set_port_latency (_own_latency);
+
+       return _own_latency;
+}
+
+
+Track::FreezeRecord::~FreezeRecord ()
+{
+       for (vector<FreezeRecordInsertInfo*>::iterator i = insert_info.begin(); i != insert_info.end(); ++i) {
+               delete *i;
+       }
+}
+
+Track::FreezeState
+Track::freeze_state() const
+{
+       return _freeze_record.state;
+}
+
+Track::RecEnableControllable::RecEnableControllable (Track& s)
+       : track (s)
+{
+}
+
+void
+Track::RecEnableControllable::set_value (float val)
+{
+       bool bval = ((val >= 0.5f) ? true: false);
+       track.set_record_enable (bval, this);
+}
+
+float
+Track::RecEnableControllable::get_value (void) const
+{
+       if (track.record_enabled()) { return 1.0f; }
+       return 0.0f;
+}
+
+bool
+Track::record_enabled () const
+{
+       return _diskstream->record_enabled ();
+}
+       
+void
+Track::set_record_enable (bool yn, void *src)
+{
+       if (_freeze_record.state == Frozen) {
+               return;
+       }
+
+       if (_mix_group && src != _mix_group && _mix_group->is_active()) {
+               _mix_group->apply (&Track::set_record_enable, yn, _mix_group);
+               return;
+       }
+
+       /* keep track of the meter point as it was before we rec-enabled */
+
+       if (!_diskstream->record_enabled()) {
+               _saved_meter_point = _meter_point;
+       }
+       
+       _diskstream->set_record_enabled (yn);
+
+       if (_diskstream->record_enabled()) {
+               set_meter_point (MeterInput, this);
+       } else {
+               set_meter_point (_saved_meter_point, this);
+       }
+
+       _rec_enable_control.Changed ();
+}
+
+void
+Track::set_mode (TrackMode m)
+{
+       if (_diskstream) {
+               if (_mode != m) {
+                       _mode = m;
+                       _diskstream->set_destructive (m == Destructive);
+                       ModeChanged();
+               }
+       }
+}
+
+int
+Track::set_name (string str, void *src)
+{
+       int ret;
+
+       if (record_enabled() && _session.actively_recording()) {
+               /* this messes things up if done while recording */
+               return -1;
+       }
+
+       if (_diskstream->set_name (str)) {
+               return -1;
+       }
+
+       /* save state so that the statefile fully reflects any filename changes */
+
+       if ((ret = IO::set_name (str, src)) == 0) {
+               _session.save_state ("");
+       }
+       return ret;
+}
+
+void
+Track::set_latency_delay (jack_nframes_t longest_session_latency)
+{
+       Route::set_latency_delay (longest_session_latency);
+       _diskstream->set_roll_delay (_roll_delay);
+}
+
index 9adc7c72cd39f2cac11afc9f38634516570dec60..78e5572a3ddb20aa994a3fe6de687d488f9ab672 100644 (file)
@@ -186,15 +186,6 @@ touch_file (string path)
        return 1;
 }
 
-uint32_t long
-get_uid()
-{
-       struct timeval tv;
-       gettimeofday(&tv, 0);
-
-       return (uint32_t long) tv.tv_sec * 1000000 + tv.tv_usec;
-}
-
 string
 placement_as_string (Placement p)
 {
@@ -262,3 +253,21 @@ path_expand (string path)
 #endif
 }
 
+#ifdef HAVE_COREAUDIO
+string 
+CFStringRefToStdString(CFStringRef stringRef)
+{
+       CFIndex size = 
+               CFStringGetMaximumSizeForEncoding(CFStringGetLength(stringRef) , 
+               kCFStringEncodingUTF8);
+           char *buf = new char[size];
+       
+       std::string result;
+
+       if(CFStringGetCString(stringRef, buf, size, kCFStringEncodingUTF8)) {
+           result = buf;
+       }
+       delete [] buf;
+       return result;
+}
+#endif // HAVE_COREAUDIO
index 80c36dab950450ed48b6e423eff9d94934d1a63c..a551a15d280d346ef85cd6818491fb1ca8e076e7 100644 (file)
@@ -41,8 +41,6 @@
 
 #include <vst/aeffectx.h>
 
-#include <midi++/manager.h>
-
 #include <ardour/ardour.h>
 #include <ardour/session.h>
 #include <ardour/audioengine.h>
@@ -81,7 +79,7 @@ VSTPlugin::VSTPlugin (AudioEngine& e, Session& session, FSTHandle* h)
 
        _plugin->dispatcher (_plugin, effSetProgram, 0, 0, NULL, 0.0f);
        
-       Plugin::setup_midi_controls ();
+       Plugin::setup_controls ();
 }
 
 VSTPlugin::VSTPlugin (const VSTPlugin &other)
@@ -94,7 +92,7 @@ VSTPlugin::VSTPlugin (const VSTPlugin &other)
        }
        _plugin = _fst->plugin;
 
-       Plugin::setup_midi_controls ();
+       Plugin::setup_controls ();
 }
 
 VSTPlugin::~VSTPlugin ()
@@ -133,13 +131,6 @@ VSTPlugin::set_parameter (uint32_t which, float val)
 {
        _plugin->setParameter (_plugin, which, val);
        ParameterChanged (which, val); /* EMIT SIGNAL */
-
-       if (session().get_midi_feedback()) {
-               
-               if (which < parameter_count() && midi_controls[which]) {
-                       midi_controls[which]->send_feedback (val);
-               }
-       }
 }
 
 float
@@ -488,3 +479,31 @@ 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;
+
+                       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 (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 b70aea3d4096f9a84c00808f52f91d4e96ea0ddb..cf513eb5a1b7a77b05e099a576af12cc549f12a2 100644 (file)
@@ -9,8 +9,7 @@ Import('env final_prefix install_prefix libraries i18n')
 gtkmm2ext = env.Copy()
 gtkmm2ext.Merge ([ 
     libraries['sigc2'], 
-    libraries['pbd3'],
-    libraries['midi++2'],
+    libraries['pbd'],
     libraries['gtk2'],
     libraries['glibmm2'],
     libraries['pangomm'],
@@ -25,24 +24,25 @@ gtkmm2ext.Merge ([
 
 domain = 'libgtkmm2ext'
 
-gtkmm2ext.Append(DOMAIN=domain,MAJOR=0,MINOR=8,MICRO=2)
+gtkmm2ext.Append(DOMAIN=domain,MAJOR=0,MINOR=8,MICRO=3)
 gtkmm2ext.Append(CXXFLAGS="-DPACKAGE=\\\"" + domain + "\\\"")
 gtkmm2ext.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
+#gtkmm2ext.Append(CPPPATH='#libs/surfaces/control_protocol')
 gtkmm2ext.Append(PACKAGE=domain)
 gtkmm2ext.Append(POTFILE=domain + '.pot')
 
 gtkmm2ext_files = Split("""
 auto_spin.cc
 barcontroller.cc
-bindable_button.cc
+binding_proxy.cc
 choice.cc
 click_box.cc
-controller.cc
 dndtreeview.cc
 fastmeter.cc
 gtk_ui.cc
 hexentry.cc
 idle_adjustment.cc
+pathlist.cc
 pixscroller.cc
 popup.cc
 prompter.cc
index c977f3e5f79ac4edb980eaa6c1b414c5eaaa8638..eefe6ca843295125fc1fd33cb6d8266efc08718c 100644 (file)
@@ -23,7 +23,7 @@
 #include <cmath>
 #include <algorithm>
 
-#include <midi++/controllable.h>
+#include <pbd/controllable.h>
 
 #include <gtkmm2ext/gtk_ui.h>
 #include <gtkmm2ext/utils.h>
@@ -36,16 +36,13 @@ using namespace Gtk;
 using namespace Gtkmm2ext;
 
 BarController::BarController (Gtk::Adjustment& adj,
-                             MIDI::Controllable *mc,
+                             PBD::Controllable& mc,
                              sigc::slot<void,char*,unsigned int> lc) 
 
        : adjustment (adj),
-         prompter (Gtk::WIN_POS_MOUSE, 30000, false),
-         midi_control (mc),
+         binding_proxy (mc),
          label_callback (lc),
-         spinner (adjustment),
-         bind_button (2),
-         bind_statemask (Gdk::CONTROL_MASK)
+         spinner (adjustment)
 
 {                        
        _style = LeftToRight;
@@ -77,16 +74,6 @@ BarController::BarController (Gtk::Adjustment& adj,
        darea.signal_button_release_event().connect (mem_fun (*this, &BarController::button_release));
        darea.signal_scroll_event().connect (mem_fun (*this, &BarController::scroll));
 
-       prompter.signal_unmap_event().connect (mem_fun (*this, &BarController::prompter_hiding));
-       
-       prompting = false;
-       unprompting = false;
-       
-       if (mc) {
-               mc->learning_started.connect (mem_fun (*this, &BarController::midicontrol_prompt));
-               mc->learning_stopped.connect (mem_fun (*this, &BarController::midicontrol_unprompt));
-       }
-
        spinner.signal_activate().connect (mem_fun (*this, &BarController::entry_activated));
        spinner.signal_focus_out_event().connect (mem_fun (*this, &BarController::entry_focus_out));
        spinner.set_digits (3);
@@ -95,24 +82,13 @@ BarController::BarController (Gtk::Adjustment& adj,
        show_all ();
 }
 
-void
-BarController::set_bind_button_state (guint button, guint statemask)
-{
-       bind_button = button;
-       bind_statemask = statemask;
-}
-
-void
-BarController::get_bind_button_state (guint &button, guint &statemask)
-{
-       button = bind_button;
-       statemask = bind_statemask;
-}
-
-
 bool
 BarController::button_press (GdkEventButton* ev)
 {
+       if (binding_proxy.button_press_handler (ev)) {
+               return true;
+       }
+
        switch (ev->button) {
        case 1:
                if (ev->type == GDK_2BUTTON_PRESS) {
@@ -174,8 +150,8 @@ BarController::button_release (GdkEventButton* ev)
                break;
 
        case 2:
-               if ((ev->state & bind_statemask) && bind_button == 2) {
-                       midi_learn ();
+               if (true) { // XXX FIX ME
+                       /* relax */
                } else {
                        double fract;
                        fract = ev->x / (darea.get_width() - 2.0);
@@ -185,10 +161,6 @@ BarController::button_release (GdkEventButton* ev)
                return true;
 
        case 3:
-               if ((ev->state & bind_statemask) && bind_button == 3) {
-                       midi_learn ();
-                       return TRUE;
-               }
                return false;
                
        default:
@@ -407,61 +379,6 @@ BarController::set_with_text (bool yn)
        }
 }
 
-void
-BarController::midicontrol_set_tip ()
-{
-       if (midi_control) {
-               // Gtkmm2ext::UI::instance()->set_tip (&darea, midi_control->control_description());
-       }
-}
-
-void
-BarController::midi_learn()
-{
-       if (midi_control) {
-               prompting = true;
-               midi_control->learn_about_external_control ();
-       }
-}
-
-
-void
-BarController::midicontrol_prompt ()
-{
-       if (prompting) {
-               string prompt = _("operate MIDI controller now");
-               prompter.set_text (prompt);
-               Gtkmm2ext::UI::instance()->touch_display (&prompter);
-
-               unprompting = true;
-               prompting = false;
-       }
-}
-
-void
-BarController::midicontrol_unprompt ()
-{
-       if (unprompting) {
-               Gtkmm2ext::UI::instance()->touch_display (&prompter);
-               
-               unprompting = false;
-       }
-}
-
-gint
-BarController::prompter_hiding (GdkEventAny *ev)
-{
-       if (unprompting) {
-               if (midi_control) {
-                       midi_control->stop_learning();
-               }
-               unprompting = false;
-       }
-       
-       return FALSE;
-}
-
-
 void
 BarController::set_style (Style s)
 {
diff --git a/libs/gtkmm2ext/binding_proxy.cc b/libs/gtkmm2ext/binding_proxy.cc
new file mode 100644 (file)
index 0000000..3a2f5bb
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+    Copyright (C) 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
+    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$
+*/
+
+#include <string>
+#include <climits>
+#include <iostream>
+
+#include <pbd/controllable.h>
+
+#include <gtkmm2ext/binding_proxy.h>
+
+#include "i18n.h"
+
+using namespace Gtkmm2ext;
+using namespace std;
+using namespace PBD;
+
+BindingProxy::BindingProxy (Controllable& c)
+       : prompter (Gtk::WIN_POS_MOUSE, 30000, false),
+         controllable (c),
+         bind_button (2),
+         bind_statemask (Gdk::CONTROL_MASK)
+
+{                        
+       prompter.signal_unmap_event().connect (mem_fun (*this, &BindingProxy::prompter_hiding));
+}
+
+void
+BindingProxy::set_bind_button_state (guint button, guint statemask)
+{
+       bind_button = button;
+       bind_statemask = statemask;
+}
+
+void
+BindingProxy::get_bind_button_state (guint &button, guint &statemask)
+{
+       button = bind_button;
+       statemask = bind_statemask;
+}
+
+bool
+BindingProxy::button_press_handler (GdkEventButton *ev)
+{
+       if ((ev->state & bind_statemask) && ev->button == bind_button) { 
+               if (Controllable::StartLearning (&controllable)) {
+                       string prompt = _("operate controller now");
+                       prompter.set_text (prompt);
+                       prompter.touch (); // shows popup
+                       learning_connection = controllable.LearningFinished.connect (mem_fun (*this, &BindingProxy::learning_finished));
+               }
+               return true;
+       }
+       
+       return false;
+}
+
+void
+BindingProxy::learning_finished ()
+{
+       learning_connection.disconnect ();
+       prompter.touch (); // hides popup
+}
+
+
+bool
+BindingProxy::prompter_hiding (GdkEventAny *ev)
+{
+       learning_connection.disconnect ();
+       Controllable::StopLearning (&controllable);
+       return false;
+}
+
diff --git a/libs/gtkmm2ext/controller.cc b/libs/gtkmm2ext/controller.cc
deleted file mode 100644 (file)
index 98d5566..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-    Copyright (C) 1998-99 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$
-*/
-
-#include <string>
-#include <climits>
-
-#include <midi++/channel.h>
-#include <gtkmm2ext/gtk_ui.h>
-#include <gtkmm2ext/controller.h>
-
-#include "i18n.h"
-
-using namespace Gtkmm2ext;
-
-Controller::Controller (Gtk::Adjustment *adj, MIDI::Port *p)
-       : MIDI::Controllable (p),
-         adjustment (adj),
-         prompter (Gtk::WIN_POS_MOUSE, 30000, false)
-{
-       new_value_pending = false;
-
-       /* hear about MIDI control learning */
-
-       learning_started.connect 
-               (mem_fun (*this, &Controller::midicontrol_prompt));
-       learning_stopped.connect 
-               (mem_fun (*this, &Controller::midicontrol_unprompt));
-}
-
-void
-Controller::midicontrol_prompt ()
-
-{
-       string prompt = _("operate MIDI controller now");
-
-       prompter.set_text (prompt);
-       Gtkmm2ext::UI::instance()->touch_display (&prompter);
-}
-
-void
-Controller::midicontrol_unprompt ()
-
-{
-       Gtkmm2ext::UI::instance()->touch_display (&prompter);
-}
-
-int
-Controller::update_controller_value (void *arg)
-
-{
-       Controller *c = (Controller *) arg;
-
-       c->adjustment->set_value (c->new_value);
-       c->new_value_pending = false;
-
-       return FALSE;
-}
-
-void
-Controller::set_value (float v)
-
-{
-       /* This is called from a MIDI callback. It could happen
-          a thousand times a second, or more. Therefore, instead
-          of going straight to the X server, which may not work for
-          thread-related reasons, simply request an update whenever
-          the GTK main loop is idle.
-       */
-       
-       new_value = v;
-
-       if (!new_value_pending) {
-               new_value_pending = true;
-               Gtkmm2ext::UI::instance()->idle_add (update_controller_value, this);
-       }
-}
index 67c8221a55ba15771043971a16a167851978fa7f..ebce4e2de925e79192a0f6eac8d4149dfb14afa4 100644 (file)
@@ -21,9 +21,9 @@
 #define __gtkmm2ext_bar_controller_h__
 
 #include <gtkmm.h>
-#include <gtkmm2ext/popup.h>
+#include <gtkmm2ext/binding_proxy.h>
 
-namespace MIDI {
+namespace ARDOUR {
        class Controllable;
 }
 
@@ -32,14 +32,9 @@ namespace Gtkmm2ext {
 class BarController : public Gtk::Frame
 {
   public:
-       BarController (Gtk::Adjustment& adj, MIDI::Controllable*, sigc::slot<void,char*,unsigned int>);
+       BarController (Gtk::Adjustment& adj, PBD::Controllable&, sigc::slot<void,char*,unsigned int>);
        virtual ~BarController () {}
        
-       void set_bind_button_state (guint button, guint statemask);
-       void get_bind_button_state (guint &button, guint &statemask);
-       void midicontrol_set_tip ();
-       void midi_learn ();
-
        void set_sensitive (bool yn) {
                darea.set_sensitive (yn);
        }
@@ -69,9 +64,8 @@ class BarController : public Gtk::Frame
 
   protected:
        Gtk::Adjustment&    adjustment;
+       BindingProxy        binding_proxy;
        Gtk::DrawingArea    darea;
-       Gtkmm2ext::PopUp     prompter;
-       MIDI::Controllable* midi_control;
        sigc::slot<void,char*,unsigned int> label_callback;
        Glib::RefPtr<Pango::Layout> layout;
        Style              _style;
@@ -85,10 +79,6 @@ class BarController : public Gtk::Frame
        Gtk::SpinButton     spinner;
        bool                use_parent;
 
-       guint bind_button;
-       guint bind_statemask;
-       bool prompting, unprompting;
-       
        bool button_press (GdkEventButton *);
        bool button_release (GdkEventButton *);
        bool motion (GdkEventMotion *);
@@ -98,11 +88,6 @@ class BarController : public Gtk::Frame
 
        gint mouse_control (double x, GdkWindow* w, double scaling);
 
-       gint prompter_hiding (GdkEventAny *);
-       void midicontrol_prompt ();
-       void midicontrol_unprompt ();
-       void update_midi_control ();
-
        gint switch_to_bar ();
        gint switch_to_spinner ();
 
index 7400cf15d092416362d76a8f9f4f9a549961037a..193612540551db5d4873cc4d4aa6b2a56df82f91 100644 (file)
     $Id$
 */
 
-#ifndef __pbd_gtkmm_bindable_button_h__
-#define __pbd_gtkmm_bindable_button_h__
+#ifndef __bindable_button_h__
+#define __bindable_button_h__
 
 #include <string>
 
 #include <gtkmm2ext/stateful_button.h>
-#include <gtkmm2ext/popup.h>
+#include "binding_proxy.h"
 
-namespace MIDI {
+namespace PBD {
        class Controllable;
 }
 
-namespace Gtkmm2ext {
-
 class BindableToggleButton : public Gtk::ToggleButton
 {
    public:
-       BindableToggleButton(MIDI::Controllable *);
-
-       //: Create a check button with a label.
-       //- You won't be able
-       //- to add a widget in this button since it already has a {\class Gtk_Label}
-       //- in it.
-       explicit BindableToggleButton(MIDI::Controllable *, const std::string &label);
-
+       BindableToggleButton (PBD::Controllable& c) : binding_proxy (c) {}
+       explicit BindableToggleButton (PBD::Controllable& c, const std::string &label) : Gtk::ToggleButton (label), binding_proxy (c) {}
        virtual ~BindableToggleButton() {}
        
-       void set_bind_button_state (guint button, guint statemask);
-       void get_bind_button_state (guint &button, guint &statemask);
-       
-       void midicontrol_set_tip ();
-
-       void midi_learn ();
-       
-  protected:
-
-       Gtkmm2ext::PopUp     prompter;
-       
-       MIDI::Controllable* midi_control;
-
-       guint bind_button;
-       guint bind_statemask;
-
-       bool prompting, unprompting;
-       
-       void init_events ();
-       bool prompter_hiding (GdkEventAny *);
-       void midicontrol_prompt ();
-       void midicontrol_unprompt ();
-       
-       bool on_button_press_event (GdkEventButton *);
-};
+       bool on_button_press_event (GdkEventButton *ev) {
+               return binding_proxy.button_press_handler (ev);
+       }
 
+  private:
+       BindingProxy binding_proxy;
 };
 
 #endif
diff --git a/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h b/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h
new file mode 100644 (file)
index 0000000..a26c8ac
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+    Copyright (C) 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
+    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$
+*/
+
+#ifndef __binding_proxy__
+#define __binding_proxy__
+
+#include <string>
+
+#include <gtkmm2ext/popup.h>
+
+namespace PBD {
+       class Controllable;
+}
+
+class BindingProxy : public sigc::trackable
+{
+   public:
+       BindingProxy (PBD::Controllable&);
+       virtual ~BindingProxy() {}
+       
+       void set_bind_button_state (guint button, guint statemask);
+       void get_bind_button_state (guint &button, guint &statemask);
+
+       bool button_press_handler (GdkEventButton *);
+
+  protected:
+
+       Gtkmm2ext::PopUp     prompter;
+       PBD::Controllable& controllable;
+       guint bind_button;
+       guint bind_statemask;
+       sigc::connection learning_connection;
+       void learning_finished ();
+       bool prompter_hiding (GdkEventAny *);
+};
+
+#endif
diff --git a/libs/gtkmm2ext/gtkmm2ext/controller.h b/libs/gtkmm2ext/gtkmm2ext/controller.h
deleted file mode 100644 (file)
index b72f6c7..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-    Copyright (C) 1998-99 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$
-*/
-
-#ifndef __gtkmm2ext_controller_h__
-#define __gtkmm2ext_controller_h__
-
-#include <gtkmm.h>
-#include <gtkmm2ext/popup.h>
-#include <midi++/controllable.h>
-
-namespace Gtkmm2ext {
-
-class Controller : public MIDI::Controllable
-
-{
-  public:
-       Controller (Gtk::Adjustment *, MIDI::Port *);
-        virtual ~Controller () {}
-       
-       void set_value (float);
-       float lower () { return adjustment->get_lower(); }
-       float upper () { return adjustment->get_upper(); }
-       float range () { return upper() - lower() /* XXX +1 ??? */ ; }
-
-       void midicontrol_prompt ();
-       void midicontrol_unprompt ();
-
-  protected:
-       Gtk::Adjustment *adjustment;
-
-  private:
-       Gtkmm2ext::PopUp prompter;
-       gfloat new_value;
-       bool new_value_pending;
-
-       static gint update_controller_value (void *);
-};
-
-}; /* namespace */
-
-#endif // __gtkmm2ext_controller_h__           
-
-
diff --git a/libs/gtkmm2ext/gtkmm2ext/pathlist.h b/libs/gtkmm2ext/gtkmm2ext/pathlist.h
new file mode 100644 (file)
index 0000000..f4a5973
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+    Copyright (C) 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
+    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.
+
+*/
+
+#ifndef __gtkmm2ext_pathlist_h__
+#define __gtkmm2ext_pathlist_h__
+
+#include <vector>
+#include <string>
+
+#include <gtkmm.h>
+
+namespace Gtkmm2ext {
+
+class PathList : public Gtk::VBox
+{
+  public:
+       PathList ();
+       ~PathList () {};
+               
+       std::vector<std::string> get_paths ();
+       void set_paths (std::vector<std::string> paths);
+       
+       sigc::signal<void> PathsUpdated;
+       
+  protected:
+       Gtk::Button    add_btn;
+       Gtk::Button    subtract_btn;
+
+       void add_btn_clicked ();
+       void subtract_btn_clicked ();
+
+  private:
+       struct PathColumns : public Gtk::TreeModel::ColumnRecord {
+               PathColumns() { add (paths); }
+               Gtk::TreeModelColumn<std::string> paths;
+       };
+       PathColumns path_columns;
+       
+       Glib::RefPtr<Gtk::ListStore> _store;
+       Gtk::TreeView  _view;
+       
+       void selection_changed ();
+};
+
+} // namespace Gtkmm2ext
+
+#endif // __gtkmm2ext_pathlist_h__
index 7abaf285d197d28f0c06b0e4312aef2df896b9c7..f0f645eab7502b402c77344074aa378fb46efd17 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 1998-99 Paul Davis 
+    Copyright (C) 1998-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
     the Free Software Foundation; either version 2 of the License, or
     $Id$
 */
 
-#ifndef __gtkmm2ext_motion_controller_h__
-#define __gtkmm2ext_motion_controller_h__
+#ifndef __gtkmm2ext_slider_controller_h__
+#define __gtkmm2ext_slider_controller_h__
 
 #include <gtkmm.h>
 #include <gtkmm2ext/popup.h>
 #include <gtkmm2ext/pixscroller.h>
+#include <gtkmm2ext/binding_proxy.h>
 
 namespace Gtkmm2ext {
        class Pix;
 }
 
-namespace MIDI {
+namespace PBD {
        class Controllable;
 }
 
@@ -40,41 +41,24 @@ class SliderController : public Gtkmm2ext::PixScroller
        SliderController (Glib::RefPtr<Gdk::Pixbuf> slider,
                          Glib::RefPtr<Gdk::Pixbuf> rail,
                          Gtk::Adjustment* adj,
-                         MIDI::Controllable*,
+                         PBD::Controllable&,
                          bool with_numeric = true);
 
         virtual ~SliderController () {}
 
-       void set_bind_button_state (guint button, guint statemask);
-       void get_bind_button_state (guint &button, guint &statemask);
-       void midicontrol_set_tip ();
-       void midi_learn ();
-       
        void set_value (float);
-       // void set_sensitive (bool yn) {
-       // spin.set_sensitive (yn);
-       // }
 
-       Gtk::SpinButton & get_spin_button () { return spin; }
+       Gtk::SpinButton& get_spin_button () { return spin; }
        
+       bool on_button_press_event (GdkEventButton *ev);
+
   protected:
+       BindingProxy binding_proxy;
        Glib::RefPtr<Gdk::Pixbuf> slider;
        Glib::RefPtr<Gdk::Pixbuf> rail;
        Gtk::SpinButton     spin;
        Gtk::Frame          spin_frame;
        Gtk::HBox           spin_hbox;
-       Gtkmm2ext::PopUp     prompter;
-       MIDI::Controllable* midi_control;
-
-       guint bind_button;
-       guint bind_statemask;
-       bool prompting, unprompting;
-       
-       bool button_press (GdkEventButton *);
-       bool prompter_hiding (GdkEventAny *);
-       void midicontrol_prompt ();
-       void midicontrol_unprompt ();
-       void update_midi_control ();
 };
 
 class VSliderController : public SliderController
@@ -83,7 +67,7 @@ class VSliderController : public SliderController
        VSliderController (Glib::RefPtr<Gdk::Pixbuf> slider,
                           Glib::RefPtr<Gdk::Pixbuf> rail,
                           Gtk::Adjustment *adj,
-                          MIDI::Controllable *,
+                          PBD::Controllable&,
                           bool with_numeric = true);
 };
 
@@ -93,11 +77,11 @@ class HSliderController : public SliderController
        HSliderController (Glib::RefPtr<Gdk::Pixbuf> slider,
                           Glib::RefPtr<Gdk::Pixbuf> rail,
                           Gtk::Adjustment *adj,
-                          MIDI::Controllable *,
+                          PBD::Controllable&,
                           bool with_numeric = true);
 };
 
 
 }; /* namespace */
 
-#endif // __gtkmm2ext_motion_controller_h__            
+#endif // __gtkmm2ext_slider_controller_h__            
diff --git a/libs/gtkmm2ext/pathlist.cc b/libs/gtkmm2ext/pathlist.cc
new file mode 100644 (file)
index 0000000..7b3448e
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+    Copyright (C) 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
+    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 <gtkmm2ext/pathlist.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace Gtkmm2ext;
+
+PathList::PathList ()
+       :
+       add_btn(_("+")),
+       subtract_btn(_("-")),
+       path_columns(),
+       _store(Gtk::ListStore::create(path_columns)),
+       _view(_store)
+{
+       _view.append_column(_("Paths"), path_columns.paths);
+       _view.set_size_request(-1, 100);
+       _view.set_headers_visible (false);
+       
+       Gtk::ScrolledWindow* scroll = manage(new Gtk::ScrolledWindow);
+       scroll->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+       scroll->add(_view);
+       
+       add (*scroll);
+       
+       Gtk::HBox* btn_box = manage(new Gtk::HBox);
+       btn_box->add(add_btn);
+       btn_box->add(subtract_btn);
+
+       add (*btn_box);
+       
+       add_btn.signal_clicked().connect (mem_fun(*this, &PathList::add_btn_clicked));
+       subtract_btn.signal_clicked().connect (mem_fun(*this, &PathList::subtract_btn_clicked));
+       _view.get_selection()->signal_changed().connect (mem_fun(*this, &PathList::selection_changed));
+}
+
+vector<string>
+PathList::get_paths ()
+{
+       vector<string> paths;
+       
+       Gtk::TreeModel::Children children(_store->children());
+       
+       for (Gtk::TreeIter iter = children.begin(); iter != children.end(); ++iter) {
+               Gtk::ListStore::Row row = *iter;
+               
+               paths.push_back(row[path_columns.paths]);
+       }
+       
+       return paths;
+}
+
+void
+PathList::set_paths (vector<string> paths)
+{
+       _store->clear();
+       
+       for (vector<string>::iterator i = paths.begin(); i != paths.end(); ++i) {
+               Gtk::ListStore::iterator iter = _store->append();
+               Gtk::ListStore::Row row = *iter;
+               row[path_columns.paths] = *i;
+       }
+}
+
+void
+PathList::add_btn_clicked ()
+{
+       Gtk::FileChooserDialog path_chooser (_("Path Chooser"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
+       
+       path_chooser.add_button (Gtk::Stock::ADD, Gtk::RESPONSE_OK);
+       path_chooser.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+       
+       int result = path_chooser.run ();
+       
+       if (result == Gtk::RESPONSE_OK) {
+               string pathname = path_chooser.get_filename();
+               
+               if (pathname.length ()) {
+                       Gtk::ListStore::iterator iter = _store->append ();
+                       Gtk::ListStore::Row row = *iter;
+                       row[path_columns.paths] = pathname;
+                       
+                       PathsUpdated (); // EMIT_SIGNAL
+               }
+       }
+}
+
+void
+PathList::subtract_btn_clicked ()
+{
+       Gtk::ListStore::iterator iter = _view.get_selection()->get_selected();
+       _store->erase (iter);
+       
+       PathsUpdated (); // EMIT_SIGNAL
+}
+
+void
+PathList::selection_changed ()
+{
+       if (_view.get_selection()->count_selected_rows ()) {
+               subtract_btn.set_sensitive (true);
+       } else {
+               subtract_btn.set_sensitive (false);
+       }
+}
index 0a48ebfc594ce551cb85e1b84b3ed6aeb05549ba..a8ffc4af669526baaca8ec481899d5dc36e6a842 100644 (file)
@@ -73,11 +73,12 @@ PopUp::remove ()
 {
        hide ();
 
+       if (popdown_time != 0 && timeout != -1) {
+               gtk_timeout_remove (timeout);
+       }
+
        if (delete_on_hide) {
                std::cerr << "deleting prompter\n";
-               if (popdown_time != 0 && timeout != -1) {
-                       gtk_timeout_remove (timeout);
-               }
                gtk_idle_add (idle_delete, this);
        }
 }
@@ -125,11 +126,12 @@ PopUp::on_delete_event (GdkEventAny* ev)
 {
        hide();
 
+       if (popdown_time != 0 && timeout != -1) {
+               gtk_timeout_remove (timeout);
+       }       
+
        if (delete_on_hide) {
                std::cerr << "deleting prompter\n" << endl;
-               if (popdown_time != 0 && timeout != -1) {
-                       gtk_timeout_remove (timeout);
-               }
                gtk_idle_add (idle_delete, this);
        }
 
index 734d5eb62f41721b83e36f832c6c734878407c7f..e524eba1cbd4bdd57010351bf3a10bf2feee1e5c 100644 (file)
 */
 
 #include <string>
-#include <climits>
-
-#include <midi++/controllable.h>
 
 #include <gtkmm2ext/gtk_ui.h>
-#include <gtkmm2ext/slider_controller.h>
 #include <gtkmm2ext/pixscroller.h>
+#include <gtkmm2ext/slider_controller.h>
 
 #include "i18n.h"
 
 using namespace Gtkmm2ext;
+using namespace PBD;
 
 SliderController::SliderController (Glib::RefPtr<Gdk::Pixbuf> slide,
                                    Glib::RefPtr<Gdk::Pixbuf> rail,
                                    Gtk::Adjustment *adj,
-                                   MIDI::Controllable *mc,
+                                   Controllable& c,
                                    bool with_numeric)
 
        : PixScroller (*adj, slide, rail),
-         spin (*adj, 0, 2),
-         prompter (Gtk::WIN_POS_MOUSE, 30000, false),
-         midi_control (mc),
-         bind_button (2),
-         bind_statemask (Gdk::CONTROL_MASK)
-
+         binding_proxy (c),
+         spin (*adj, 0, 2)
 {                        
-       signal_button_press_event().connect (mem_fun (this, &SliderController::button_press));
        spin.set_name ("SliderControllerValue");
        spin.set_size_request (70,-1); // should be based on font size somehow
        spin.set_numeric (true);
        spin.set_snap_to_ticks (false);
-
-       prompter.signal_unmap_event().connect (mem_fun (*this, &SliderController::prompter_hiding));
-       
-       prompting = false;
-       unprompting = false;
-       
-       if (mc) {
-               mc->learning_started.connect (mem_fun (*this, &SliderController::midicontrol_prompt));
-               mc->learning_stopped.connect (mem_fun (*this, &SliderController::midicontrol_unprompt));
-       }
 }
 
 void
@@ -67,95 +50,22 @@ SliderController::set_value (float v)
        adj.set_value (v);
 }
 
-void
-SliderController::set_bind_button_state (guint button, guint statemask)
-{
-       bind_button = button;
-       bind_statemask = statemask;
-}
-
-void
-SliderController::get_bind_button_state (guint &button, guint &statemask)
-{
-       button = bind_button;
-       statemask = bind_statemask;
-}
-
-void
-SliderController::midi_learn()
-{
-       if (midi_control) {
-               prompting = true;
-               midi_control->learn_about_external_control ();
-       }
-}
-
-bool
-SliderController::button_press (GdkEventButton *ev)
+bool 
+SliderController::on_button_press_event (GdkEventButton *ev) 
 {
-       if ((ev->state & bind_statemask) && ev->button == bind_button) { 
-               midi_learn ();
+       if (binding_proxy.button_press_handler (ev)) {
                return true;
        }
-
-       return false;
-}
-
-void
-SliderController::midicontrol_set_tip ()
-
-{
-       if (midi_control) {
-               // Gtkmm2ext::UI::instance()->set_tip (this, midi_control->control_description());
-       }
-}
-
-bool
-SliderController::prompter_hiding (GdkEventAny *ev)
-{
-       if (unprompting) {
-               if (midi_control) {
-                       midi_control->stop_learning();
-               }
-               unprompting = false;
-       }
-       
-       return false;
-}
-
-void
-SliderController::midicontrol_prompt ()
-
-{
-       if (prompting) {
-
-               string prompt = _("operate MIDI controller now");
-               prompter.set_text (prompt);
-               Gtkmm2ext::UI::instance()->touch_display (&prompter);
-
-               unprompting = true;
-               prompting = false;
-       }
-}
-
-void
-SliderController::midicontrol_unprompt ()
-
-{
-       if (unprompting) {
-               Gtkmm2ext::UI::instance()->touch_display (&prompter);
-               unprompting = false;
-       }
+       return PixScroller::on_button_press_event (ev);
 }
 
-
 VSliderController::VSliderController (Glib::RefPtr<Gdk::Pixbuf> slide,
                                      Glib::RefPtr<Gdk::Pixbuf> rail,
                                      Gtk::Adjustment *adj,
-                                     MIDI::Controllable *mcontrol,
+                                     Controllable& control,
                                      bool with_numeric)
 
-       : SliderController (slide, rail, adj, mcontrol, with_numeric)
+       : SliderController (slide, rail, adj, control, with_numeric)
 {
        if (with_numeric) {
                spin_frame.add (spin);
@@ -169,10 +79,10 @@ VSliderController::VSliderController (Glib::RefPtr<Gdk::Pixbuf> slide,
 HSliderController::HSliderController (Glib::RefPtr<Gdk::Pixbuf> slide,
                                      Glib::RefPtr<Gdk::Pixbuf> rail,
                                      Gtk::Adjustment *adj,
-                                     MIDI::Controllable *mcontrol,
+                                     Controllable& control,
                                      bool with_numeric)
        
-       : SliderController (slide, rail, adj, mcontrol, with_numeric)
+       : SliderController (slide, rail, adj, control, with_numeric)
 {
        if (with_numeric) {
                spin_frame.add (spin);
index 1d5f3e0050874464dc004c9678ab4d2221b2dd88..d9620dc378eb597429f47f7ca15d6653c47cb153 100644 (file)
@@ -8,7 +8,14 @@ gnomecanvasmm_files = glob.glob('libgnomecanvasmm/*.cc')
 
 Import('env libraries install_prefix')
 gnomecanvasmm = env.Copy()
-gnomecanvasmm.Merge([libraries['glibmm2'], libraries['gtk2'], libraries['sigc2'], libraries['pangomm'], libraries['atkmm'], libraries['gdkmm2'], libraries['gtkmm2'], libraries['libgnomecanvas2'] ])
+gnomecanvasmm.Merge([libraries['glibmm2'],
+                     libraries['gtk2'],
+                     libraries['sigc2'],
+                     libraries['pangomm'],
+                     libraries['atkmm'],
+                     libraries['gdkmm2'],
+                     libraries['gtkmm2'],
+                     libraries['libgnomecanvas2'] ])
 
 libgnomecanvasmm = gnomecanvasmm.SharedLibrary('libgnomecanvasmm', gnomecanvasmm_files)
 Default(libgnomecanvasmm)
index 47b74cfd7fc5b4d77be68b8f0c17e93a9947bc03..14586526e4bc705fb9b874b0a08c406f3439ca7d 100644 (file)
@@ -1065,20 +1065,19 @@ sf_command      (SNDFILE *sndfile, int command, void *data, int datasize)
                        memcpy (data, psf->loop_info, sizeof (SF_LOOP_INFO)) ;
                        return SF_TRUE ;
 
-               case SFC_SET_BROADCAST_INFO :
-                       {       int format = psf->sf.format & SF_FORMAT_TYPEMASK ;
+               case SFC_SET_BROADCAST_INFO : {
+                       int format = psf->sf.format & SF_FORMAT_TYPEMASK ;
 
-                               /* Only WAV supports the BEXT (Broadcast) chunk. */
-                               if (format != SF_FORMAT_WAV && format != SF_FORMAT_WAVEX) 
-                                       return SF_FALSE ;
-                                } ;
+                       /* Only WAV supports the BEXT (Broadcast) chunk. */
+                       if (format != SF_FORMAT_WAV && format != SF_FORMAT_WAVEX)
+                               return SF_FALSE ;
 
                        /* Can only do this is in SFM_RDWR or SFM_WRITE modes. */
                        if (psf->mode == SFM_READ)
                                return SF_FALSE ;
 
                        /* If data has already been written this must fail. */
-                       if (psf->broadcast_info == NULL && psf->have_written) 
+                       if (psf->broadcast_info == NULL && psf->have_written)
                                return SF_FALSE ;
 
                        if (psf->broadcast_info == NULL)
@@ -1089,7 +1088,9 @@ sf_command        (SNDFILE *sndfile, int command, void *data, int datasize)
 
                        if (psf->auto_header && psf->write_header)
                                psf->write_header (psf, SF_TRUE) ;
+
                        return SF_TRUE ;
+               }
 
                case SFC_GET_BROADCAST_INFO :
                        if (datasize != sizeof (SF_BROADCAST_INFO) || data == NULL)
index 928372909cc51708f2114533a84922ab52d3ea82..696fed6b5be003930bd0ba2b4f6748e497afc409 100644 (file)
@@ -7,7 +7,7 @@ import glob
 Import('env libraries install_prefix')
 
 midi2 = env.Copy()
-midi2.Merge([ libraries['sigc2'], libraries['xml'], libraries['glib2'], libraries['pbd3'] ])
+midi2.Merge([ libraries['sigc2'], libraries['xml'], libraries['glib2'], libraries['pbd'] ])
 
 domain = 'midipp'
 
@@ -18,7 +18,6 @@ fd_midiport.cc
 fifomidi.cc
 midi.cc
 midichannel.cc
-midicontrollable.cc
 midifactory.cc
 midimanager.cc
 midiparser.cc
index 1efde3cb93d5e13c2e8099f608484ea36bcc2d08..f8dbb6e194381348350d4941723fecc5eb7a3af3 100644 (file)
@@ -152,7 +152,7 @@ class Channel : public sigc::trackable {
        void process_reset (Parser &);
 };
 
-}; /* namespace MIDI */
+} // namespace MIDI
 
 #endif // __midichannel_h__
 
diff --git a/libs/midi++2/midi++/controllable.h b/libs/midi++2/midi++/controllable.h
deleted file mode 100644 (file)
index 3fa108b..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#ifndef __qm_midicontrollable_h__
-#define __qm_midicontrollable_h__
-
-#include <string>
-
-#include <sigc++/sigc++.h>
-
-#include <midi++/types.h>
-
-namespace MIDI {
-
-class Channel;
-class Port;
-class Parser;
-
-class Controllable : public sigc::trackable
-{
-  public:
-       Controllable (Port *, bool bistate = false);
-       virtual ~Controllable ();
-
-       void midi_rebind (Port *, channel_t channel=-1);
-       void midi_forget ();
-       void learn_about_external_control ();
-       void stop_learning ();
-       void drop_external_control ();
-
-       virtual void set_value (float) = 0;
-
-       sigc::signal<void> learning_started;
-       sigc::signal<void> learning_stopped;
-
-       bool get_control_info (channel_t&, eventType&, byte&);
-       void set_control_type (channel_t, eventType, byte);
-
-       bool get_midi_feedback () { return feedback; }
-       void set_midi_feedback (bool val) { feedback = val; }
-
-       Port * get_port() { return port; }
-       
-       std::string control_description() const { return _control_description; }
-
-       void send_midi_feedback (float);
-       
-  private:
-       bool             bistate;
-       int              midi_msg_id;      /* controller ID or note number */
-       sigc::connection midi_sense_connection[2];
-       sigc::connection midi_learn_connection;
-       size_t           connections;
-       Port*            port;
-       eventType        control_type;
-       byte             control_additional;
-       channel_t        control_channel;
-       std::string     _control_description;
-       bool             feedback;
-       
-       void midi_receiver (Parser &p, byte *, size_t);
-       void midi_sense_note (Parser &, EventTwoBytes *, bool is_on);
-       void midi_sense_note_on (Parser &p, EventTwoBytes *tb);
-       void midi_sense_note_off (Parser &p, EventTwoBytes *tb);
-       void midi_sense_controller (Parser &, EventTwoBytes *);
-       void midi_sense_program_change (Parser &, byte);
-       void midi_sense_pitchbend (Parser &, pitchbend_t);
-
-       void bind_midi (channel_t, eventType, byte);
-};
-
-}; /* namespace MIDI */
-
-#endif // __qm_midicontrollable_h__
-
index e02a22578492cf34d34c19b80bd0a6d1c92910b7..d7df23aa0400ed2d7cec2de49e9355803292c458 100644 (file)
@@ -62,6 +62,6 @@ namespace MIDI {
        bool firstrecv;
     };
 
-}; /* namespace MIDI */
+} // namespace MIDI
 
 #endif // __coremidi_midiport_h__
index 1543f68cdc7c7dbbc78afc66eee6ab71847fdc48..7b4122d7911c288cf39f1b2f8e027a3ef950b3de 100644 (file)
@@ -35,6 +35,6 @@ class PortFactory {
                                      const std::string &reqstr);
 };
 
-}; /* namespace MIDI */
+} // namespace MIDI
 
 #endif // __midi_factory_h__
index 853af9d7b4eb7507750f24b9f6fc8f2e5c866954..6a9b8f74d16e4d2f6a1f13426ae57997a6613ef6 100644 (file)
@@ -89,6 +89,6 @@ class FD_MidiPort : public Port
        int do_slow_write (byte *msg, unsigned int msglen);
 };
 
-}; /*namespace MIDI */
+} // namespace MIDI
 
 #endif  // __fd_midiport_h__
index eb8778d4d5b427f63c27897cb7d32965e337c563..200d90eda8da21b59bc343366febb57c11e46217 100644 (file)
@@ -42,6 +42,6 @@ class FIFO_MidiPort : public MIDI::FD_MidiPort
        void open (PortRequest &req);
 };
 
-}; /* namespace MIDI */
+} // namespace MIDI
 
 #endif // __fifomidi_h__
index 4889aad8c92bb6e4c0d312ebd79c5fb854debe07..1bf8dc7cbd0317043cb28e8939a11114ac2ff1d8 100644 (file)
@@ -83,6 +83,6 @@ class Manager {
        void close_ports ();
 };
 
-}; /* namespace MIDI */
+} // namespace MIDI
 
 #endif  // __midi_manager_h__
index 7b51b33a7286920f778fda97bb34fc8a74fd5668..2d569f122c1bc141b80ce96fb2d27c75d9f7de2e 100644 (file)
@@ -82,7 +82,7 @@ class MachineControl : public sigc::trackable
                cmdRecordStrobeVariable = 0x55,
 
                cmdWait = 0x7C,
-               cmdResume = 0x7F,
+               cmdResume = 0x7F
        };
        
        MachineControl (Port &port,
@@ -256,6 +256,6 @@ class MachineControl : public sigc::trackable
        void write_track_record_ready (byte *, size_t len);
 };
 
-}; /* namespace MIDI */        
+} // namespace MIDI
 
 #endif /* __midipp_mmc_h_h__ */
index a94b1015b092df417d27ae83c2bb95c80b207bec..a74e5e3d9b98821c49e180dc32eb82cb03e50f9e 100644 (file)
@@ -57,6 +57,6 @@ class Null_MidiPort : public Port
        virtual int selectable() const { return -1; }
 };
 
-}; /* namespace MIDI */
+} // namespace MIDI
 
 #endif // __nullmidi_h__
index 4ac07cc15d8222002bf716f270352534a753ab1e..36d19f3da90a566333d791e34685cc06c20ed2b4 100644 (file)
@@ -183,7 +183,7 @@ class Parser : public sigc::trackable {
        void process_mtc_quarter_frame (byte *msg);
 };
 
-}; /* namespace MIDI */
+} // namespace MIDI
 
 #endif   // __midi_parse_h__
 
index a186f1fd5fbd76453e6f91b7c606c76e79d6b2ac..4a5319b120da103e5a75a8957046a0513da101ec 100644 (file)
@@ -40,7 +40,7 @@ class Port : public sigc::trackable {
                ALSA_Sequencer,
                CoreMidi_MidiPort,
                Null,
-               FIFO,
+               FIFO
        };
 
 
@@ -140,7 +140,6 @@ class Port : public sigc::trackable {
        static size_t nports;
 };
 
-}; /* namespace MIDI */
+} // namespace MIDI
 
 #endif // __libmidi_port_h__
-
index 28a0d1d70bc0ae6c2d8d62015c6a8d65948677f4..86838dd04d2fb5fcb8a113f2ed204340641f5411 100644 (file)
@@ -54,7 +54,7 @@ struct PortRequest {
                 const std::string &xtype);
 };
 
-}; /* namespace MIDI */
+} // namespace MIDI
 
 #endif // __midi_port_request_h__
 
index b9d9bf33e7c4d6f7abb5e3bee7395e41f9a8f0ae..218416d213889bf20dcbdb5111c7de4cf7f7d7c7 100644 (file)
@@ -57,10 +57,10 @@ namespace MIDI {
     enum MTC_Status {
            MTC_Stopped = 0,
            MTC_Forward,
-           MTC_Backward,
+           MTC_Backward
     };
 
-}; /* namespace MIDI */
+} // namespace MIDI
 
 #endif // __midi_types_h__
 
diff --git a/libs/midi++2/midicontrollable.cc b/libs/midi++2/midicontrollable.cc
deleted file mode 100644 (file)
index f0dbd9c..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#include <cstdio> /* for sprintf, sigh */
-#include <pbd/error.h>
-#include <midi++/port.h>
-#include <midi++/channel.h>
-#include <midi++/controllable.h>
-
-using namespace sigc;
-using namespace MIDI;
-using namespace PBD;
-
-Controllable::Controllable (Port *p, bool is_bistate)
-{
-       control_type = none;
-       _control_description = "MIDI Control: none";
-       control_additional = (byte) -1;
-       bistate = is_bistate;
-       connections = 0;
-       feedback = true; // for now
-       
-       /* use channel 0 ("1") as the initial channel */
-
-       midi_rebind (p, 0);
-}
-
-Controllable::~Controllable ()
-{
-       drop_external_control ();
-}
-
-void
-Controllable::midi_forget ()
-{
-       /* stop listening for incoming messages, but retain
-          our existing event + type information.
-       */
-       
-       if (connections > 0) {
-               midi_sense_connection[0].disconnect ();
-       } 
-       
-       if (connections > 1) {
-               midi_sense_connection[1].disconnect ();
-       }
-       
-       connections = 0;
-       midi_learn_connection.disconnect ();
-       
-}
-
-void
-Controllable::midi_rebind (Port *p, channel_t c)
-{
-       if ((port = p) == 0) {
-               midi_forget ();
-       } else {
-               if (c >= 0) {
-                       bind_midi (c, control_type, control_additional);
-               } else {
-                       midi_forget ();
-               }
-       }
-}
-
-void
-Controllable::learn_about_external_control ()
-{
-       drop_external_control ();
-
-       if (port) {
-               midi_learn_connection = port->input()->any.connect (mem_fun (*this, &Controllable::midi_receiver));
-               learning_started ();
-
-       } else {
-               info << "No MIDI port specified - external control disabled" << endmsg;
-       }
-}
-
-void
-Controllable::stop_learning ()
-{
-       midi_learn_connection.disconnect ();
-}
-
-void
-Controllable::drop_external_control ()
-{
-       if (connections > 0) {
-               midi_sense_connection[0].disconnect ();
-       } 
-       if (connections > 1) {
-               midi_sense_connection[1].disconnect ();
-       }
-
-       connections = 0;
-       midi_learn_connection.disconnect ();
-
-       control_type = none;
-       control_additional = (byte) -1;
-}
-
-void 
-Controllable::midi_sense_note_on (Parser &p, EventTwoBytes *tb) 
-{
-       midi_sense_note (p, tb, true);
-}
-
-void 
-Controllable::midi_sense_note_off (Parser &p, EventTwoBytes *tb) 
-{
-       midi_sense_note (p, tb, false);
-}
-
-void
-Controllable::midi_sense_note (Parser &p, EventTwoBytes *msg, bool is_on)
-{
-       if (!bistate) {
-               set_value (msg->note_number/127.0);
-       } else {
-
-               /* Note: parser handles the use of zero velocity to
-                  mean note off. if we get called with is_on=true, then we
-                  got a *real* note on.  
-               */
-
-               if (msg->note_number == control_additional) {
-                       set_value (is_on ? 1 : 0);
-               }
-       }
-}
-
-void
-Controllable::midi_sense_controller (Parser &, EventTwoBytes *msg)
-{
-       if (control_additional == msg->controller_number) {
-               if (!bistate) {
-                       set_value (msg->value/127.0);
-               } else {
-                       if (msg->value > 64.0) {
-                               set_value (1);
-                       } else {
-                               set_value (0);
-                       }
-               }
-       }
-}
-
-void
-Controllable::midi_sense_program_change (Parser &p, byte msg)
-{
-       /* XXX program change messages make no sense for bistates */
-
-       if (!bistate) {
-               set_value (msg/127.0);
-       } 
-}
-
-void
-Controllable::midi_sense_pitchbend (Parser &p, pitchbend_t pb)
-{
-       /* pitchbend messages make no sense for bistates */
-
-       /* XXX gack - get rid of assumption about typeof pitchbend_t */
-
-       set_value ((pb/(float) SHRT_MAX));
-}                      
-
-void
-Controllable::midi_receiver (Parser &p, byte *msg, size_t len)
-{
-       /* we only respond to channel messages */
-
-       if ((msg[0] & 0xF0) < 0x80 || (msg[0] & 0xF0) > 0xE0) {
-               return;
-       }
-
-       /* if the our port doesn't do input anymore, forget it ... */
-
-       if (!port->input()) {
-               return;
-       }
-
-       bind_midi ((channel_t) (msg[0] & 0xf), eventType (msg[0] & 0xF0), msg[1]);
-
-       learning_stopped ();
-}
-
-void
-Controllable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
-{
-       char buf[64];
-
-       drop_external_control ();
-
-       control_type = ev;
-       control_channel = chn;
-       control_additional = additional;
-
-       if (port == 0 || port->input() == 0) {
-               return;
-       }
-       
-       Parser& p = *port->input();
-
-       int chn_i = chn;
-       switch (ev) {
-       case MIDI::off:
-               midi_sense_connection[0] = p.channel_note_off[chn_i].connect
-                       (mem_fun (*this, &Controllable::midi_sense_note_off));
-
-               /* if this is a bistate, connect to noteOn as well,
-                  and we'll toggle back and forth between the two.
-               */
-
-               if (bistate) {
-                       midi_sense_connection[1] = p.channel_note_on[chn_i].connect
-                               (mem_fun (*this, &Controllable::midi_sense_note_on));
-                       connections = 2;
-               } else {
-                       connections = 1;
-               }
-               _control_description = "MIDI control: NoteOff";
-               break;
-
-       case MIDI::on:
-               midi_sense_connection[0] = p.channel_note_on[chn_i].connect
-                       (mem_fun (*this, &Controllable::midi_sense_note_on));
-               if (bistate) {
-                       midi_sense_connection[1] = p.channel_note_off[chn_i].connect 
-                               (mem_fun (*this, &Controllable::midi_sense_note_off));
-                       connections = 2;
-               } else {
-                       connections = 1;
-               }
-               _control_description = "MIDI control: NoteOn";
-               break;
-
-       case MIDI::controller:
-               midi_sense_connection[0] = p.channel_controller[chn_i].connect 
-                       (mem_fun (*this, &Controllable::midi_sense_controller));
-               connections = 1;
-               snprintf (buf, sizeof (buf), "MIDI control: Controller %d", control_additional);
-               _control_description = buf;
-               break;
-
-       case MIDI::program:
-               if (!bistate) {
-                       midi_sense_connection[0] = p.channel_program_change[chn_i].connect
-                               (mem_fun (*this, 
-                                      &Controllable::midi_sense_program_change));
-                       connections = 1;
-                       _control_description = "MIDI control: ProgramChange";
-               }
-               break;
-
-       case MIDI::pitchbend:
-               if (!bistate) {
-                       midi_sense_connection[0] = p.channel_pitchbend[chn_i].connect
-                               (mem_fun (*this, &Controllable::midi_sense_pitchbend));
-                       connections = 1;
-                       _control_description = "MIDI control: Pitchbend";
-               }
-               break;
-
-       default:
-               break;
-       }
-}
-
-void
-Controllable::set_control_type (channel_t chn, eventType ev, MIDI::byte additional)
-{
-       bind_midi (chn, ev, additional);
-}
-
-bool
-Controllable::get_control_info (channel_t& chn, eventType& ev, byte& additional)
-{
-       if (control_type == none) {
-               chn = -1;
-               return false;
-       } 
-       
-       ev = control_type;
-       chn = control_channel;
-       additional = control_additional;
-
-       return true;
-}
-
-
-void
-Controllable::send_midi_feedback (float val)
-{
-       byte msg[3];
-
-       if (port == 0 || control_type == none) {
-               return;
-       }
-       
-       msg[0] = (control_type & 0xF0) | (control_channel & 0xF); 
-       msg[1] = control_additional;
-       msg[2] = (byte) (val * 127.0f);
-
-       port->write (msg, 3);
-}
-
index 04ac2728f1c150be4637816f0af7780c05e71d3b..424bfa04f8581b6bc9eeda0fd19b2ea01f5178d5 100644 (file)
@@ -101,7 +101,7 @@ Parser::midi_event_type_name (eventType t)
        default:
                return "unknow MIDI event type";
        }
-};
+}
 
 Parser::Parser (Port &p) 
        : _port (p)
diff --git a/libs/pbd/.cvsignore b/libs/pbd/.cvsignore
new file mode 100644 (file)
index 0000000..e9a15e8
--- /dev/null
@@ -0,0 +1,5 @@
+libpbd.pc
+libpbd.spec
+version.cc
+*.os
+*.dylib
diff --git a/libs/pbd/AUTHORS b/libs/pbd/AUTHORS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/pbd/COPYING b/libs/pbd/COPYING
new file mode 100644 (file)
index 0000000..d60c31a
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/libs/pbd/ChangeLog b/libs/pbd/ChangeLog
new file mode 100644 (file)
index 0000000..59e9291
--- /dev/null
@@ -0,0 +1,10 @@
+2005-12-02 Taybin Rutkin <taybin@earthlink.net>
+       * libpbd now allocates warning, info, error, and fatal itself.
+       * Incremented version to 3.1.
+
+2005-04-01 Taybin Rutkin <taybin@earthlink.net>
+       * Updated to support sigc++-2.0.
+       * Incremented version to 3.0.0.
+
+2004-08-04 Taybin Rutkin <taybin@earthlink.net>
+       * Added support for gcc-3.4
diff --git a/libs/pbd/NEWS b/libs/pbd/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/pbd/README b/libs/pbd/README
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libs/pbd/SConscript b/libs/pbd/SConscript
new file mode 100644 (file)
index 0000000..4b15dd7
--- /dev/null
@@ -0,0 +1,75 @@
+# -*- python -*-
+
+import os
+import os.path
+import glob
+
+Import('env libraries i18n install_prefix')
+
+pbd = env.Copy()
+
+domain = 'libpbd'
+
+pbd.Append(DOMAIN=domain,MAJOR=4,MINOR=1,MICRO=0)
+pbd.Append(CXXFLAGS="-DPACKAGE=\\\"" + domain + "\\\"")
+pbd.Append(CXXFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
+pbd.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
+pbd.Append(PACKAGE=domain)
+pbd.Append(POTFILE=domain + '.pot')
+
+pbd_files = Split("""
+basename.cc
+base_ui.cc
+convert.cc
+command.cc
+controllable.cc
+dmalloc.cc
+error.cc
+id.cc
+mountpoint.cc
+path.cc
+pathscanner.cc
+pool.cc
+pthread_utils.cc
+receiver.cc
+stacktrace.cc
+stateful.cc
+strsplit.cc
+textreceiver.cc
+transmitter.cc
+undo.cc
+version.cc
+whitespace.cc
+xml++.cc
+""")
+
+conf = Configure(pbd)
+if conf.CheckFunc('getmntent'):
+    conf.env.Append(CCFLAGS="-DHAVE_GETMNTENT")
+if conf.CheckCHeader('execinfo.h'):
+    conf.env.Append(CXXFLAGS="-DHAVE_EXECINFO")
+pbd = conf.Finish()
+
+pbd.Merge ([ libraries['sigc2'],
+             libraries['xml'],
+             libraries['glibmm2'],
+             libraries['glib2'] ])
+
+pbd.VersionBuild(['version.cc','pbd/version.h'], 'SConscript')
+
+libpbd = pbd.SharedLibrary('pbd', pbd_files)
+Default(libpbd)
+
+mount_env = Environment(CCFLAGS='-DTEST_MOUNTPOINT -Ilibs/pbd')
+mount_env.Program('mountpoint', 'mountpoint.cc')
+
+if env['NLS']:
+    i18n (pbd, pbd_files, env)
+
+env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2'), libpbd))
+
+env.Alias('tarball', env.Distribute (env['DISTTREE'],
+                                     [ 'SConscript', 'i18n.h', 'gettext.h', 'pbd/abstract_ui.cc' ] +
+                                     pbd_files +
+                                     glob.glob('po/*.po') +
+                                     glob.glob('pbd/*.h')))
diff --git a/libs/pbd/base_ui.cc b/libs/pbd/base_ui.cc
new file mode 100644 (file)
index 0000000..d3c8d5e
--- /dev/null
@@ -0,0 +1,88 @@
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <pbd/base_ui.h>
+#include <pbd/error.h>
+#include <pbd/compose.h>
+#include <pbd/failed_constructor.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace PBD;
+       
+uint32_t BaseUI::rt_bit = 1;
+BaseUI::RequestType BaseUI::CallSlot = BaseUI::new_request_type();
+
+BaseUI::BaseUI (string str, bool with_signal_pipe)
+       : _name (str)
+{
+       /* odd pseudo-singleton semantics */
+
+       base_ui_instance = this;
+
+       signal_pipe[0] = -1;
+       signal_pipe[1] = -1;
+
+       if (with_signal_pipe) {
+               if (setup_signal_pipe ()) {
+                       throw failed_constructor ();
+               }
+       }
+}
+
+BaseUI::~BaseUI()
+{
+       if (signal_pipe[0] >= 0) {
+               close (signal_pipe[0]);
+       } 
+
+       if (signal_pipe[1] >= 0) {
+               close (signal_pipe[1]);
+       } 
+}
+
+BaseUI::RequestType
+BaseUI::new_request_type ()
+{
+       RequestType rt;
+
+       /* XXX catch out-of-range */
+
+       rt = RequestType (rt_bit);
+       rt_bit <<= 1;
+
+       return rt;
+}
+
+int
+BaseUI::setup_signal_pipe ()
+{
+       /* setup the pipe that other threads send us notifications/requests
+          through.
+       */
+
+       if (pipe (signal_pipe)) {
+               error << string_compose (_("%1-UI: cannot create error signal pipe (%2)"), _name, std::strerror (errno))
+                     << endmsg;
+
+               return -1;
+       }
+
+       if (fcntl (signal_pipe[0], F_SETFL, O_NONBLOCK)) {
+               error << string_compose (_("%1-UI: cannot set O_NONBLOCK on signal read pipe (%2)"), _name, std::strerror (errno))
+                     << endmsg;
+               return -1;
+       }
+
+       if (fcntl (signal_pipe[1], F_SETFL, O_NONBLOCK)) {
+               error << string_compose (_("%1-UI: cannot set O_NONBLOCK on signal write pipe (%2)"), _name, std::strerror (errno))
+                     << endmsg;
+               return -1;
+       }
+
+       return 0;
+}
+
diff --git a/libs/pbd/basename.cc b/libs/pbd/basename.cc
new file mode 100644 (file)
index 0000000..a51e393
--- /dev/null
@@ -0,0 +1,20 @@
+#include <iostream>
+#include <string.h>
+#include <pbd/basename.h>
+
+
+// implement this using Glib::path_get_basename
+std::string 
+PBD::basename_nosuffix (const std::string& str)
+{
+       std::string::size_type slash = str.find_last_of ('/');
+       std::string noslash;
+
+       if (slash == std::string::npos) {
+               noslash = str;
+       } else {
+               noslash = str.substr (slash+1);
+       }
+
+       return noslash.substr (0, noslash.find_last_of ('.'));
+}
diff --git a/libs/pbd/command.cc b/libs/pbd/command.cc
new file mode 100644 (file)
index 0000000..3f5aca8
--- /dev/null
@@ -0,0 +1,10 @@
+#include <pbd/command.h>
+
+class XMLNode;
+
+XMLNode &Command::serialize()
+{
+    XMLNode *node = new XMLNode ("Command");
+    // TODO
+    return *node;
+}
diff --git a/libs/pbd/controllable.cc b/libs/pbd/controllable.cc
new file mode 100644 (file)
index 0000000..b1176c6
--- /dev/null
@@ -0,0 +1,26 @@
+#include <pbd/controllable.h>
+#include <pbd/xml++.h>
+
+#include "i18n.h"
+
+using namespace PBD;
+
+sigc::signal<void,Controllable*> Controllable::Created;
+sigc::signal<void,Controllable*> Controllable::GoingAway;
+sigc::signal<bool,Controllable*> Controllable::StartLearning;
+sigc::signal<void,Controllable*> Controllable::StopLearning;
+
+Controllable::Controllable ()
+{
+       Created (this);
+}
+
+XMLNode&
+Controllable::get_state ()
+{
+       XMLNode* node = new XMLNode (X_("Controllable"));
+       char buf[64];
+       _id.print (buf);
+       node->add_property (X_("id"), buf);
+       return *node;
+}
diff --git a/libs/pbd/convert.cc b/libs/pbd/convert.cc
new file mode 100644 (file)
index 0000000..60d39c9
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+    Copyright (C) 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
+    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 <cmath>
+#include <stdint.h>
+
+#include "pbd/convert.h"
+
+#include "i18n.h"
+
+using std::string;
+using std::vector;
+
+namespace PBD {
+
+string
+short_version (string orig, string::size_type target_length)
+{
+       /* this tries to create a recognizable abbreviation
+          of "orig" by removing characters until we meet
+          a certain target length.
+
+          note that we deliberately leave digits in the result
+          without modification.
+       */
+
+
+       string::size_type pos;
+
+       /* remove white-space and punctuation, starting at end */
+
+       while (orig.length() > target_length) {
+               if ((pos = orig.find_last_of (_("\"\n\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="))) == string::npos) {
+                       break;
+               }
+               orig.replace (pos, 1, "");
+       }
+
+       /* remove lower-case vowels, starting at end */
+
+       while (orig.length() > target_length) {
+               if ((pos = orig.find_last_of (_("aeiou"))) == string::npos) {
+                       break;
+               }
+               orig.replace (pos, 1, "");
+       }
+
+       /* remove upper-case vowels, starting at end */
+
+       while (orig.length() > target_length) {
+               if ((pos = orig.find_last_of (_("AEIOU"))) == string::npos) {
+                       break;
+               }
+               orig.replace (pos, 1, "");
+       }
+
+       /* remove lower-case consonants, starting at end */
+
+       while (orig.length() > target_length) {
+               if ((pos = orig.find_last_of (_("bcdfghjklmnpqrtvwxyz"))) == string::npos) {
+                       break;
+               }
+               orig.replace (pos, 1, "");
+       }
+
+       /* remove upper-case consonants, starting at end */
+
+       while (orig.length() > target_length) {
+               if ((pos = orig.find_last_of (_("BCDFGHJKLMNPQRTVWXYZ"))) == string::npos) {
+                       break;
+               }
+               orig.replace (pos, 1, "");
+       }
+
+       /* whatever the length is now, use it */
+       
+       return orig;
+}
+
+int
+atoi (const string& s)
+{
+       return std::atoi (s.c_str());
+}
+
+double
+atof (const string& s)
+{
+       return std::atof (s.c_str());
+}
+
+vector<string>
+internationalize (const char **array)
+{
+       vector<string> v;
+
+       for (uint32_t i = 0; array[i]; ++i) {
+               v.push_back (_(array[i]));
+       }
+
+       return v;
+}
+
+static int32_t 
+int_from_hex (char hic, char loc) 
+{
+       int hi;         /* hi byte */
+       int lo;         /* low byte */
+
+       hi = (int) hic;
+
+       if( ('0'<=hi) && (hi<='9') ) {
+               hi -= '0';
+       } else if( ('a'<= hi) && (hi<= 'f') ) {
+               hi -= ('a'-10);
+       } else if( ('A'<=hi) && (hi<='F') ) {
+               hi -= ('A'-10);
+       }
+       
+       lo = (int) loc;
+       
+       if( ('0'<=lo) && (lo<='9') ) {
+               lo -= '0';
+       } else if( ('a'<=lo) && (lo<='f') ) {
+               lo -= ('a'-10);
+       } else if( ('A'<=lo) && (lo<='F') ) {
+               lo -= ('A'-10);
+       }
+
+       return lo + (16 * hi);
+}
+
+void
+url_decode (string& url)
+{
+       string::iterator last;
+       string::iterator next;
+
+       for (string::iterator i = url.begin(); i != url.end(); ++i) {
+               if ((*i) == '+') {
+                       *i = ' ';
+               }
+       }
+
+       if (url.length() <= 3) {
+               return;
+       }
+
+       last = url.end();
+
+       --last; /* points at last char */
+       --last; /* points at last char - 1 */
+
+       for (string::iterator i = url.begin(); i != last; ) {
+
+               if (*i == '%') {
+
+                       next = i;
+
+                       url.erase (i);
+                       
+                       i = next;
+                       ++next;
+                       
+                       if (isxdigit (*i) && isxdigit (*next)) {
+                               /* replace first digit with char */
+                               *i = int_from_hex (*i,*next);
+                               ++i; /* points at 2nd of 2 digits */
+                               url.erase (i);
+                       }
+               } else {
+                       ++i;
+               }
+       }
+}
+
+string
+length2string (const int32_t frames, const float sample_rate)
+{
+    int secs = (int) (frames / sample_rate);
+    int hrs =  secs / 3600;
+    secs -= (hrs * 3600);
+    int mins = secs / 60;
+    secs -= (mins * 60);
+
+    int total_secs = (hrs * 3600) + (mins * 60) + secs;
+    int frames_remaining = (int) floor (frames - (total_secs * sample_rate));
+    float fractional_secs = (float) frames_remaining / sample_rate;
+
+    char duration_str[32];
+    sprintf (duration_str, "%02d:%02d:%05.2f", hrs, mins, (float) secs + fractional_secs);
+
+    return duration_str;
+}
+
+} // namespace PBD
diff --git a/libs/pbd/dmalloc.cc b/libs/pbd/dmalloc.cc
new file mode 100644 (file)
index 0000000..0e73094
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * file that facilitates C++ program debugging.
+ *
+ * Copyright 1995 by Gray Watson
+ *
+ * This file is part of the dmalloc package.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * NON-COMMERCIAL purpose and without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear
+ * in all copies, and that the name of Gray Watson not be used in
+ * advertising or publicity pertaining to distribution of the document
+ * or software without specific, written prior permission.
+ *
+ * Please see the PERMISSIONS file or contact the author for information
+ * about commercial licenses.
+ *
+ * Gray Watson makes no representations about the suitability of the
+ * software described herein for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * The author may be contacted via http://www.letters.com/~gray/
+ *
+ * $Id$
+ */
+
+/*
+ * This file is used to effectively redirect new to the more familiar
+ * malloc and delete to the more familiar free so they can be debugged
+ * with the debug malloc library..  They also give the known error
+ * behavior, too.
+ *
+ * Compile and link this in with the C++ program you want to debug.
+ *
+ * NOTE: I am not a C++ hacker so feedback in the form of other hints
+ * and ideas for C++ users would be much appreciated.
+ */
+
+#ifdef DEBUG_MALLOC
+
+extern "C" {
+#include <stdlib.h>
+#include <dmalloc.h>
+#include "/usr/local/src/dmalloc-4.1.2/return.h"
+}
+
+/*
+ * An overload function for the C++ new.
+ */
+void *
+operator new(size_t size)
+{
+  char *file;
+  GET_RET_ADDR(file);
+
+  /* handle correct C++ semantics for an alloc of size 0 */
+  
+  if (size == 0) size = 1;
+  
+  return _malloc_leap(file, 0, size);
+}
+
+/*
+ * An overload function for the C++ new[].
+ */
+void *
+operator new[](size_t size)
+{
+  char *file;
+  GET_RET_ADDR(file);
+
+  /* handle correct C++ semantics for an alloc of size 0 */
+  
+  if (size == 0) size = 1;
+
+  return _malloc_leap(file, 0, size);
+}
+
+/*
+ * An overload function for the C++ delete.
+ */
+void
+operator delete(void *pnt)
+{
+  char *file;
+  GET_RET_ADDR(file);
+  _free_leap(file, 0, pnt);
+}
+
+/*
+ * An overload function for the C++ delete[].  Thanks to Jens Krinke
+ * <j.krinke@gmx.de>
+ */
+void
+operator delete[](void *pnt)
+{
+  char *file;
+  GET_RET_ADDR(file);
+  _free_leap(file, 0, pnt);
+}
+
+#endif
diff --git a/libs/pbd/error.cc b/libs/pbd/error.cc
new file mode 100644 (file)
index 0000000..a6f8fb7
--- /dev/null
@@ -0,0 +1,7 @@
+#include <pbd/error.h>
+
+Transmitter  PBD::error (Transmitter::Error);
+Transmitter  PBD::info (Transmitter::Info);
+Transmitter  PBD::fatal (Transmitter::Fatal);
+Transmitter  PBD::warning (Transmitter::Warning);
+
diff --git a/libs/pbd/gettext.h b/libs/pbd/gettext.h
new file mode 100644 (file)
index 0000000..339c74f
--- /dev/null
@@ -0,0 +1,82 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+   Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#ifndef _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option.  */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions.  */
+# include <libintl.h>
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+   chokes if dcgettext is defined as a macro.  So include it now, to make
+   later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
+   as well because people using "gettext.h" will not include <libintl.h>,
+   and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+   is OK.  */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Disabled NLS.
+   The casts to 'const char *' serve the purpose of producing warnings
+   for invalid uses of the value returned from these functions.
+   On pre-ANSI systems without 'const', the config.h file is supposed to
+   contain "#define const".  */
+
+/* other headers may have included libintl.h */
+
+# undef gettext
+# undef dgettext
+# undef dcgettext
+# undef ngettext
+# undef dngettext
+# undef dcngettext
+# undef textdomain
+# undef bindtextdomain
+# undef bind_textdomain_codeset
+
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+   extraction of messages, but does not call gettext().  The run-time
+   translation is done at a different place in the code.
+   The argument, String, should be a literal string.  Concatenated strings
+   and other string expressions won't work.
+   The macro's expansion is not parenthesized, so that it is suitable as
+   initializer for static 'char[]' or 'const char[]' variables.  */
+#define gettext_noop(String) String
+
+#endif /* _LIBGETTEXT_H */
diff --git a/libs/pbd/i18n.h b/libs/pbd/i18n.h
new file mode 100644 (file)
index 0000000..7c79d2e
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __i18n_h__
+#define __i18n_h__
+
+#include <pbd/compose.h>
+#include "gettext.h"
+
+#define _(Text) dgettext (PACKAGE, Text)
+#define N_(Text) gettext_noop (Text)
+#define X_(Text) (Text)
+
+#endif // __i18n_h__
diff --git a/libs/pbd/id.cc b/libs/pbd/id.cc
new file mode 100644 (file)
index 0000000..f9afa72
--- /dev/null
@@ -0,0 +1,63 @@
+#include <ostream>
+#include <iostream>
+#include <stdio.h>
+
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+#include <inttypes.h>
+
+#include <pbd/id.h>
+
+using namespace std;
+using namespace PBD;
+
+Glib::Mutex* ID::counter_lock = 0;
+uint64_t ID::_counter = 0;
+
+void
+ID::init ()
+{
+       counter_lock = new Glib::Mutex;
+}
+
+ID::ID ()
+{
+       Glib::Mutex::Lock lm (*counter_lock);
+       id = _counter++;
+}
+
+ID::ID (string str)
+{
+       string_assign (str);
+}
+
+int
+ID::string_assign (string str)
+{
+       return sscanf (str.c_str(), "%" PRIu64, &id) != 0;
+}
+
+void
+ID::print (char* buf) const
+{
+       /* XXX sizeof buf is unknown. bad API design */
+       snprintf (buf, 16, "%" PRIu64, id);
+}
+
+ID&
+ID::operator= (string str)
+{
+       string_assign (str);
+       return *this;
+}
+
+ostream&
+operator<< (ostream& ostr, const ID& id)
+{
+       char buf[32];
+       id.print (buf);
+       ostr << buf;
+       return ostr;
+}
+
diff --git a/libs/pbd/libpbd.pc.in b/libs/pbd/libpbd.pc.in
new file mode 100644 (file)
index 0000000..14d0208
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/pbd
+
+Name: libpbd
+Version: @VERSION@
+Description: libpbd, a library of useful, generic C++ objects
+Requires: 
+Libs: -L${libdir} -lpbd @NON_PKG_LIBS@
+Cflags: -I${includedir} @NON_PKG_CFLAGS@
diff --git a/libs/pbd/libpbd.spec.in b/libs/pbd/libpbd.spec.in
new file mode 100644 (file)
index 0000000..d50622d
--- /dev/null
@@ -0,0 +1,70 @@
+Summary: A general purpose programming library
+%define lib_name pbd
+Name: lib%{lib_name}
+Version: @VERSION@
+Release: 2
+Copyright: GPL
+Source: .
+Url: http://www.quasimodo.org
+Vendor: Paul Davis <paul@linuxaudiosystems.com>
+Packager: jfm3 <jfm3@acm.org>
+Group: System Environment/Libraries
+Prefix: %{_prefix}
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+
+%description
+
+This library implements a number of programming utilities used by Paul
+Davis (formerly Paul Barton-Davis, hence the name).  It is used in
+some of his Open Source software projects.  See
+http://ardour.sf.net/ for examples.
+
+%prep
+%setup -q
+
+%build
+CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" ./configure $ARCH_FLAGS --prefix=%{prefix}
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+install -d -m 755 $RPM_BUILD_ROOT%{prefix}/{{include,lib}/%{lib_name}}
+make install INSTALL="%(which install) -p" prefix=$RPM_BUILD_ROOT%{prefix}
+
+%post
+/sbin/ldconfig
+
+%postun
+/sbin/ldconfig
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc README AUTHORS NEWS COPYING*
+%{prefix}/lib/libpbd.so*
+
+%package devel
+Summary: A general purpose programming library -- developer version.
+Group: System Environment/Libraries
+
+%description devel
+
+This library implements a number of programming utilities used by Paul
+Davis (formerly Paul Barton-Davis, hence the name).  It is used in
+some of his Open Source software projects.  See
+http://ardour.sf.net/ for examples.
+
+This package holds static libraries and headers needed by developers
+who wish to use libpbd in their programs.
+
+%files devel
+%defattr(-,root,root)
+%{prefix}/include/pbd/*
+%{prefix}/lib/libpbd.a
+%{prefix}/lib/libpbd.la
+%{prefix}/bin/pbd-config
+%{prefix}/share/aclocal/pbd.m4
+%{prefix}/share/aclocal/unique_args.m4
+
diff --git a/libs/pbd/mountpoint.cc b/libs/pbd/mountpoint.cc
new file mode 100644 (file)
index 0000000..c1bcb37
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+    Copyright (C) 2002 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$
+*/
+
+#include <cstdio>
+#include <string>
+#include <limits.h>
+
+#include <pbd/mountpoint.h>
+
+using std::string;
+
+#if HAVE_GETMNTENT
+#include <mntent.h>
+
+struct mntent_sorter {
+    bool operator() (const mntent *a, const mntent *b) {
+           return strcmp (a->mnt_dir, b->mnt_dir);
+    }
+};
+
+string
+mountpoint (string path)
+{
+       FILE *mntf;
+       mntent *mnt;
+       unsigned int maxmatch = 0;
+       unsigned int matchlen;
+       const char *cpath = path.c_str();
+       char best[PATH_MAX+1];
+       
+       if ((mntf = setmntent ("/etc/mtab", "r")) == 0) {
+               return "";
+       }
+
+       best[0] = '\0';
+
+       while ((mnt = getmntent (mntf))) {
+               unsigned int n;
+
+               n = 0;
+               matchlen = 0;
+
+               /* note: strcmp's semantics are not 
+                  strict enough to use for this.
+               */
+
+               while (cpath[n] && mnt->mnt_dir[n]) {
+                       if (cpath[n] != mnt->mnt_dir[n]) {
+                               break;
+                       }
+                       matchlen++;
+                       n++;
+               }
+
+               if (cpath[matchlen] == '\0') {
+
+                       endmntent (mntf);
+                       return mnt->mnt_dir;
+
+               } else {
+
+                       if (matchlen > maxmatch) {
+                               snprintf (best, sizeof(best), "%s", mnt->mnt_dir);
+                               maxmatch = matchlen;
+                       }
+               }
+       }
+
+       endmntent (mntf);
+
+       return best;
+}
+
+#else // !HAVE_GETMNTENT
+
+#include <sys/param.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
+
+string
+mountpoint (string path)
+{
+       struct statfs *mntbufp = 0;
+       int count;
+       unsigned int maxmatch = 0;
+       unsigned int matchlen;
+       const char *cpath = path.c_str();
+       char best[PATH_MAX+1];
+       
+       if ((count = getmntinfo(&mntbufp, MNT_NOWAIT)) == 0) {
+               free(mntbufp);
+               return "\0";
+       }
+
+       best[0] = '\0';
+
+       for (int i = 0; i < count; ++i) {
+               unsigned int n = 0;
+               matchlen = 0;
+
+               /* note: strcmp's semantics are not 
+                  strict enough to use for this.
+               */
+
+               while (cpath[n] && mntbufp[i].f_mntonname[n]) {
+                       if (cpath[n] != mntbufp[i].f_mntonname[n]) {
+                               break;
+                       }
+                       matchlen++;
+                       n++;
+               }
+
+               if (cpath[matchlen] == '\0') {
+                       snprintf(best, sizeof(best), "%s", mntbufp[i].f_mntonname);
+                       free(mntbufp);
+                       return best;
+
+               } else {
+
+                       if (matchlen > maxmatch) {
+                               snprintf (best, sizeof(best), "%s", mntbufp[i].f_mntonname);
+                               maxmatch = matchlen;
+                       }
+               }
+       }
+
+       free(mntbufp);
+       
+       return best;
+}
+#endif // HAVE_GETMNTENT
+
+#ifdef TEST_MOUNTPOINT
+               
+main (int argc, char *argv[])
+{
+       printf ("mp of %s = %s\n", argv[1], mountpoint (argv[1]).c_str());
+       exit (0);
+}
+
+#endif // TEST_MOUNTPOINT
diff --git a/libs/pbd/path.cc b/libs/pbd/path.cc
new file mode 100644 (file)
index 0000000..80f916c
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+   Copyright (C) 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 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#include <cerrno>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include <glibmm/miscutils.h>
+#include <glibmm/fileutils.h>
+
+#include <pbd/path.h>
+#include <pbd/tokenizer.h>
+
+namespace PBD {
+
+Path::Path ()
+{
+
+}
+
+Path::Path (const string& path)
+{
+       vector<string> tmp;
+
+       if(!tokenize ( path, string(":;"), std::back_inserter (tmp))) {
+               g_warning ("%s : %s\n", G_STRLOC, G_STRFUNC);
+               return;
+       }
+
+       add_readable_directories (tmp);
+}
+
+Path::Path (const vector<string>& paths)
+{
+       add_readable_directories (paths);
+}
+
+Path::Path (const Path& other)
+       : m_dirs(other.m_dirs)
+{
+
+}
+
+bool
+Path::readable_directory (const string& directory_path)
+{
+       if (g_access (directory_path.c_str(), R_OK) == 0) {
+               if (Glib::file_test(directory_path, Glib::FILE_TEST_IS_DIR)) {
+                       return true;
+               } else {
+                       g_warning (" %s : Path exists but is not a directory\n", G_STRLOC); 
+               }
+       } else {
+               g_warning ("%s : %s : %s\n", G_STRLOC, directory_path.c_str(), g_strerror(errno));
+       }
+       return false;
+}
+
+void
+Path::add_readable_directory (const string& directory_path)
+{
+       if(readable_directory(directory_path)) {
+               m_dirs.push_back(directory_path);
+       }
+}
+
+void
+Path::add_readable_directories (const vector<string>& paths)
+{
+       for(vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
+               add_readable_directory (*i);
+       }
+}
+
+const string
+Path::path_string() const
+{
+       string path;
+
+       for (vector<string>::const_iterator i = m_dirs.begin(); i != m_dirs.end(); ++i) {
+               path += (*i);
+               path += G_SEARCHPATH_SEPARATOR;
+       }
+
+       g_message ("%s : %s", G_STRLOC, path.c_str());
+
+       return path.substr (0, path.length() - 1); // drop final colon
+}
+
+const Path&
+Path::operator= (const Path& path)
+{
+       m_dirs = path.m_dirs;
+       return *this;
+}
+
+const Path& 
+Path::operator+= (const string& directory_path)
+{
+       add_readable_directory (directory_path);
+       return *this;
+}
+
+const Path 
+operator+ (const Path& lhs_path, const Path& rhs_path)
+{
+       Path tmp_path(lhs_path); // does this do what I think it does.
+       // concatenate paths into new Path
+       tmp_path.m_dirs.insert(tmp_path.m_dirs.end(), rhs_path.m_dirs.begin(), rhs_path.m_dirs.end());
+       return tmp_path;
+}
+
+Path&
+Path::add_subdirectory_to_path (const string& subdir)
+{
+       vector<string> tmp;
+       string directory_path;
+
+       for (vector<string>::iterator i = m_dirs.begin(); i != m_dirs.end(); ++i) {
+               directory_path = Glib::build_filename (*i, subdir);
+               if(readable_directory(directory_path)) {
+                       tmp.push_back(directory_path);
+               }
+       }
+       m_dirs = tmp;
+       return *this;
+}
+
+bool
+find_file_in_path (const Path& path, const string& filename, string& resulting_path)
+{
+       for (vector<string>::const_iterator i = path.dirs().begin(); i != path.dirs().end(); ++i) {
+               resulting_path = Glib::build_filename ((*i), filename);
+               if (g_access (resulting_path.c_str(), R_OK) == 0) {
+                       g_message ("File %s found in Path : %s\n", resulting_path.c_str(),
+                                       path.path_string().c_str());
+                       return true;
+               }
+       }
+
+       g_warning ("%s : Could not locate file %s in path %s\n", G_STRLOC, filename.c_str(),
+                       path.path_string().c_str());
+       
+       return false;
+}
+
+} // namespace PBD
+
diff --git a/libs/pbd/pathscanner.cc b/libs/pbd/pathscanner.cc
new file mode 100644 (file)
index 0000000..2af227a
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#include <cstdlib>
+#include <cstdio>
+#include <vector>
+#include <dirent.h>
+
+#include <pbd/error.h>
+#include <pbd/pathscanner.h>
+#include <pbd/stl_delete.h>
+
+using namespace PBD;
+
+vector<string *> *
+PathScanner::operator() (const string &dirpath, const string &regexp,
+                        bool match_fullpath, bool return_fullpath, 
+                        long limit)
+
+{
+       int err;
+       char msg[256];
+
+       if ((err = regcomp (&compiled_pattern, regexp.c_str(),
+                           REG_EXTENDED|REG_NOSUB))) {
+               
+               regerror (err, &compiled_pattern,
+                         msg, sizeof (msg));
+               
+               error << "Cannot compile soundfile regexp for use (" 
+                     << msg 
+                     << ")" 
+                     << endmsg;
+               
+               return 0;
+       }
+       
+       return run_scan (dirpath, &PathScanner::regexp_filter, 
+                        (bool (*)(const string &, void *)) 0,
+                        0,
+                        match_fullpath,
+                        return_fullpath,
+                        limit);
+}      
+
+vector<string *> *
+PathScanner::run_scan (const string &dirpath, 
+                      bool (PathScanner::*memberfilter)(const string &),
+                      bool (*filter)(const string &, void *),
+                      void *arg,
+                      bool match_fullpath, bool return_fullpath,
+                      long limit)
+
+{
+       vector<string *> *result = 0;
+       DIR *dir;
+       struct dirent *finfo;
+       char *pathcopy = strdup (dirpath.c_str());
+       char *thisdir;
+       char fullpath[PATH_MAX+1];
+       string search_str;
+       string *newstr;
+       long nfound = 0;
+
+       if ((thisdir = strtok (pathcopy, ":")) == 0 ||
+           strlen (thisdir) == 0) {
+               free (pathcopy);
+               return 0;
+       }
+
+       result = new vector<string *>;
+
+       do {
+
+               if ((dir = opendir (thisdir)) == 0) {
+                       continue;
+               }
+               
+               while ((finfo = readdir (dir)) != 0) {
+
+                       snprintf (fullpath, sizeof(fullpath), "%s/%s",
+                                 thisdir, finfo->d_name);
+
+                       if (match_fullpath) {
+                               search_str = fullpath;
+                       } else {
+                               search_str = finfo->d_name;
+                       }
+
+                       /* handle either type of function ptr */
+
+                       if (memberfilter) {
+                               if (!(this->*memberfilter)(search_str)) {
+                                       continue;
+                               } 
+                       } else {
+                               if (!filter(search_str, arg)) {
+                                       continue;
+                               }
+                       }
+
+                       if (return_fullpath) {
+                               newstr = new string (fullpath);
+                       } else {
+                               newstr = new string (finfo->d_name);
+                       } 
+
+                       result->push_back (newstr);
+                       nfound++;
+               }
+
+               closedir (dir);
+               
+       } while ((limit < 0 || (nfound < limit)) && (thisdir = strtok (0, ":")));
+
+       free (pathcopy);
+       return result;
+}
+
+string *
+PathScanner::find_first (const string &dirpath,
+                        const string &regexp,
+                        bool match_fullpath,
+                        bool return_fullpath)
+{
+       vector<string *> *res;
+       string *ret;
+       int err;
+       char msg[256];
+
+       if ((err = regcomp (&compiled_pattern, regexp.c_str(),
+                           REG_EXTENDED|REG_NOSUB))) {
+               
+               regerror (err, &compiled_pattern,
+                         msg, sizeof (msg));
+               
+               error << "Cannot compile soundfile regexp for use (" << msg << ")" << endmsg;
+
+               
+               return 0;
+       }
+       
+       res = run_scan (dirpath, 
+                       &PathScanner::regexp_filter,
+                       (bool (*)(const string &, void *)) 0,
+                       0,
+                       match_fullpath,
+                       return_fullpath, 
+                       1);
+       
+       if (res->size() == 0) {
+               ret = 0;
+       } else {
+               ret = res->front();
+       }
+       vector_delete (res);
+       delete res;
+       return ret;
+}
+
+string *
+PathScanner::find_first (const string &dirpath,
+                        bool (*filter)(const string &, void *),
+                        void *arg,
+                        bool match_fullpath,
+                        bool return_fullpath)
+{
+       vector<string *> *res;
+       string *ret;
+
+       res = run_scan (dirpath, 
+                       (bool (PathScanner::*)(const string &)) 0,
+                       filter,
+                       0,
+                       match_fullpath,
+                       return_fullpath, 1);
+       
+       if (res->size() == 0) {
+               ret = 0;
+       } else {
+               ret = res->front();
+       }
+       vector_delete (res);
+       delete res;
+       return ret;
+}
diff --git a/libs/pbd/pbd/.DS_Store b/libs/pbd/pbd/.DS_Store
new file mode 100644 (file)
index 0000000..5008ddf
Binary files /dev/null and b/libs/pbd/pbd/.DS_Store differ
diff --git a/libs/pbd/pbd/.cvsignore b/libs/pbd/pbd/.cvsignore
new file mode 100644 (file)
index 0000000..6702033
--- /dev/null
@@ -0,0 +1 @@
+version.h
diff --git a/libs/pbd/pbd/abstract_ui.cc b/libs/pbd/pbd/abstract_ui.cc
new file mode 100644 (file)
index 0000000..0e34787
--- /dev/null
@@ -0,0 +1,149 @@
+#include <unistd.h>
+
+#include <pbd/abstract_ui.h>
+#include <pbd/pthread_utils.h>
+#include <pbd/failed_constructor.h>
+
+template <typename RequestObject>
+AbstractUI<RequestObject>::AbstractUI (string name, bool with_signal_pipes)
+       : BaseUI (name, with_signal_pipes)
+{
+       if (pthread_key_create (&thread_request_buffer_key, 0)) {
+               cerr << _("cannot create thread request buffer key") << endl;
+               throw failed_constructor();
+       }
+
+       PBD::ThreadCreated.connect (mem_fun (*this, &AbstractUI<RequestObject>::register_thread));
+       PBD::ThreadCreatedWithRequestSize.connect (mem_fun (*this, &AbstractUI<RequestObject>::register_thread_with_request_count));
+}
+
+template <typename RequestObject> void
+AbstractUI<RequestObject>::register_thread (pthread_t thread_id, string name)
+{
+       register_thread_with_request_count (thread_id, name, 256);
+}
+
+template <typename RequestObject> void
+AbstractUI<RequestObject>::register_thread_with_request_count (pthread_t thread_id, string thread_name, uint32_t num_requests)
+{
+       RequestBuffer* b = new RequestBuffer (num_requests);
+
+       {
+        Glib::Mutex::Lock lm (request_buffer_map_lock);
+               request_buffers[thread_id] = b;
+       }
+
+       pthread_setspecific (thread_request_buffer_key, b);
+}
+
+template <typename RequestObject> RequestObject*
+AbstractUI<RequestObject>::get_request (RequestType rt)
+{
+       RequestBuffer* rbuf = static_cast<RequestBuffer*>(pthread_getspecific (thread_request_buffer_key));
+       
+       if (rbuf == 0) {
+               /* Cannot happen, but if it does we can't use the error reporting mechanism */
+               cerr << _("programming error: ")
+                    << string_compose (X_("no %1-UI request buffer found for thread %2"), name(), pthread_name())
+                    << endl;
+               abort ();
+       }
+       
+       RequestBufferVector vec;
+       
+       rbuf->get_write_vector (&vec);
+
+       if (vec.len[0] == 0) {
+               if (vec.len[1] == 0) {
+                       cerr << string_compose (X_("no space in %1-UI request buffer for thread %2"), name(), pthread_name())
+                            << endl;
+                       return 0;
+               } else {
+                       vec.buf[1]->type = rt;
+                       return vec.buf[1];
+               }
+       } else {
+               vec.buf[0]->type = rt;
+               return vec.buf[0];
+       }
+}
+
+template <typename RequestObject> void
+AbstractUI<RequestObject>::handle_ui_requests ()
+{
+       RequestBufferMapIterator i;
+
+       request_buffer_map_lock.lock ();
+
+       for (i = request_buffers.begin(); i != request_buffers.end(); ++i) {
+
+               RequestBufferVector vec;
+
+               while (true) {
+
+                       /* we must process requests 1 by 1 because
+                          the request may run a recursive main
+                          event loop that will itself call
+                          handle_ui_requests. when we return
+                          from the request handler, we cannot
+                          expect that the state of queued requests
+                          is even remotely consistent with
+                          the condition before we called it.
+                       */
+
+                       i->second->get_read_vector (&vec);
+
+                       if (vec.len[0] == 0) {
+                               break;
+                       } else {
+                               /* request_factory/copy constructor does a deep
+                                  copy of the Request object,
+                                  unlike Ringbuffer::read()
+                               */
+
+                               RequestObject req (*vec.buf[0]);
+                               i->second->increment_read_ptr (1);
+                               request_buffer_map_lock.unlock ();
+                               do_request (&req);
+                               request_buffer_map_lock.lock ();
+                       } 
+               }
+       }
+
+       request_buffer_map_lock.unlock ();
+}
+
+template <typename RequestObject> void
+AbstractUI<RequestObject>::send_request (RequestObject *req)
+{
+       if (base_instance() == 0) {
+               return; /* XXX is this the right thing to do ? */
+       }
+       
+       if (caller_is_ui_thread()) {
+               // cerr << "GUI thread sent request " << req << " type = " << req->type << endl;
+               do_request (req);
+       } else {        
+               RequestBuffer* rbuf = static_cast<RequestBuffer*> (pthread_getspecific (thread_request_buffer_key));
+
+               if (rbuf == 0) {
+                       /* can't use the error system to report this, because this
+                          thread isn't registered!
+                       */
+                       cerr << _("programming error: ")
+                            << string_compose (X_("AbstractUI::send_request() called from %1, but no request buffer exists for that thread"), pthread_name())
+                            << endl;
+                       abort ();
+               }
+               
+               // cerr << "thread " << pthread_self() << " sent request " << req << " type = " << req->type << endl;
+
+               rbuf->increment_write_ptr (1);
+
+               if (signal_pipe[1] >= 0) {
+                       const char c = 0;
+                       write (signal_pipe[1], &c, 1);
+               }
+       }
+}
+
diff --git a/libs/pbd/pbd/abstract_ui.h b/libs/pbd/pbd/abstract_ui.h
new file mode 100644 (file)
index 0000000..f80db7b
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#ifndef __pbd_abstract_ui_h__
+#define __pbd_abstract_ui_h__
+
+#include <map>
+#include <string>
+#include <pthread.h>
+
+#include <sigc++/sigc++.h>
+
+#include <glibmm/thread.h>
+
+#include <pbd/receiver.h>
+#include <pbd/ringbufferNPT.h>
+#include <pbd/base_ui.h>
+
+class Touchable;
+
+template <class RequestObject>
+class AbstractUI : public BaseUI
+{
+  public:
+       AbstractUI (std::string name, bool with_signal_pipe);
+       virtual ~AbstractUI() {}
+
+       virtual bool caller_is_ui_thread() = 0;
+
+       void call_slot (sigc::slot<void> el_slot) {
+               RequestObject *req = get_request (BaseUI::CallSlot);
+               
+               if (req == 0) {
+                       return;
+               }
+               
+               req->slot = el_slot;
+               send_request (req);
+       }       
+
+       void register_thread (pthread_t, std::string);
+       void register_thread_with_request_count (pthread_t, std::string, uint32_t num_requests);
+
+  protected:
+       typedef RingBufferNPT<RequestObject> RequestBuffer;
+       typedef typename RequestBuffer::rw_vector RequestBufferVector;
+       typedef typename std::map<pthread_t,RequestBuffer*>::iterator RequestBufferMapIterator;
+
+    Glib::Mutex request_buffer_map_lock;
+       typedef std::map<pthread_t,RequestBuffer*> RequestBufferMap;
+       RequestBufferMap request_buffers;
+       pthread_key_t thread_request_buffer_key;
+       RequestObject* get_request (RequestType);
+       void handle_ui_requests ();
+       void send_request (RequestObject *);
+
+       virtual void do_request (RequestObject *) = 0;
+};
+
+#endif /* __pbd_abstract_ui_h__ */
+
+
diff --git a/libs/pbd/pbd/base_ui.h b/libs/pbd/pbd/base_ui.h
new file mode 100644 (file)
index 0000000..b4570f8
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef __pbd_base_ui_h__
+#define __pbd_base_ui_h__
+
+#include <string>
+#include <stdint.h>
+
+#include <sigc++/slot.h>
+#include <sigc++/trackable.h>
+
+class BaseUI : virtual public sigc::trackable {
+  public:
+       BaseUI (std::string name, bool with_signal_pipes);
+       virtual ~BaseUI();
+
+       BaseUI* base_instance() { return base_ui_instance; }
+
+       std::string name() const { return _name; }
+
+       bool ok() const { return _ok; }
+
+       enum RequestType {
+               range_guarantee = ~0
+       };
+
+       struct BaseRequestObject {
+           RequestType type;
+           sigc::slot<void> the_slot;
+       };
+
+       static RequestType new_request_type();
+       static RequestType CallSlot;
+
+  protected:
+       int signal_pipe[2];
+       bool _ok; 
+
+  private:
+       std::string _name; 
+       BaseUI* base_ui_instance;
+
+       static uint32_t rt_bit;
+
+       int setup_signal_pipe ();
+};
+
+#endif /* __pbd_base_ui_h__ */
diff --git a/libs/pbd/pbd/basename.h b/libs/pbd/pbd/basename.h
new file mode 100644 (file)
index 0000000..a7e36ac
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __stupid_basename_h__
+#define __stupid_basename_h__
+
+#include <string>
+
+namespace PBD
+{
+       
+extern std::string basename_nosuffix (const std::string&);
+
+} // namespace PBD
+
+#endif  // __stupid_basename_h__
diff --git a/libs/pbd/pbd/command.h b/libs/pbd/pbd/command.h
new file mode 100644 (file)
index 0000000..35ae011
--- /dev/null
@@ -0,0 +1,36 @@
+/* 
+   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/serializable.h>
+
+class Command : public Serializable
+{
+    public:
+       virtual ~Command() {}
+       virtual void operator() () = 0;
+        virtual void undo() = 0;
+        virtual void redo() { (*this)(); }
+        virtual XMLNode &serialize();
+};
+
+#endif // __lib_pbd_command_h_
diff --git a/libs/pbd/pbd/compose.h b/libs/pbd/pbd/compose.h
new file mode 100644 (file)
index 0000000..0df9519
--- /dev/null
@@ -0,0 +1,393 @@
+/* Defines String::compose(fmt, arg...) for easy, i18n-friendly
+ * composition of strings.
+ *
+ * Version 1.0.
+ *
+ * Copyright (c) 2002 Ole Laursen <olau@hardworking.dk>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ */
+
+//
+// Basic usage is like
+//
+//   std::cout << String::compose("This is a %1x%2 matrix.", rows, cols);
+//
+// See http://www.cs.auc.dk/~olau/compose/ or the included README.compose for
+// more details.
+//
+
+#ifndef STRING_COMPOSE_H
+#define STRING_COMPOSE_H
+
+#include <sstream>
+#include <string>
+#include <list>
+#include <map>                 // for multimap
+
+namespace StringPrivate
+{
+  // the actual composition class - using string::compose is cleaner, so we
+  // hide it here
+  class Composition
+  {
+  public:
+    // initialize and prepare format string on the form "text %1 text %2 etc."
+    explicit Composition(std::string fmt);
+
+    // supply an replacement argument starting from %1
+    template <typename T>
+    Composition &arg(const T &obj);
+
+    // compose and return string
+    std::string str() const;
+
+  private:
+    std::ostringstream os;
+    int arg_no;
+
+    // we store the output as a list - when the output string is requested, the
+    // list is concatenated to a string; this way we can keep iterators into
+    // the list instead of into a string where they're possibly invalidated on
+    // inserting a specification string
+    typedef std::list<std::string> output_list;
+    output_list output;
+
+    // the initial parse of the format string fills in the specification map
+    // with positions for each of the various %?s
+    typedef std::multimap<int, output_list::iterator> specification_map;
+    specification_map specs;
+  };
+
+  // helper for converting spec string numbers
+  inline int char_to_int(char c)
+  {
+    switch (c) {
+    case '0': return 0;
+    case '1': return 1;
+    case '2': return 2;
+    case '3': return 3;
+    case '4': return 4;
+    case '5': return 5;
+    case '6': return 6;
+    case '7': return 7;
+    case '8': return 8;
+    case '9': return 9;
+    default: return -1000;
+    }
+  }
+
+  inline bool is_number(int n)
+  {
+    switch (n) {
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      return true;
+    
+    default:
+      return false;
+    }
+  }
+
+
+  // implementation of class Composition
+  template <typename T>
+  inline Composition &Composition::arg(const T &obj)
+  {
+    os << obj;
+
+    std::string rep = os.str();
+  
+    if (!rep.empty()) {                // manipulators don't produce output
+      for (specification_map::const_iterator i = specs.lower_bound(arg_no),
+            end = specs.upper_bound(arg_no); i != end; ++i) {
+       output_list::iterator pos = i->second;
+       ++pos;
+      
+       output.insert(pos, rep);
+      }
+    
+      os.str(std::string());
+      //os.clear();
+      ++arg_no;
+    }
+  
+    return *this;
+  }
+
+  inline Composition::Composition(std::string fmt)
+    : arg_no(1)
+  {
+    std::string::size_type b = 0, i = 0;
+  
+    // fill in output with the strings between the %1 %2 %3 etc. and
+    // fill in specs with the positions
+    while (i < fmt.length()) {
+      if (fmt[i] == '%' && i + 1 < fmt.length()) {
+       if (fmt[i + 1] == '%') {        // catch %%
+         fmt.replace(i, 2, "%");
+         ++i;
+       }
+       else if (is_number(fmt[i + 1])) { // aha! a spec!
+         // save string
+         output.push_back(fmt.substr(b, i - b));
+       
+         int n = 1;            // number of digits
+         int spec_no = 0;
+
+         do {
+           spec_no += char_to_int(fmt[i + n]);
+           spec_no *= 10;
+           ++n;
+         } while (i + n < fmt.length() && is_number(fmt[i + n]));
+
+         spec_no /= 10;
+         output_list::iterator pos = output.end();
+         --pos;                // safe since we have just inserted a string>
+       
+         specs.insert(specification_map::value_type(spec_no, pos));
+       
+         // jump over spec string
+         i += n;
+         b = i;
+       }
+       else
+         ++i;
+      }
+      else
+       ++i;
+    }
+  
+    if (i - b > 0)             // add the rest of the string
+      output.push_back(fmt.substr(b, i - b));
+  }
+
+  inline std::string Composition::str() const
+  {
+    // assemble string
+    std::string str;
+  
+    for (output_list::const_iterator i = output.begin(), end = output.end();
+        i != end; ++i)
+      str += *i;
+  
+    return str;
+  }
+}
+
+// now for the real thing(s)
+//namespace PBD
+//{
+  // a series of functions which accept a format string on the form "text %1
+  // more %2 less %3" and a number of templated parameters and spits out the
+  // composited string
+  template <typename T1>
+  inline std::string string_compose(const std::string &fmt, const T1 &o1)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1);
+    return c.str();
+  }
+
+  template <typename T1, typename T2>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2);
+    return c.str();
+  }
+
+  template <typename T1, typename T2, typename T3>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2, const T3 &o3)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2).arg(o3);
+    return c.str();
+  }
+
+  template <typename T1, typename T2, typename T3, typename T4>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2, const T3 &o3,
+                            const T4 &o4)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2).arg(o3).arg(o4);
+    return c.str();
+  }
+
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2, const T3 &o3,
+                            const T4 &o4, const T5 &o5)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5);
+    return c.str();
+  }
+
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+           typename T6>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2, const T3 &o3,
+                            const T4 &o4, const T5 &o5, const T6 &o6)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6);
+    return c.str();
+  }
+
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+           typename T6, typename T7>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2, const T3 &o3,
+                            const T4 &o4, const T5 &o5, const T6 &o6,
+                            const T7 &o7)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7);
+    return c.str();
+  }
+
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+           typename T6, typename T7, typename T8>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2, const T3 &o3,
+                            const T4 &o4, const T5 &o5, const T6 &o6,
+                            const T7 &o7, const T8 &o8)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8);
+    return c.str();
+  }
+
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+           typename T6, typename T7, typename T8, typename T9>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2, const T3 &o3,
+                            const T4 &o4, const T5 &o5, const T6 &o6,
+                            const T7 &o7, const T8 &o8, const T9 &o9)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9);
+    return c.str();
+  }
+
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+           typename T6, typename T7, typename T8, typename T9, typename T10>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2, const T3 &o3,
+                            const T4 &o4, const T5 &o5, const T6 &o6,
+                            const T7 &o7, const T8 &o8, const T9 &o9,
+                            const T10 &o10)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
+      .arg(o10);
+    return c.str();
+  }
+  
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+           typename T6, typename T7, typename T8, typename T9, typename T10,
+           typename T11>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2, const T3 &o3,
+                            const T4 &o4, const T5 &o5, const T6 &o6,
+                            const T7 &o7, const T8 &o8, const T9 &o9,
+                            const T10 &o10, const T11 &o11)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
+      .arg(o10).arg(o11);
+    return c.str();
+  }
+
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+           typename T6, typename T7, typename T8, typename T9, typename T10,
+           typename T11, typename T12>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2, const T3 &o3,
+                            const T4 &o4, const T5 &o5, const T6 &o6,
+                            const T7 &o7, const T8 &o8, const T9 &o9,
+                            const T10 &o10, const T11 &o11, const T12 &o12)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
+      .arg(o10).arg(o11).arg(o12);
+    return c.str();
+  }
+
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+           typename T6, typename T7, typename T8, typename T9, typename T10,
+           typename T11, typename T12, typename T13>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2, const T3 &o3,
+                            const T4 &o4, const T5 &o5, const T6 &o6,
+                            const T7 &o7, const T8 &o8, const T9 &o9,
+                            const T10 &o10, const T11 &o11, const T12 &o12,
+                            const T13 &o13)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
+      .arg(o10).arg(o11).arg(o12).arg(o13);
+    return c.str();
+  }
+
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+           typename T6, typename T7, typename T8, typename T9, typename T10,
+           typename T11, typename T12, typename T13, typename T14>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2, const T3 &o3,
+                            const T4 &o4, const T5 &o5, const T6 &o6,
+                            const T7 &o7, const T8 &o8, const T9 &o9,
+                            const T10 &o10, const T11 &o11, const T12 &o12,
+                            const T13 &o13, const T14 &o14)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
+      .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14);
+    return c.str();
+  }
+
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+           typename T6, typename T7, typename T8, typename T9, typename T10,
+           typename T11, typename T12, typename T13, typename T14,
+           typename T15>
+  inline std::string string_compose(const std::string &fmt,
+                            const T1 &o1, const T2 &o2, const T3 &o3,
+                            const T4 &o4, const T5 &o5, const T6 &o6,
+                            const T7 &o7, const T8 &o8, const T9 &o9,
+                            const T10 &o10, const T11 &o11, const T12 &o12,
+                            const T13 &o13, const T14 &o14, const T15 &o15)
+  {
+    StringPrivate::Composition c(fmt);
+    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
+      .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15);
+    return c.str();
+  }
+//}
+
+
+#endif // STRING_COMPOSE_H
diff --git a/libs/pbd/pbd/controllable.h b/libs/pbd/pbd/controllable.h
new file mode 100644 (file)
index 0000000..c46e477
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef __pbd_controllable_h__
+#define __pbd_controllable_h__
+
+#include <sigc++/trackable.h>
+#include <sigc++/signal.h>
+
+#include <pbd/stateful.h>
+#include <pbd/id.h>
+
+class XMLNode;
+
+namespace PBD {
+
+class Controllable : public virtual sigc::trackable, public Stateful {
+  public:
+       Controllable ();
+       virtual ~Controllable() { GoingAway (this); }
+
+       virtual void set_value (float) = 0;
+       virtual float get_value (void) const = 0;
+
+       virtual bool can_send_feedback() const { return true; }
+
+       sigc::signal<void> LearningFinished;
+
+       static sigc::signal<void,Controllable*> Created;
+       static sigc::signal<void,Controllable*> GoingAway;
+
+
+       static sigc::signal<bool,PBD::Controllable*> StartLearning;
+       static sigc::signal<void,PBD::Controllable*> StopLearning;
+
+       sigc::signal<void> Changed;
+
+       const PBD::ID& id() const { return _id; }
+
+       int set_state (const XMLNode&) { return 0; }
+       XMLNode& get_state ();
+
+  private:
+       PBD::ID _id;
+};
+
+}
+
+#endif /* __pbd_controllable_h__ */
diff --git a/libs/pbd/pbd/convert.h b/libs/pbd/pbd/convert.h
new file mode 100644 (file)
index 0000000..12e63ba
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+    Copyright (C) 2002 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.
+
+*/
+
+#ifndef __pbd_convert_h__
+#define __pbd_convert_h__
+
+#include <string>
+#include <vector>
+
+namespace PBD {
+
+std::string short_version (std::string, std::string::size_type target_length);
+
+int    atoi (const std::string&);
+double atof (const std::string&);
+void   url_decode (std::string&);
+
+std::string length2string (const int32_t frames, const float sample_rate);
+
+std::vector<std::string> internationalize (const char **);
+
+} //namespace PBD
+
+#endif /* __pbd_convert_h__ */
diff --git a/libs/pbd/pbd/error.h b/libs/pbd/pbd/error.h
new file mode 100644 (file)
index 0000000..4136f02
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+    Copyright (C) 1998-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
+    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$
+*/
+#ifndef __libpbd_error_h__
+#define __libpbd_error_h__
+
+#include "transmitter.h"
+
+namespace PBD {
+       extern Transmitter error;
+       extern Transmitter info;
+       extern Transmitter warning;
+       extern Transmitter fatal;
+}
+
+#endif  // __libpbd_error_h__
diff --git a/libs/pbd/pbd/failed_constructor.h b/libs/pbd/pbd/failed_constructor.h
new file mode 100644 (file)
index 0000000..62eb6c0
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __pbd_failed_constructor_h__
+#define __pbd_failed_constructor_h__
+
+#include <exception>
+
+class failed_constructor : public std::exception {
+  public:
+       virtual const char *what() const throw() { return "failed constructor"; }
+};
+
+#endif /* __pbd_failed_constructor_h__ */
diff --git a/libs/pbd/pbd/fastlog.h b/libs/pbd/pbd/fastlog.h
new file mode 100644 (file)
index 0000000..4269705
--- /dev/null
@@ -0,0 +1,40 @@
+/* Copyright unknown. Code by Laurent de Soras <laurent@ohmforce.com>.
+ */
+
+#ifndef __pbd_fastlog_h__
+#define __pbd_fastlog_h__
+
+#include <math.h> /* for HUGE_VAL */
+
+static inline float fast_log2 (float val)
+{
+       /* don't use reinterpret_cast<> because that prevents this
+          from being used by pure C code (for example, GnomeCanvasItems)
+       */
+       union {float f; int i;} t;
+       t.f = val;
+       int * const    exp_ptr =  &t.i;
+       int            x = *exp_ptr;
+       const int      log_2 = ((x >> 23) & 255) - 128;
+       x &= ~(255 << 23);
+       x += 127 << 23;
+       *exp_ptr = x;
+       
+       val = ((-1.0f/3) * t.f + 2) * t.f - 2.0f/3;
+       
+       return (val + log_2);
+}
+
+static inline float fast_log (const float val)
+{
+       return (fast_log2 (val) * 0.69314718f);
+}
+
+static inline float fast_log10 (const float val)
+{
+       return fast_log2(val) / 3.312500f;
+}
+
+static inline float minus_infinity() { return -HUGE_VAL; }
+
+#endif /* __pbd_fastlog_h__ */
diff --git a/libs/pbd/pbd/forkexec.h b/libs/pbd/pbd/forkexec.h
new file mode 100644 (file)
index 0000000..2af3711
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __forkexec_h__
+#define __forkexec_h__
+
+#include <unistd.h>
+
+pid_t forkexec(char **argv, char **envp, int outpipe[2], int inpipe[2]);
+pid_t forkexec_cmd(char *cmd, char **envp, int outpipe[2], int inpipe[2]);
+
+#endif // __forkexec_h__
diff --git a/libs/pbd/pbd/id.h b/libs/pbd/pbd/id.h
new file mode 100644 (file)
index 0000000..9a3f104
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __pbd_id_h__
+#define __pbd_id_h__
+
+#include <stdint.h>
+#include <string>
+
+#include <glibmm/thread.h>
+
+namespace PBD {
+
+class ID {
+  public:
+       ID ();
+       ID (std::string);
+       
+       bool operator== (const ID& other) const {
+               return id == other.id; 
+       }
+
+       bool operator!= (const ID& other) const {
+               return id != other.id;
+       }
+
+       ID& operator= (std::string); 
+
+       bool operator< (const ID& other) const {
+               return id < other.id;
+       }
+
+       void print (char* buf) const;
+       
+       static uint64_t counter() { return _counter; }
+       static void init_counter (uint64_t val) { _counter = val; }
+       static void init ();
+
+  private:
+       uint64_t id;
+       int string_assign (std::string);
+
+       static Glib::Mutex* counter_lock;
+       static uint64_t _counter;
+};
+
+}
+std::ostream& operator<< (std::ostream& ostr, const PBD::ID&);
+
+#endif /* __pbd_id_h__ */
diff --git a/libs/pbd/pbd/mathfix.h b/libs/pbd/pbd/mathfix.h
new file mode 100644 (file)
index 0000000..f0dc7e4
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+    Copyright (C) 2005 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$
+*/
+
+#ifndef __pbd_mathfix_h__
+#define __pbd_mathfix_h__
+
+/* this is necessary to support older releases of OSX where
+   they moved around some of the standard math functions
+*/
+
+#ifdef __APPLE__
+#define powf pow
+#define sqrtf sqrt
+#endif
+
+
+#endif
diff --git a/libs/pbd/pbd/memento_command.h b/libs/pbd/pbd/memento_command.h
new file mode 100644 (file)
index 0000000..c8bfe5d
--- /dev/null
@@ -0,0 +1,94 @@
+/* 
+   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 <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 &serialize() {}
+        //{
+            // obj.id
+            // key is "MementoCommand" or something
+            // before and after mementos
+        //}
+        // 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 &serialize() {}
+    //{
+        // obj.id
+        // key is "MementoCommand" or something
+        // before and after mementos
+    //}
+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 &serialize() {}
+    //{
+        // obj.id
+        // key is "MementoCommand" or something
+        // before and after mementos
+    //}
+protected:
+    obj_T &obj;
+    XMLNode &after;
+};
+
+#endif // __lib_pbd_memento_h__
diff --git a/libs/pbd/pbd/mountpoint.h b/libs/pbd/pbd/mountpoint.h
new file mode 100644 (file)
index 0000000..86ccc58
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#ifndef __pbd_mountpoint_h__
+#define __pbd_mountpoint_h__
+
+#include <string>
+
+std::string mountpoint (std::string path);
+
+#endif // __pbd_mountpoint_h__
diff --git a/libs/pbd/pbd/path.h b/libs/pbd/pbd/path.h
new file mode 100644 (file)
index 0000000..0b77a7c
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+   Copyright (C) 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 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#ifndef PBD_PATH
+#define PBD_PATH
+
+#include <string>
+#include <vector>
+
+namespace PBD {
+
+using std::string;
+using std::vector;
+
+/**
+       The Path class is a helper class for getting a vector of absolute 
+       paths contained in a path string where a path string contains
+       absolute directory paths separated by a colon(:) or a semi-colon(;)
+       on windows.
+  */
+class Path {
+public:
+
+       /**
+         Create an empty Path.
+         */
+       Path ();
+
+       /**
+         Initialize Path from a string, each absolute path contained
+         in the "path" will be accessed to ensure it exists and is 
+         readable.
+         \param path A path string.
+         */
+       Path (const string& path);
+
+       /**
+         Initialize Path from a vector of path strings, each absolute 
+         path contained in paths will be accessed to ensure it 
+         exists and is readable.
+         \param path A path string.
+         */
+       Path (const vector<string>& paths);
+       
+       Path(const Path& path);
+
+       /**
+         Indicate whether there are any directories in m_dirs, if Path is
+         initialized with an empty string as the result of for instance
+         calling Glib::getenv where the environment variable doesn't 
+         exist or if none of the directories in the path string are 
+         accessible then false is returned.
+         
+         \return true if there are any paths in m_paths.
+         */
+       //operator bool () const { return !m_dirs.empty(); }
+               
+       /**
+         \return vector containing the absolute paths to the directories
+         contained
+         */
+       operator const vector<string>& () const { return m_dirs; }
+
+       /**
+         \return vector containing the absolute paths to the directories
+         contained
+         */
+       const vector<string>& dirs () const { return m_dirs; }
+
+       const string path_string() const;
+       
+       const Path& operator= (const Path& path);
+       
+       const Path& operator+= (const string& directory_path);
+       
+       Path& add_subdirectory_to_path (const string& subdirectory);
+
+protected:
+       
+       friend const Path operator+ (const Path&, const Path&);
+
+       bool readable_directory (const string& directory_path);
+
+       void add_readable_directory (const string& directory_path);
+
+       void add_readable_directories (const vector<string>& paths);
+       
+       vector<string> m_dirs;
+
+};
+
+bool find_file_in_path (const Path& path, const string& filename, string& resulting_path_to_file);
+
+} // namespace PBD
+
+#endif // PBD_PATH
+
+
diff --git a/libs/pbd/pbd/pathscanner.h b/libs/pbd/pbd/pathscanner.h
new file mode 100644 (file)
index 0000000..346e785
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef __libmisc_pathscanner_h__
+#define __libmisc_pathscanner_h__
+
+#include <vector>
+#include <string>
+#include <regex.h>
+
+using std::string;
+using std::vector;
+
+class PathScanner
+
+{
+  public:
+    vector<string *> *operator() (const string &dirpath,
+                                 bool (*filter)(const string &, void *arg),
+                                 void *arg, 
+                                 bool match_fullpath = true,
+                                 bool return_fullpath = true,
+                                 long limit = -1) {
+           return run_scan (dirpath,
+                            (bool (PathScanner::*)(const string &)) 0, 
+                            filter, 
+                            arg,
+                            match_fullpath,
+                            return_fullpath, 
+                            limit);
+    }
+
+    vector<string *> *operator() (const string &dirpath,
+                                 const string &regexp,
+                                 bool match_fullpath = true,
+                                 bool return_fullpath = true,
+                                 long limit = -1);
+
+    
+    string *find_first (const string &dirpath,
+                       const string &regexp,
+                       bool match_fullpath = true,
+                       bool return_fullpath = true);
+
+    string *find_first (const string &dirpath,
+                       bool (*filter)(const string &, void *),
+                       void *arg,
+                       bool match_fullpath = true,
+                       bool return_fullpath = true);
+
+  private:
+    regex_t compiled_pattern;
+    
+    bool regexp_filter (const string &str) {
+           return regexec (&compiled_pattern, str.c_str(), 0, 0, 0) == 0;
+    }
+
+    vector<string *> *run_scan (const string &dirpath,
+                               bool (PathScanner::*mfilter) (const string &),
+                               bool (*filter)(const string &, void *),
+                               void *arg,
+                               bool match_fullpath,
+                               bool return_fullpath,
+                               long limit);
+    
+
+};
+
+#endif // __libmisc_pathscanner_h__
diff --git a/libs/pbd/pbd/pool.h b/libs/pbd/pbd/pool.h
new file mode 100644 (file)
index 0000000..f8e19e7
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#ifndef __qm_pool_h__
+#define __qm_pool_h__
+
+#include <vector>
+#include <string>
+
+#include <glibmm/thread.h>
+
+#include <pbd/ringbuffer.h>
+
+class Pool 
+{
+  public:
+       Pool (std::string name, unsigned long item_size, unsigned long nitems);
+       virtual ~Pool ();
+
+       virtual void *alloc ();
+       virtual void release (void *);
+       
+       std::string name() const { return _name; }
+
+  private:
+       RingBuffer<void*>* free_list;
+       std::string _name;
+       void *block;
+};
+
+class SingleAllocMultiReleasePool : public Pool
+{
+  public:
+       SingleAllocMultiReleasePool (std::string name, unsigned long item_size, unsigned long nitems);
+       ~SingleAllocMultiReleasePool ();
+
+       virtual void *alloc ();
+       virtual void release (void *);
+
+  private:
+    Glib::Mutex* m_lock;
+};
+
+
+class MultiAllocSingleReleasePool : public Pool
+{
+  public:
+       MultiAllocSingleReleasePool (std::string name, unsigned long item_size, unsigned long nitems);
+       ~MultiAllocSingleReleasePool ();
+
+       virtual void *alloc ();
+       virtual void release (void *);
+
+  private:
+    Glib::Mutex* m_lock;
+};
+
+#endif // __qm_pool_h__
diff --git a/libs/pbd/pbd/pthread_utils.h b/libs/pbd/pbd/pthread_utils.h
new file mode 100644 (file)
index 0000000..482b5b5
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __pbd_pthread_utils__
+#define __pbd_pthread_utils__
+
+#include <pthread.h>
+#include <signal.h>
+#include <string>
+#include <stdint.h>
+
+#include <sigc++/sigc++.h>
+
+int  pthread_create_and_store (std::string name, pthread_t  *thread, pthread_attr_t *attr, void * (*start_routine)(void *), void * arg);
+void pthread_cancel_one (pthread_t thread);
+void pthread_kill_all (int signum);
+void pthread_cancel_all ();
+void pthread_exit_pbd (void* status);
+std::string pthread_name ();
+
+namespace PBD {
+  extern sigc::signal<void,pthread_t,std::string> ThreadCreated;
+  extern sigc::signal<void,pthread_t,std::string,uint32_t> ThreadCreatedWithRequestSize;
+}
+
+#endif /* __pbd_pthread_utils__ */
diff --git a/libs/pbd/pbd/rcu.h b/libs/pbd/pbd/rcu.h
new file mode 100644 (file)
index 0000000..6d9586c
--- /dev/null
@@ -0,0 +1,120 @@
+#ifndef __pbd_rcu_h__
+#define __pbd_rcu_h__
+
+#include "boost/shared_ptr.hpp"
+#include "glibmm/thread.h"
+#include <list> 
+template<class T>
+class RCUManager
+{
+public:
+       RCUManager (T* new_rcu_value)
+               : m_rcu_value(new_rcu_value)
+       {
+       }
+       virtual ~RCUManager() { }
+       boost::shared_ptr<T> reader () const { return m_rcu_value; }
+       // should be private
+       virtual boost::shared_ptr<T> write_copy () = 0;
+       // should be private
+       virtual void update (boost::shared_ptr<T> new_value) = 0;
+protected:
+       boost::shared_ptr<T> m_rcu_value;
+};
+template<class T>
+class SerializedRCUManager : public RCUManager<T>
+{
+public:
+       SerializedRCUManager(T* new_rcu_value)
+               : RCUManager<T>(new_rcu_value)
+       {
+       }
+       virtual boost::shared_ptr<T> write_copy ()
+       {
+               m_lock.lock();
+               // I hope this is doing what I think it is doing :)
+               boost::shared_ptr<T> new_copy(new T(*RCUManager<T>::m_rcu_value));
+               // XXX todo remove old copies with only 1 reference from the list.
+               return new_copy;
+       }
+       virtual void update (boost::shared_ptr<T> new_value)
+       {
+               // So a current reader doesn't hold the only reference to
+               // the existing value when we assign it a new value which 
+               // should ensure that deletion of old values doesn't
+               // occur in a reader thread.
+               boost::shared_ptr<T> old_copy = RCUManager<T>::m_rcu_value;
+               // we hold the lock at this point effectively blocking
+               // other writers.
+               RCUManager<T>::m_rcu_value = new_value;
+               // XXX add the old value to the list of old copies.
+               m_lock.unlock();
+       }
+private:
+       Glib::Mutex                     m_lock;
+       std::list<boost::shared_ptr<T> > m_old_values;
+};
+template<class T>
+class RCUWriter
+{
+public:
+       RCUWriter(RCUManager<T>& manager)
+               : m_manager(manager)
+       {
+               m_copy = m_manager.write_copy();        
+       }
+       ~RCUWriter()
+       {
+               // we can check here that the refcount of m_copy is 1
+               if(m_copy.use_count() == 1) {
+                       m_manager.update(m_copy);
+               } else {
+                       // critical error.
+               }
+       }
+       // or operator boost::shared_ptr<T> ();
+       boost::shared_ptr<T> get_copy() { return m_copy; }
+private:
+       RCUManager<T>& m_manager;
+       // preferably this holds a pointer to T
+       boost::shared_ptr<T> m_copy;
+};
+
+#endif /* __pbd_rcu_h__ */
diff --git a/libs/pbd/pbd/receiver.h b/libs/pbd/pbd/receiver.h
new file mode 100644 (file)
index 0000000..5ce238d
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#ifndef __libmisc_receiver_h__
+#define __libmisc_receiver_h__
+
+#include <vector>
+
+#include <sigc++/sigc++.h>
+
+#include "transmitter.h"
+
+using std::vector;
+
+class strstream;
+
+class Receiver : virtual public sigc::trackable
+{
+  public:
+       Receiver ();
+       virtual ~Receiver ();
+       
+       void listen_to (Transmitter &);
+       void hangup ();
+
+  protected:
+       virtual void receive (Transmitter::Channel, const char *) = 0;
+
+  private:
+       vector<sigc::connection *> connections;
+};
+
+#endif  // __libmisc_receiver_h__
diff --git a/libs/pbd/pbd/restartable_rw.h b/libs/pbd/pbd/restartable_rw.h
new file mode 100644 (file)
index 0000000..ee84e4e
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __libmisc_restartable_rw__h__
+#define __libmisc_restartable_rw__h__
+
+extern int restartable_write (int fd, unsigned char *buf, size_t cnt);
+extern int restartable_read (int fd, unsigned char *buf, size_t cnt);
+
+#endif // __libmisc_restartable_rw__h__
diff --git a/libs/pbd/pbd/ringbuffer.h b/libs/pbd/pbd/ringbuffer.h
new file mode 100644 (file)
index 0000000..1d9c9b0
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+    Copyright (C) 2000 Paul Davis & Benno Senoner
+
+    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$
+*/
+
+#ifndef ringbuffer_h
+#define ringbuffer_h
+
+//#include <sys/mman.h>
+
+#include <glib.h>
+
+template<class T>
+class RingBuffer 
+{
+  public:
+       RingBuffer (size_t sz) {
+               size_t power_of_two;
+               
+               for (power_of_two = 1; 1U<<power_of_two < sz; power_of_two++);
+               
+               size = 1<<power_of_two;
+               size_mask = size;
+               size_mask -= 1;
+               buf = new T[size];
+               reset ();
+
+       };
+       
+       virtual ~RingBuffer() {
+               delete [] buf;
+       }
+
+       void reset () {
+               /* !!! NOT THREAD SAFE !!! */
+               g_atomic_int_set (&write_ptr, 0);
+               g_atomic_int_set (&read_ptr, 0);
+       }
+
+       void set (size_t r, size_t w) {
+               /* !!! NOT THREAD SAFE !!! */
+               g_atomic_int_set (&write_ptr, w);
+               g_atomic_int_set (&read_ptr, r);
+       }
+       
+       size_t  read  (T *dest, size_t cnt);
+       size_t  write (T *src, size_t cnt);
+
+       struct rw_vector {
+           T *buf[2];
+           size_t len[2];
+       };
+
+       void get_read_vector (rw_vector *);
+       void get_write_vector (rw_vector *);
+       
+       void decrement_read_ptr (size_t cnt) {
+               g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) - cnt) & size_mask);
+       }                
+
+       void increment_read_ptr (size_t cnt) {
+               g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) + cnt) & size_mask);
+       }                
+
+       void increment_write_ptr (size_t cnt) {
+               g_atomic_int_set (&write_ptr,  (g_atomic_int_get(&write_ptr) + cnt) & size_mask);
+       }                
+
+       size_t write_space () {
+               size_t w, r;
+               
+               w = g_atomic_int_get (&write_ptr);
+               r = g_atomic_int_get (&read_ptr);
+               
+               if (w > r) {
+                       return ((r - w + size) & size_mask) - 1;
+               } else if (w < r) {
+                       return (r - w) - 1;
+               } else {
+                       return size - 1;
+               }
+       }
+       
+       size_t read_space () {
+               size_t w, r;
+               
+               w = g_atomic_int_get (&write_ptr);
+               r = g_atomic_int_get (&read_ptr);
+               
+               if (w > r) {
+                       return w - r;
+               } else {
+                       return (w - r + size) & size_mask;
+               }
+       }
+
+       T *buffer () { return buf; }
+       size_t get_write_ptr () const { return g_atomic_int_get (&write_ptr); }
+       size_t get_read_ptr () const { return g_atomic_int_get (&read_ptr); }
+       size_t bufsize () const { return size; }
+
+  protected:
+       T *buf;
+       size_t size;
+       mutable gint write_ptr;
+       mutable gint read_ptr;
+       size_t size_mask;
+};
+
+template<class T> size_t
+RingBuffer<T>::read (T *dest, size_t cnt)
+{
+        size_t free_cnt;
+        size_t cnt2;
+        size_t to_read;
+        size_t n1, n2;
+        size_t priv_read_ptr;
+
+        priv_read_ptr=g_atomic_int_get(&read_ptr);
+
+        if ((free_cnt = read_space ()) == 0) {
+                return 0;
+        }
+
+        to_read = cnt > free_cnt ? free_cnt : cnt;
+        
+        cnt2 = priv_read_ptr + to_read;
+
+        if (cnt2 > size) {
+                n1 = size - priv_read_ptr;
+                n2 = cnt2 & size_mask;
+        } else {
+                n1 = to_read;
+                n2 = 0;
+        }
+        
+        memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T));
+        priv_read_ptr = (priv_read_ptr + n1) & size_mask;
+
+        if (n2) {
+                memcpy (dest+n1, buf, n2 * sizeof (T));
+                priv_read_ptr = n2;
+        }
+
+        g_atomic_int_set(&read_ptr, priv_read_ptr);
+        return to_read;
+}
+
+template<class T> size_t
+RingBuffer<T>::write (T *src, size_t cnt)
+
+{
+        size_t free_cnt;
+        size_t cnt2;
+        size_t to_write;
+        size_t n1, n2;
+        size_t priv_write_ptr;
+
+        priv_write_ptr=g_atomic_int_get(&write_ptr);
+
+        if ((free_cnt = write_space ()) == 0) {
+                return 0;
+        }
+
+        to_write = cnt > free_cnt ? free_cnt : cnt;
+        
+        cnt2 = priv_write_ptr + to_write;
+
+        if (cnt2 > size) {
+                n1 = size - priv_write_ptr;
+                n2 = cnt2 & size_mask;
+        } else {
+                n1 = to_write;
+                n2 = 0;
+        }
+
+        memcpy (&buf[priv_write_ptr], src, n1 * sizeof (T));
+        priv_write_ptr = (priv_write_ptr + n1) & size_mask;
+
+        if (n2) {
+                memcpy (buf, src+n1, n2 * sizeof (T));
+                priv_write_ptr = n2;
+        }
+
+        g_atomic_int_set(&write_ptr, priv_write_ptr);
+        return to_write;
+}
+
+template<class T> void
+RingBuffer<T>::get_read_vector (RingBuffer<T>::rw_vector *vec)
+
+{
+       size_t free_cnt;
+       size_t cnt2;
+       size_t w, r;
+       
+       w = g_atomic_int_get (&write_ptr);
+       r = g_atomic_int_get (&read_ptr);
+       
+       if (w > r) {
+               free_cnt = w - r;
+       } else {
+               free_cnt = (w - r + size) & size_mask;
+       }
+
+       cnt2 = r + free_cnt;
+
+       if (cnt2 > size) {
+               /* Two part vector: the rest of the buffer after the
+                  current write ptr, plus some from the start of 
+                  the buffer.
+               */
+
+               vec->buf[0] = &buf[r];
+               vec->len[0] = size - r;
+               vec->buf[1] = buf;
+               vec->len[1] = cnt2 & size_mask;
+
+       } else {
+               
+               /* Single part vector: just the rest of the buffer */
+               
+               vec->buf[0] = &buf[r];
+               vec->len[0] = free_cnt;
+               vec->len[1] = 0;
+       }
+}
+
+template<class T> void
+RingBuffer<T>::get_write_vector (RingBuffer<T>::rw_vector *vec)
+
+{
+       size_t free_cnt;
+       size_t cnt2;
+       size_t w, r;
+       
+       w = g_atomic_int_get (&write_ptr);
+       r = g_atomic_int_get (&read_ptr);
+       
+       if (w > r) {
+               free_cnt = ((r - w + size) & size_mask) - 1;
+       } else if (w < r) {
+               free_cnt = (r - w) - 1;
+       } else {
+               free_cnt = size - 1;
+       }
+       
+       cnt2 = w + free_cnt;
+
+       if (cnt2 > size) {
+               
+               /* Two part vector: the rest of the buffer after the
+                  current write ptr, plus some from the start of 
+                  the buffer.
+               */
+
+               vec->buf[0] = &buf[w];
+               vec->len[0] = size - w;
+               vec->buf[1] = buf;
+               vec->len[1] = cnt2 & size_mask;
+       } else {
+               vec->buf[0] = &buf[w];
+               vec->len[0] = free_cnt;
+               vec->len[1] = 0;
+       }
+}
+
+
+#endif /* __ringbuffer_h__ */
diff --git a/libs/pbd/pbd/ringbufferNPT.h b/libs/pbd/pbd/ringbufferNPT.h
new file mode 100644 (file)
index 0000000..fee2efc
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+    Copyright (C) 2000 Paul Davis & Benno Senoner
+
+    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$
+*/
+
+#ifndef ringbuffer_npt_h
+#define ringbuffer_npt_h
+
+//#include <sys/mman.h>
+
+#include <glib.h>
+
+/* ringbuffer class where the element size is not required to be a power of two */
+
+template<class T>
+class RingBufferNPT
+{
+  public:
+       RingBufferNPT (size_t sz) {
+               size = sz;
+               buf = new T[size];
+               reset ();
+
+       };
+       
+       virtual ~RingBufferNPT() {
+               delete [] buf;
+       }
+
+       void reset () {
+               /* !!! NOT THREAD SAFE !!! */
+               g_atomic_int_set (&write_ptr, 0);
+               g_atomic_int_set (&read_ptr, 0);
+       }
+
+       void set (size_t r, size_t w) {
+               /* !!! NOT THREAD SAFE !!! */
+               g_atomic_int_set (&write_ptr, w);
+               g_atomic_int_set (&read_ptr, r);
+       }
+       
+       size_t  read  (T *dest, size_t cnt);
+       size_t  write (T *src, size_t cnt);
+
+       struct rw_vector {
+           T *buf[2];
+           size_t len[2];
+       };
+
+       void get_read_vector (rw_vector *);
+       void get_write_vector (rw_vector *);
+       
+       void decrement_read_ptr (size_t cnt) {
+               g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) - cnt) % size);
+       }                
+
+       void increment_read_ptr (size_t cnt) {
+               g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) + cnt) % size);
+       }                
+
+       void increment_write_ptr (size_t cnt) {
+               g_atomic_int_set (&write_ptr,  (g_atomic_int_get(&write_ptr) + cnt) % size);
+       }                
+
+       size_t write_space () {
+               size_t w, r;
+               
+               w = g_atomic_int_get (&write_ptr);
+               r = g_atomic_int_get (&read_ptr);
+               
+               if (w > r) {
+                       return ((r - w + size) % size) - 1;
+               } else if (w < r) {
+                       return (r - w) - 1;
+               } else {
+                       return size - 1;
+               }
+       }
+       
+       size_t read_space () {
+               size_t w, r;
+               
+               w = g_atomic_int_get (&write_ptr);
+               r = g_atomic_int_get (&read_ptr);
+               
+               if (w > r) {
+                       return w - r;
+               } else {
+                       return (w - r + size) % size;
+               }
+       }
+
+       T *buffer () { return buf; }
+       size_t get_write_ptr () const { return g_atomic_int_get (&write_ptr); }
+       size_t get_read_ptr () const { return g_atomic_int_get (&read_ptr); }
+       size_t bufsize () const { return size; }
+
+  protected:
+       T *buf;
+       size_t size;
+       mutable gint write_ptr;
+       mutable gint read_ptr;
+};
+
+template<class T> size_t
+RingBufferNPT<T>::read (T *dest, size_t cnt)
+{
+        size_t free_cnt;
+        size_t cnt2;
+        size_t to_read;
+        size_t n1, n2;
+        size_t priv_read_ptr;
+
+        priv_read_ptr=g_atomic_int_get(&read_ptr);
+
+        if ((free_cnt = read_space ()) == 0) {
+                return 0;
+        }
+
+        to_read = cnt > free_cnt ? free_cnt : cnt;
+        
+        cnt2 = priv_read_ptr + to_read;
+
+        if (cnt2 > size) {
+                n1 = size - priv_read_ptr;
+                n2 = cnt2 % size;
+        } else {
+                n1 = to_read;
+                n2 = 0;
+        }
+        
+        memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T));
+        priv_read_ptr = (priv_read_ptr + n1) % size;
+
+        if (n2) {
+                memcpy (dest+n1, buf, n2 * sizeof (T));
+                priv_read_ptr = n2;
+        }
+
+        g_atomic_int_set(&read_ptr, priv_read_ptr);
+        return to_read;
+}
+
+template<class T> size_t
+RingBufferNPT<T>::write (T *src, size_t cnt)
+{
+        size_t free_cnt;
+        size_t cnt2;
+        size_t to_write;
+        size_t n1, n2;
+        size_t priv_write_ptr;
+
+        priv_write_ptr=g_atomic_int_get(&write_ptr);
+
+        if ((free_cnt = write_space ()) == 0) {
+                return 0;
+        }
+
+        to_write = cnt > free_cnt ? free_cnt : cnt;
+        
+        cnt2 = priv_write_ptr + to_write;
+
+        if (cnt2 > size) {
+                n1 = size - priv_write_ptr;
+                n2 = cnt2 % size;
+        } else {
+                n1 = to_write;
+                n2 = 0;
+        }
+
+        memcpy (&buf[priv_write_ptr], src, n1 * sizeof (T));
+        priv_write_ptr = (priv_write_ptr + n1) % size;
+
+        if (n2) {
+                memcpy (buf, src+n1, n2 * sizeof (T));
+                priv_write_ptr = n2;
+        }
+
+        g_atomic_int_set(&write_ptr, priv_write_ptr);
+        return to_write;
+}
+
+template<class T> void
+RingBufferNPT<T>::get_read_vector (RingBufferNPT<T>::rw_vector *vec)
+{
+       size_t free_cnt;
+       size_t cnt2;
+       size_t w, r;
+       
+       w = g_atomic_int_get (&write_ptr);
+       r = g_atomic_int_get (&read_ptr);
+       
+       if (w > r) {
+               free_cnt = w - r;
+       } else {
+               free_cnt = (w - r + size) % size;
+       }
+
+       cnt2 = r + free_cnt;
+
+       if (cnt2 > size) {
+               /* Two part vector: the rest of the buffer after the
+                  current write ptr, plus some from the start of 
+                  the buffer.
+               */
+
+               vec->buf[0] = &buf[r];
+               vec->len[0] = size - r;
+               vec->buf[1] = buf;
+               vec->len[1] = cnt2 % size;
+
+       } else {
+               
+               /* Single part vector: just the rest of the buffer */
+               
+               vec->buf[0] = &buf[r];
+               vec->len[0] = free_cnt;
+               vec->len[1] = 0;
+       }
+}
+
+template<class T> void
+RingBufferNPT<T>::get_write_vector (RingBufferNPT<T>::rw_vector *vec)
+{
+       size_t free_cnt;
+       size_t cnt2;
+       size_t w, r;
+       
+       w = g_atomic_int_get (&write_ptr);
+       r = g_atomic_int_get (&read_ptr);
+       
+       if (w > r) {
+               free_cnt = ((r - w + size) % size) - 1;
+       } else if (w < r) {
+               free_cnt = (r - w) - 1;
+       } else {
+               free_cnt = size - 1;
+       }
+       
+       cnt2 = w + free_cnt;
+
+       if (cnt2 > size) {
+               
+               /* Two part vector: the rest of the buffer after the
+                  current write ptr, plus some from the start of 
+                  the buffer.
+               */
+
+               vec->buf[0] = &buf[w];
+               vec->len[0] = size - w;
+               vec->buf[1] = buf;
+               vec->len[1] = cnt2 % size;
+       } else {
+               vec->buf[0] = &buf[w];
+               vec->len[0] = free_cnt;
+               vec->len[1] = 0;
+       }
+}
+
+#endif /* __ringbuffer_npt_h__ */
diff --git a/libs/pbd/pbd/selectable.h b/libs/pbd/pbd/selectable.h
new file mode 100644 (file)
index 0000000..470bc3c
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#ifndef __selectable_h__
+#define __selectable_h__
+
+#include <list>
+#include <string>
+#include <stdio.h>
+
+#include <sigc++/sigc++.h>
+
+#include <sys/types.h>
+
+namespace Select {
+    enum Condition {
+               Readable = 0x1,
+               Writable = 0x2,
+               Exception = 0x4
+    };
+
+class Selectable : public sigc::trackable
+
+{
+  public:
+       Selectable (int fd);
+       Selectable (const std::string &, int flags, int mode = 0);
+       Selectable (FILE *);
+       ~Selectable ();
+
+       sigc::signal<void,Selectable *,Select::Condition> readable;
+       sigc::signal<void,Selectable *,Select::Condition> writable;
+       sigc::signal<void,Selectable *,Select::Condition> exceptioned;
+
+       int  fd() { return _fd; }
+       bool ok() { return _ok; }
+
+  protected:
+       void selected (unsigned int condition);
+       int condition;
+       int _fd;
+
+       friend class Selector;
+
+  private:
+       enum {
+               fromFD,
+               fromPath,
+               fromFILE
+       };
+               
+       bool _ok;
+       int _type;
+       std::string path;
+};
+
+class Selector {
+  private:
+       int post_select (fd_set *, fd_set *, fd_set *);
+       int _max_fd;
+
+       typedef std::list<Selectable *> Selectables;
+       Selectables selectables;
+       pthread_mutex_t list_lock;
+
+       static bool use_list_lock;
+
+  public:
+       Selector ();
+
+       void multithreaded (bool yn) {
+               use_list_lock = yn;
+       }
+       
+       void add (int condition, Selectable *s);
+       void remove (Selectable *);
+       int select (unsigned long usecs);
+};
+
+
+
+} /* namespace */
+
+
+#endif // __selectable_h__
diff --git a/libs/pbd/pbd/serializable.h b/libs/pbd/pbd/serializable.h
new file mode 100644 (file)
index 0000000..f6ac4e9
--- /dev/null
@@ -0,0 +1,33 @@
+/* 
+   Copyright (C) 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
+    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 59 2006-06-15T18:16:20.960977Z fugalh  $
+*/
+
+#ifndef __lib_pbd_serializable_h__
+#define __lib_pbd_serializable_h__
+
+#include <pbd/xml++.h>
+
+class Serializable 
+{
+public:
+    virtual XMLNode &serialize() = 0;
+    virtual ~Serializable() {}
+};
+
+#endif // __lib_pbd_serializable_h__
diff --git a/libs/pbd/pbd/stacktrace.h b/libs/pbd/pbd/stacktrace.h
new file mode 100644 (file)
index 0000000..d7278bd
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __libpbd_stacktrace_h__
+#define __libpbd_stacktrace_h__
+
+#include <ostream>
+
+namespace PBD {
+       void stacktrace (std::ostream& out);
+}
+
+#endif /* __libpbd_stacktrace_h__ */
diff --git a/libs/pbd/pbd/stateful.h b/libs/pbd/pbd/stateful.h
new file mode 100644 (file)
index 0000000..3038f16
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+    Copyright (C) 2000 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: stateful.h 17 2005-09-24 19:13:41Z taybin $
+*/
+
+#ifndef __pbd_stateful_h__
+#define __pbd_stateful_h__
+
+#include <string>
+
+class XMLNode;
+
+class Stateful {
+  public:
+       Stateful();
+       virtual ~Stateful();
+
+       virtual XMLNode& get_state (void) = 0;
+
+       virtual int set_state (const XMLNode&) = 0;
+
+       /* Extra XML nodes */
+
+       void add_extra_xml (XMLNode&);
+       XMLNode *extra_xml (const std::string& str);
+
+       virtual void add_instant_xml (XMLNode&, const std::string& dir);
+       XMLNode *instant_xml (const std::string& str, const std::string& dir);
+
+  protected:
+       XMLNode *_extra_xml;
+       XMLNode *_instant_xml;
+};
+
+#endif /* __pbd_stateful_h__ */
+
diff --git a/libs/pbd/pbd/stl_delete.h b/libs/pbd/pbd/stl_delete.h
new file mode 100644 (file)
index 0000000..6e5bfa0
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#ifndef __libmisc_stl_delete_h__
+#define __libmisc_stl_delete_h__
+
+/* To actually use any of these deletion functions, you need to
+   first include the revelant container type header.
+*/
+#if defined(_CPP_VECTOR) || defined(_GLIBCXX_VECTOR) || defined(__SGI_STL_VECTOR)
+template<class T> void vector_delete (std::vector<T *> *vec) 
+{
+       typename std::vector<T *>::iterator i;
+       
+       for (i = vec->begin(); i != vec->end(); i++) {
+               delete *i;
+       }
+       vec->clear ();
+}
+#endif // _CPP_VECTOR || _GLIBCXX_VECTOR || __SGI_STL_VECTOR
+
+#if defined(_CPP_MAP) || defined(_GLIBCXX_MAP) || defined(__SGI_STL_MAP)
+template<class K, class T> void map_delete (std::map<K, T *> *m) 
+{
+       typename std::map<K, T *>::iterator i;
+
+       for (i = m->begin(); i != m->end(); i++) {
+               delete (*i).second;
+       }
+       m->clear ();
+}
+#endif // _CPP_MAP || _GLIBCXX_MAP || __SGI_STL_MAP
+
+#if defined(_CPP_LIST) || defined(_GLIBCXX_LIST) || defined(__SGI_STL_LIST)
+template<class T> void list_delete (std::list<T *> *l) 
+{
+       typename std::list<T *>::iterator i;
+
+       for (i = l->begin(); i != l->end(); i++) {
+               delete (*i);
+       }
+
+       l->clear ();
+}
+#endif // _CPP_LIST || _GLIBCXX_LIST || __SGI_STL_LIST
+
+#if defined(_CPP_SLIST) || defined(_GLIBCXX_SLIST) || defined(__SGI_STL_SLIST)
+template<class T> void slist_delete (std::slist<T *> *l) 
+{
+       typename std::slist<T *>::iterator i;
+
+       for (i = l->begin(); i != l->end(); i++) {
+               delete (*i);
+       }
+
+       l->clear ();
+}
+#endif // _CPP_SLIST || _GLIBCXX_SLIST || __SGI_STL_SLIST
+
+#if defined(_CPP_SET) || defined(_GLIBCXX_SET) || defined(__SGI_STL_SET)
+template<class T> void set_delete (std::set<T *> *sset) 
+{
+       typename std::set<T *>::iterator i;
+       
+       for (i = sset->begin(); i != sset->end(); i++) {
+               delete *i;
+       }
+       sset->erase (sset->begin(), sset->end());
+}
+#endif // _CPP_SET || _GLIBCXX_SET || __SGI_STL_SET
+
+#endif // __libmisc_stl_delete_h__
diff --git a/libs/pbd/pbd/stl_functors.h b/libs/pbd/pbd/stl_functors.h
new file mode 100644 (file)
index 0000000..4a96e91
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#ifndef __stl_functors_h__
+#define __stl_functors_h__
+
+#include <string>
+
+#ifndef LESS_STRING_P
+struct less<std::string *> {
+    bool operator()(std::string *s1, std::string *s2) const {
+      return *s1 < *s2;
+    }
+};
+#define LESS_STRING_P
+#endif // LESS_STRING_P
+
+#ifndef LESS_CONST_STRING_P
+struct less<const std::string *> {
+    bool operator()(const std::string *s1, const std::string *s2) const {
+       return *s1 < *s2;
+    }
+};
+#define LESS_CONST_STRING_P
+#endif // LESS_CONST_STRING_P
+
+#ifndef LESS_CONST_CHAR_P
+struct less<const char *>
+{
+       bool operator()(const char* s1, const char* s2) const {
+               return strcmp(s1, s2) < 0;
+       }
+};
+#define LESS_CONST_CHAR_P
+#endif // LESS_CONST_CHAR_P
+
+#ifndef LESS_CONST_FLOAT_P
+struct less<const float *>
+{
+       bool operator()(const float *n1, const float *n2) const {
+               return *n1 < *n2;
+       }
+};
+#define LESS_CONST_FLOAT_P
+#endif // LESS_CONST_FLOAT_P
+
+#ifndef EQUAL_TO_CONST_CHAR_P
+struct equal_to<const char *>
+{
+        bool operator()(const char *s1, const char *s2) const {
+               return strcmp (s1, s2) == 0;
+       }
+};
+#define EQUAL_TO_CONST_CHAR_P
+#endif // EQUAL_TO_CONST_CHAR_P
+
+#ifndef EQUAL_TO_STRING_P
+struct equal_to<std::string *>
+{
+        bool operator()(const std::string *s1, const std::string *s2) const {
+               return *s1 == *s2;
+       }
+};
+#define EQUAL_TO_STRING_P
+#endif // EQUAL_TO_STRING_P
+
+#ifndef LESS_CONST_STRING_R
+struct less<const std::string &> {
+    bool operator() (const std::string &s1, const std::string &s2) {
+           return s1 < s2; 
+    }
+};
+#define LESS_CONST_STRING_R
+#endif // EQUAL_TO_STRING_P
+
+#endif // __stl_functors_h__
diff --git a/libs/pbd/pbd/strsplit.h b/libs/pbd/pbd/strsplit.h
new file mode 100644 (file)
index 0000000..e55ad1c
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __pbd_strplit_h__
+#define __pbd_strplit_h__
+
+#include <string>
+#include <vector>
+
+extern void split (std::string, std::vector<std::string>&, char);
+
+#endif // __pbd_strplit_h__
diff --git a/libs/pbd/pbd/textreceiver.h b/libs/pbd/pbd/textreceiver.h
new file mode 100644 (file)
index 0000000..b8bfe5b
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#ifndef __libmisc_textreceiver_h__
+#define __libmisc_textreceiver_h__
+
+#include <string>
+
+#include "receiver.h"
+
+using std::string;
+using std::cout;
+using std::endl;
+
+class TextReceiver : public Receiver 
+{
+  public:
+       TextReceiver (const string &n);
+
+  protected:
+       void receive (Transmitter::Channel, const char *);
+
+  private:
+       string name;
+};
+
+#endif //__libmisc_textreceiver_h__
diff --git a/libs/pbd/pbd/thrown_error.h b/libs/pbd/pbd/thrown_error.h
new file mode 100644 (file)
index 0000000..83cf8ac
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+#ifndef __qm_thrown_error_h__
+#define __qm_thrown_error_h__
+
+#include "transmitter.h"
+
+#define SAFE_THROW(T) \
+        T *sent = new T; \
+        (*sent) << rdbuf(); \
+        throw sent
+
+class ThrownError : public Transmitter {
+  public:
+       ThrownError () : Transmitter (Transmitter::Throw) {}
+  protected:
+       virtual void deliver () = 0;
+};
+
+#endif // __qm_thrown_error_h__
+
+
diff --git a/libs/pbd/pbd/tokenizer.h b/libs/pbd/pbd/tokenizer.h
new file mode 100644 (file)
index 0000000..a976b79
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef PBD_TOKENIZER
+#define PBD_TOKENIZER
+
+#include <iterator>
+#include <string>
+
+namespace PBD {
+
+/**
+    Tokenize string, this should work for standard
+    strings aswell as Glib::ustring. This is a bit of a hack,
+    there are much better string tokenizing patterns out there.
+*/
+template<typename StringType, typename Iter>
+unsigned int
+tokenize(const StringType& str,        
+        const StringType& delims,
+        Iter it)
+{
+    typename StringType::size_type start_pos = 0;
+    typename StringType::size_type end_pos = 0;
+    unsigned int token_count = 0;
+
+    do {
+        start_pos = str.find_first_not_of(delims, start_pos);
+        end_pos = str.find_first_of(delims, start_pos);
+        if (start_pos != end_pos) {
+            if (end_pos == str.npos) {
+                end_pos = str.length();
+            }
+            *it++ = str.substr(start_pos, end_pos - start_pos);
+            ++token_count;
+            start_pos = str.find_first_not_of(delims, end_pos + 1);
+        }
+    } while (start_pos != str.npos);
+
+    if (start_pos != str.npos) {
+        *it++ = str.substr(start_pos, str.length() - start_pos);
+        ++token_count;
+    }
+
+    return token_count;
+}
+
+} // namespace PBD
+
+#endif // PBD_TOKENIZER
+
+
diff --git a/libs/pbd/pbd/touchable.h b/libs/pbd/pbd/touchable.h
new file mode 100644 (file)
index 0000000..0298574
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+    Copyright (C) 1999 Paul Barton-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$
+*/
+
+#ifndef __pbd_touchable_h__
+#define __pbd_touchable_h__
+
+class Touchable
+{
+  public:
+       Touchable() : _delete_after_touch (false) {}
+       virtual ~Touchable() {}
+
+       void set_delete_after_touch (bool yn) { _delete_after_touch = yn; }
+       bool delete_after_touch() const { return _delete_after_touch; }
+
+       virtual void touch () = 0;
+
+  protected:
+       bool _delete_after_touch;
+};
+
+template<class T>
+class DynamicTouchable : public Touchable
+{
+  public:
+       DynamicTouchable (T& t, void (T::*m)(void)) 
+               : object (t), method (m) { set_delete_after_touch (true); }
+
+       void touch () {
+               (object.*method)();
+       }
+       
+  protected:
+       T& object;
+       void (T::*method)(void);
+};
+
+template<class T1, class T2>
+class DynamicTouchable1 : public Touchable
+{
+  public:
+       DynamicTouchable1 (T1& t, void (T1::*m)(T2), T2 a) 
+               : object (t), method (m), arg (a) { set_delete_after_touch (true); }
+
+       void touch () {
+               (object.*method)(arg);
+       }
+       
+  protected:
+       T1& object;
+       void (T1::*method)(T2);
+       T2 arg;
+};
+
+template<class T1, class T2, class T3>
+class DynamicTouchable2 : public Touchable
+{
+  public:
+       DynamicTouchable2 (T1& t, void (T1::*m)(T2, T3), T2 a1, T3 a2) 
+               : object (t), method (m), arg1 (a1), arg2 (a2) { set_delete_after_touch (true); }
+
+       void touch () {
+               (object.*method)(arg1, arg2);
+       }
+       
+  protected:
+       T1& object;
+       void (T1::*method)(T2,T3);
+       T2 arg1;
+       T3 arg2;
+};
+       
+#endif // __pbd_touchable_h__
diff --git a/libs/pbd/pbd/transmitter.h b/libs/pbd/pbd/transmitter.h
new file mode 100644 (file)
index 0000000..357cb99
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#ifndef __libmisc_transmitter_h__
+#define __libmisc_transmitter_h__
+
+#include <sstream>
+#include <iostream>
+
+#include <sigc++/sigc++.h>
+
+using std::cout;
+using std::cerr;
+using std::endl;
+
+class Transmitter : public std::stringstream
+
+{
+  public:
+       enum Channel {
+               Info,
+               Error,
+               Warning,
+               Fatal,
+               Throw
+       };
+
+       Transmitter (Channel);
+
+       sigc::signal<void,Channel, const char *> &sender() { 
+               return *send;
+       }
+
+       bool does_not_return ();
+
+  protected:
+       virtual void deliver ();
+       friend std::ostream& endmsg (std::ostream &);
+
+  private:
+       Channel channel;
+       sigc::signal<void, Channel, const char *> *send;
+
+       sigc::signal<void, Channel, const char *> info;
+       sigc::signal<void, Channel, const char *> warning;
+       sigc::signal<void, Channel, const char *> error;
+       sigc::signal<void, Channel, const char *> fatal;
+};
+
+/* for EGCS 2.91.66, if this function is not compiled within the same
+   compilation unit as the one where a ThrownError is thrown, then 
+   nothing will catch the error. This is a pretty small function, so
+   inlining it here seems like a reasonable workaround.
+*/
+
+inline std::ostream &
+endmsg (std::ostream &ostr)
+
+{
+       Transmitter *t;
+
+       /* There is a serious bug in the Cygnus/GCC libstdc++ library:
+          cout is not actually an ostream, but a trick was played
+          to make the compiler think that it is. This will cause
+          the dynamic_cast<> to fail with SEGV. So, first check to
+          see if ostr == cout, and handle it specially.
+       */
+
+       if (&ostr == &cout) {
+               cout << endl;
+               return ostr;
+       } else if (&ostr == &cerr) {
+               cerr << endl;
+               return ostr;
+       }
+
+       if ((t = dynamic_cast<Transmitter *> (&ostr)) != 0) {
+               t->deliver ();
+       } else {
+               /* hmm. not a Transmitter, so just put a newline on
+                  it and assume that that will be enough.
+               */
+               
+               ostr << endl;
+       }
+
+       return ostr;
+}
+
+
+extern "C" { void pbd_c_error (const char *); }
+
+#endif // __libmisc_transmitter_h__
diff --git a/libs/pbd/pbd/undo.h b/libs/pbd/pbd/undo.h
new file mode 100644 (file)
index 0000000..33577ed
--- /dev/null
@@ -0,0 +1,99 @@
+/* 
+   Copyright (C) 2002 Brett Viren & 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$
+*/
+
+#ifndef __lib_pbd_undo_h__
+#define __lib_pbd_undo_h__
+
+#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 UndoTransaction : public Command
+{
+  public:
+       UndoTransaction ();
+       UndoTransaction (const UndoTransaction&);
+       UndoTransaction& operator= (const UndoTransaction&);
+
+       void clear ();
+
+       void add_command (Command *const);
+
+        void operator() ();
+       void undo();
+       void redo();
+
+       XMLNode &serialize();
+       
+       void set_name (const string& str) {
+               _name = str;
+       }
+       const string& name() const { return _name; }
+
+       void set_timestamp (struct timeval &t) {
+               _timestamp = t;
+       }
+
+       const struct timeval& timestamp() const {
+               return _timestamp;
+       }
+
+  private:
+       list<Command*>   actions;
+       struct timeval   _timestamp;
+       string           _name;
+};
+
+class UndoHistory
+{
+  public:
+       UndoHistory() {}
+       ~UndoHistory() {}
+       
+       void add (UndoTransaction ut);
+       void undo (unsigned int n);
+       void redo (unsigned int n);
+       
+       unsigned long undo_depth() const { return UndoList.size(); }
+       unsigned long redo_depth() const { return RedoList.size(); }
+       
+       string next_undo() const { return (UndoList.empty() ? string("") : UndoList.back().name()); }
+       string next_redo() const { return (RedoList.empty() ? string("") : RedoList.back().name()); }
+
+       void clear ();
+       void clear_undo ();
+       void clear_redo ();
+
+  private:
+       list<UndoTransaction> UndoList;
+       list<UndoTransaction> RedoList;
+};
+
+
+#endif /* __lib_pbd_undo_h__ */
diff --git a/libs/pbd/pbd/whitespace.h b/libs/pbd/pbd/whitespace.h
new file mode 100644 (file)
index 0000000..6620a8f
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __pbd_whitespace_h__
+#define __pbd_whitespace_h__
+
+#include <string>
+
+extern void strip_whitespace_edges (std::string& str);
+
+#endif // __pbd_whitespace_h__
diff --git a/libs/pbd/pbd/xml++.h b/libs/pbd/pbd/xml++.h
new file mode 100644 (file)
index 0000000..5dcb4f0
--- /dev/null
@@ -0,0 +1,125 @@
+/* xml++.h
+ * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
+ * are covered by the GNU Lesser General Public License, which should be
+ * included with libxml++ as the file COPYING.
+ */
+
+#include <string>
+#include <list>
+#include <map>
+#include <cstdio>
+#include <cstdarg>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#ifndef __XML_H
+#define __XML_H
+
+using std::string;
+using std::map;
+using std::list;
+
+class XMLTree;
+class XMLNode;
+class XMLProperty;
+
+typedef list<XMLNode *> XMLNodeList;
+typedef XMLNodeList::iterator XMLNodeIterator;
+typedef XMLNodeList::const_iterator XMLNodeConstIterator;
+typedef list<XMLProperty*> XMLPropertyList;
+typedef XMLPropertyList::iterator XMLPropertyIterator;
+typedef XMLPropertyList::const_iterator XMLPropertyConstIterator;
+typedef map<string, XMLProperty*> XMLPropertyMap;
+
+class XMLTree {
+private:
+  string _filename;
+  XMLNode *_root;
+  int _compression;
+
+public:
+  XMLTree();
+  XMLTree(const string &fn);
+  XMLTree(const XMLTree *);
+  ~XMLTree();
+
+  XMLNode *root() const { return _root; };
+  XMLNode *set_root(XMLNode *n) { return _root = n; };
+
+  const string & filename() const { return _filename; };
+  const string & set_filename(const string &fn) { return _filename = fn; };
+
+  int compression() const { return _compression; };
+  int set_compression(int);
+
+  bool read();
+  bool read(const string &fn) { set_filename(fn); return read(); };
+  bool read_buffer(const string &);
+
+  bool write() const;
+  bool write(const string &fn) { set_filename(fn); return write(); };
+
+  void debug (FILE*) const;
+
+  const string & write_buffer() const;
+};
+
+class XMLNode {
+private:
+  string _name;
+  bool _is_content;
+  string _content;
+  XMLNodeList _children;
+  XMLPropertyList _proplist;
+  XMLPropertyMap _propmap;
+
+public:
+  XMLNode(const string &);
+  XMLNode(const string &, const string &);
+  XMLNode(const XMLNode&);
+  ~XMLNode();
+
+  const string name() const { return _name; };
+
+  bool is_content() const { return _is_content; };
+  const string & content() const { return _content; };
+  const string & set_content (const string &);
+  XMLNode *add_content(const string & = string());
+
+  const XMLNodeList & children (const string & = string()) const;
+  XMLNode *add_child (const char *);
+  XMLNode *add_child_copy (const XMLNode&);
+  void add_child_nocopy (XMLNode&);
+
+  const XMLPropertyList & properties() const { return _proplist; };
+  XMLProperty *property(const char * );
+  const XMLProperty *property(const char * n) const
+       { return ((XMLNode *) this)->property(n); };
+  XMLProperty *add_property(const char *, const string &);
+  XMLProperty *add_property(const char *, const char * = "");
+
+  void remove_property(const string &);
+
+  /** Remove all nodes with the name passed to remove_nodes */
+  void remove_nodes(const string &);
+  /** Remove and delete all nodes with the name passed to remove_nodes */
+  void remove_nodes_and_delete(const string &);
+};
+
+class XMLProperty {
+private:
+  string _name;
+  string _value;
+
+public:
+  XMLProperty(const string &n, const string &v = string());
+  ~XMLProperty();
+
+  const string & name() const { return _name; };
+  const string & value() const { return _value; };
+  const string & set_value(const string &v) { return _value = v; };
+};
+
+#endif /* __XML_H */
+
diff --git a/libs/pbd/pool.cc b/libs/pbd/pool.cc
new file mode 100644 (file)
index 0000000..be8032b
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#include <iostream>
+#include <vector>
+
+#include <pbd/pool.h>
+#include <pbd/error.h>
+
+using namespace std;
+using namespace PBD;
+
+Pool::Pool (string n, unsigned long item_size, unsigned long nitems)
+{
+       _name = n;
+
+       free_list = new RingBuffer<void*> (nitems);
+
+       /* since some overloaded ::operator new() might use this,
+          its important that we use a "lower level" allocator to
+          get more space.  
+       */
+
+       block = malloc (nitems * item_size);
+
+       void **ptrlist = (void **) malloc (sizeof (void *)  * nitems);
+
+       for (unsigned long i = 0; i < nitems; i++) {
+               ptrlist[i] = static_cast<void *> (static_cast<char*>(block) + (i * item_size));
+       }
+
+       free_list->write (ptrlist, nitems);
+
+       free (ptrlist);
+}
+
+Pool::~Pool ()
+{
+       free (block);
+}
+
+void *
+Pool::alloc ()
+{
+       void *ptr;
+
+//     cerr << _name << " pool " << " alloc, thread = " << pthread_name() << " space = " << free_list->read_space() << endl;
+
+       if (free_list->read (&ptr, 1) < 1) {
+               fatal << "CRITICAL: " << _name << " POOL OUT OF MEMORY - RECOMPILE WITH LARGER SIZE!!" << endmsg;
+               /*NOTREACHED*/
+               return 0;
+       } else {
+               return ptr;
+       }
+}
+
+void           
+Pool::release (void *ptr)
+{
+       free_list->write (&ptr, 1);
+//     cerr << _name << ": release, now has " << free_list->read_space() << endl;
+}
+
+/*---------------------------------------------*/
+
+MultiAllocSingleReleasePool::MultiAllocSingleReleasePool (string n, unsigned long isize, unsigned long nitems) 
+       : Pool (n, isize, nitems),
+        m_lock(0)
+{
+}
+
+MultiAllocSingleReleasePool::~MultiAllocSingleReleasePool ()
+{
+    if(m_lock) delete m_lock;
+}
+
+SingleAllocMultiReleasePool::SingleAllocMultiReleasePool (string n, unsigned long isize, unsigned long nitems) 
+       : Pool (n, isize, nitems),
+    m_lock(0)
+{
+}
+
+SingleAllocMultiReleasePool::~SingleAllocMultiReleasePool ()
+{
+    if(m_lock) delete m_lock;
+}
+
+void*
+MultiAllocSingleReleasePool::alloc ()
+{
+       void *ptr;
+    if(!m_lock) {
+        m_lock = new Glib::Mutex();
+        // umm, I'm not sure that this doesn't also allocate memory.
+        if(!m_lock) error << "cannot create Glib::Mutex in pool.cc" << endmsg;
+    }
+    
+    Glib::Mutex::Lock guard(*m_lock);
+       ptr = Pool::alloc ();
+       return ptr;
+}
+
+void
+MultiAllocSingleReleasePool::release (void* ptr)
+{
+       Pool::release (ptr);
+}
+
+void*
+SingleAllocMultiReleasePool::alloc ()
+{
+       return Pool::alloc ();
+}
+
+void
+SingleAllocMultiReleasePool::release (void* ptr)
+{
+    if(!m_lock) {
+        m_lock = new Glib::Mutex();
+        // umm, I'm not sure that this doesn't also allocate memory.
+        if(!m_lock) error << "cannot create Glib::Mutex in pool.cc" << endmsg;
+    }
+    Glib::Mutex::Lock guard(*m_lock);
+       Pool::release (ptr);
+}
+
diff --git a/libs/pbd/pthread_utils.cc b/libs/pbd/pthread_utils.cc
new file mode 100644 (file)
index 0000000..db242ce
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+    Copyright (C) 2002 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$
+*/
+
+#include <map>
+#include <iostream>
+#include <string>
+#include <stdint.h>
+
+#include <pbd/pthread_utils.h>
+
+using namespace std;
+
+typedef std::map<string,pthread_t> ThreadMap;
+static ThreadMap all_threads;
+static pthread_mutex_t thread_map_lock = PTHREAD_MUTEX_INITIALIZER;
+
+namespace PBD {
+   sigc::signal<void,pthread_t,std::string> ThreadCreated;
+   sigc::signal<void,pthread_t,std::string,uint32_t> ThreadCreatedWithRequestSize;
+}
+
+using namespace PBD;
+
+int  
+pthread_create_and_store (string name, pthread_t  *thread, pthread_attr_t *attr, void * (*start_routine)(void *), void * arg)
+{
+       int ret;
+
+       if ((ret = pthread_create (thread, attr, start_routine, arg)) == 0) {
+               std::pair<string,pthread_t> newpair;
+               newpair.first = name;
+               newpair.second = *thread;
+
+               pthread_mutex_lock (&thread_map_lock);
+               all_threads.insert (newpair);
+
+               pthread_mutex_unlock (&thread_map_lock);
+       }
+       
+       return ret;
+}
+
+string
+pthread_name ()
+{
+       pthread_t self = pthread_self();
+       string str;
+
+       pthread_mutex_lock (&thread_map_lock);
+       for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
+               if (i->second == self) {
+                       str = i->first;
+                       pthread_mutex_unlock (&thread_map_lock);
+                       return str;
+               }
+       }
+       pthread_mutex_unlock (&thread_map_lock);
+       return "unknown";
+}
+
+void
+pthread_kill_all (int signum) 
+{      
+       pthread_mutex_lock (&thread_map_lock);
+       for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
+               if (i->second != pthread_self()) {
+                       pthread_kill (i->second, signum);
+               }
+       }
+       all_threads.clear();
+       pthread_mutex_unlock (&thread_map_lock);
+}
+
+void
+pthread_cancel_all () 
+{      
+       pthread_mutex_lock (&thread_map_lock);
+       for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
+               if (i->second != pthread_self()) {
+                       pthread_cancel (i->second);
+               }
+       }
+       all_threads.clear();
+       pthread_mutex_unlock (&thread_map_lock);
+}
+
+void
+pthread_cancel_one (pthread_t thread) 
+{      
+       pthread_mutex_lock (&thread_map_lock);
+       for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
+               if (i->second == thread) {
+                       all_threads.erase (i);
+                       break;
+               }
+       }
+
+       pthread_cancel (thread);
+       pthread_mutex_unlock (&thread_map_lock);
+}
+
+void
+pthread_exit_pbd (void* status) 
+{      
+       pthread_t thread = pthread_self();
+
+       pthread_mutex_lock (&thread_map_lock);
+       for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
+               if (i->second == thread) {
+                       all_threads.erase (i);
+                       break;
+               }
+       }
+       pthread_mutex_unlock (&thread_map_lock);
+       pthread_exit (status);
+}
diff --git a/libs/pbd/receiver.cc b/libs/pbd/receiver.cc
new file mode 100644 (file)
index 0000000..5e7c10d
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#include <vector>
+
+#include <pbd/receiver.h>
+#include <pbd/transmitter.h>
+
+using namespace sigc;
+
+Receiver::Receiver () {}
+
+Receiver::~Receiver ()
+
+{
+       hangup ();
+}
+
+void
+Receiver::hangup ()
+{
+       vector<sigc::connection *>::iterator i;
+
+       for (i = connections.begin(); i != connections.end (); i++) {
+               (*i)->disconnect ();
+               delete *i;
+       }
+
+       connections.erase (connections.begin(), connections.end());
+}
+
+void
+Receiver::listen_to (Transmitter &transmitter)
+
+{
+       sigc::connection *c = new sigc::connection;
+
+       (*c) = transmitter.sender().connect(mem_fun(*this, &Receiver::receive));
+
+       connections.push_back (c);
+}
diff --git a/libs/pbd/stacktrace.cc b/libs/pbd/stacktrace.cc
new file mode 100644 (file)
index 0000000..1e7dfa0
--- /dev/null
@@ -0,0 +1,42 @@
+#include <pbd/stacktrace.h>
+#include <iostream>
+
+/* Obtain a backtrace and print it to stdout. */
+
+#ifdef HAVE_EXECINFO
+
+#include <execinfo.h>
+#include <stdlib.h>
+
+void
+PBD::stacktrace (std::ostream& out)
+{
+       void *array[200];
+       size_t size;
+       char **strings;
+       size_t i;
+     
+       size = backtrace (array, 200);
+       strings = backtrace_symbols (array, size);
+     
+       if (strings) {
+
+               printf ("Obtained %zd stack frames.\n", size);
+               
+               for (i = 0; i < size; i++) {
+                       out << strings[i] << std::endl;
+               }
+               
+               free (strings);
+       }
+}
+
+#else
+
+void
+PBD::stacktrace (std::ostream& out)
+{
+       out << "stack tracing is not enabled on this platform" << std::endl;
+}
+
+#endif /* HAVE_EXECINFO */
diff --git a/libs/pbd/stateful.cc b/libs/pbd/stateful.cc
new file mode 100644 (file)
index 0000000..786410e
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+    Copyright (C) 2000-2001 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: stateful.cc 629 2006-06-21 23:01:03Z paul $
+*/
+
+#include <unistd.h>
+
+#include <pbd/stateful.h>
+#include <pbd/xml++.h>
+#include <pbd/error.h>
+
+#include "i18n.h"
+
+using namespace PBD;
+
+Stateful::Stateful ()
+{
+       _extra_xml = 0;
+       _instant_xml = 0;
+}
+
+Stateful::~Stateful ()
+{
+       // Do not delete _extra_xml.  The use of add_child_nocopy() 
+       // means it needs to live on indefinately.
+
+       if (_instant_xml) {
+               delete _instant_xml;
+       }
+}
+
+void
+Stateful::add_extra_xml (XMLNode& node)
+{
+       if (_extra_xml == 0) {
+               _extra_xml = new XMLNode ("extra");
+       }
+
+       _extra_xml->remove_nodes (node.name());
+       _extra_xml->add_child_nocopy (node);
+}
+
+XMLNode *
+Stateful::extra_xml (const string& str)
+{
+       if (_extra_xml == 0) {
+               return 0;
+       }
+
+       const XMLNodeList& nlist = _extra_xml->children();
+       XMLNodeConstIterator i;
+
+       for (i = nlist.begin(); i != nlist.end(); ++i) {
+               if ((*i)->name() == str) {
+                       return (*i);
+               }
+       }
+
+       return 0;
+}
+
+void
+Stateful::add_instant_xml (XMLNode& node, const string& dir)
+{
+       if (_instant_xml == 0) {
+               _instant_xml = new XMLNode ("instant");
+       }
+
+       _instant_xml->remove_nodes_and_delete (node.name());
+       _instant_xml->add_child_copy (node);
+       
+       XMLTree tree;
+       tree.set_filename(dir+"/instant.xml");
+
+       /* Important: the destructor for an XMLTree deletes
+          all of its nodes, starting at _root. We therefore
+          cannot simply hand it our persistent _instant_xml 
+          node as its _root, because we will lose it whenever
+          the Tree goes out of scope.
+
+          So instead, copy the _instant_xml node (which does 
+          a deep copy), and hand that to the tree.
+       */
+
+       XMLNode* copy = new XMLNode (*_instant_xml);
+       tree.set_root (copy);
+
+       if (!tree.write()) {
+               error << string_compose(_("Error: could not write %1"), dir+"/instant.xml") << endmsg;
+       }
+}
+
+XMLNode *
+Stateful::instant_xml (const string& str, const string& dir)
+{
+       if (_instant_xml == 0) {
+               string instant_file = dir + "/instant.xml";
+               if (access(instant_file.c_str(), F_OK) == 0) {
+                       XMLTree tree;
+                       if (tree.read(dir+"/instant.xml")) {
+                               _instant_xml = new XMLNode(*(tree.root()));
+                       } else {
+                               warning << string_compose(_("Could not understand XML file %1"), instant_file) << endmsg;
+                               return 0;
+                       }
+               } else {
+                       return 0;
+               }
+       }
+
+       const XMLNodeList& nlist = _instant_xml->children();
+       XMLNodeConstIterator i;
+
+       for (i = nlist.begin(); i != nlist.end(); ++i) {
+               if ((*i)->name() == str) {
+                       return (*i);
+               }
+       }
+
+       return 0;
+}
diff --git a/libs/pbd/strsplit.cc b/libs/pbd/strsplit.cc
new file mode 100644 (file)
index 0000000..7f29a77
--- /dev/null
@@ -0,0 +1,41 @@
+#include <pbd/strsplit.h>
+
+using namespace std;
+
+void
+split (string str, vector<string>& result, char splitchar)
+{      
+       string::size_type pos;
+       string remaining;
+       string::size_type len = str.length();
+       int cnt;
+
+       cnt = 0;
+
+       if (str.empty()) {
+               return;
+       }
+
+       for (string::size_type n = 0; n < len; ++n) {
+               if (str[n] == splitchar) {
+                       cnt++;
+               }
+       }
+
+       if (cnt == 0) {
+               result.push_back (str);
+               return;
+       }
+
+       remaining = str;
+
+       while ((pos = remaining.find_first_of (':')) != string::npos) {
+               result.push_back (remaining.substr (0, pos));
+               remaining = remaining.substr (pos+1);
+       }
+
+       if (remaining.length()) {
+
+               result.push_back (remaining);
+       }
+}
diff --git a/libs/pbd/textreceiver.cc b/libs/pbd/textreceiver.cc
new file mode 100644 (file)
index 0000000..43620e9
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#include <iostream>
+#include <cstdlib>
+
+#include <pbd/textreceiver.h>
+
+TextReceiver::TextReceiver (const string &n)
+
+{
+       name = n;
+}
+
+void
+TextReceiver::receive (Transmitter::Channel chn, const char *str)
+
+{
+       const char *prefix = "";
+
+       switch (chn) {
+       case Transmitter::Error:
+               prefix = ": [ERROR]: ";
+               break;
+       case Transmitter::Info:
+               prefix = ": [INFO]: ";
+               break;
+       case Transmitter::Warning:
+               prefix = ": [WARNING]: ";
+               break;
+       case Transmitter::Fatal:
+               prefix = ": [FATAL]: ";
+               break;
+       case Transmitter::Throw:
+               /* this isn't supposed to happen */
+               abort ();
+       }
+
+       /* note: iostreams are already thread-safe: no external
+          lock required.
+       */
+       
+       cout << name << prefix << str << endl;
+
+       if (chn == Transmitter::Fatal) {
+               exit (9);
+       }
+}
+
diff --git a/libs/pbd/transmitter.cc b/libs/pbd/transmitter.cc
new file mode 100644 (file)
index 0000000..876a9d8
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+    Copyright (C) 1998-99 Paul Barton-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$
+*/
+
+#include <cstdlib>
+#include <signal.h>
+#include <iostream>
+#include <string>
+
+#include <pbd/transmitter.h>
+#include <pbd/error.h>
+
+using std::string;
+using std::ios;
+
+Transmitter::Transmitter (Channel c)
+{
+       channel = c;
+       switch (c) {
+       case Error:
+               send = &error;
+               break;
+       case Warning:
+               send = &warning;
+               break;
+       case Info:
+               send = &info;
+               break;
+       case Fatal:
+               send = &fatal;
+               break;
+       case Throw:
+               /* we should never call Transmitter::deliver
+                  for thrown messages (because its overridden in the
+                  class heirarchy). force a segv if we do.
+               */
+               send = 0;
+               break;
+       }
+}              
+
+void
+Transmitter::deliver ()
+
+{
+       string foo;
+
+       /* NOTE: this is just a default action for a Transmitter or a
+          derived class. Any class can override this to produce some
+          other action when deliver() is called. 
+       */
+
+       *this << '\0';
+
+       /* send the SigC++ signal */
+
+       foo = str();
+       (*send) (channel, foo.c_str());
+
+       /* XXX when or how can we delete this ? */
+       // delete foo;
+
+       /* return to a pristine state */
+
+       clear ();
+       seekp (0, ios::beg);
+       seekg (0, ios::beg);
+
+       /* do the right thing if this should not return */
+       
+       if (does_not_return()) {
+               sigset_t mask;
+               
+               sigemptyset (&mask);
+               sigsuspend (&mask);
+               /*NOTREACHED*/
+               exit (1);
+       } 
+}
+
+bool
+Transmitter::does_not_return ()
+
+{
+       if (channel == Fatal || channel == Throw) {
+               return true;
+       } else {
+               return false;
+       }
+}
+
+
+extern "C" {
+  void pbd_c_error (const char *str)
+  {
+       PBD::error << str << endmsg;
+  }
+}
diff --git a/libs/pbd/undo.cc b/libs/pbd/undo.cc
new file mode 100644 (file)
index 0000000..aa27f95
--- /dev/null
@@ -0,0 +1,143 @@
+/* 
+    Copyright (C) 2001 Brett Viren & 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$
+*/
+
+#include <iostream>
+
+#include <pbd/undo.h>
+
+using namespace std;
+using namespace sigc;
+
+UndoTransaction::UndoTransaction ()
+{
+}
+
+UndoTransaction::UndoTransaction (const UndoTransaction& rhs)
+{
+       _name = rhs._name;
+       clear ();
+       actions.insert(actions.end(),rhs.actions.begin(),rhs.actions.end());
+}
+
+UndoTransaction& 
+UndoTransaction::operator= (const UndoTransaction& rhs)
+{
+       if (this == &rhs) return *this;
+       _name = rhs._name;
+       clear ();
+       actions.insert(actions.end(),rhs.actions.begin(),rhs.actions.end());
+       return *this;
+}
+
+void
+UndoTransaction::add_command (Command *const action)
+{
+       actions.push_back (action);
+}
+
+void
+UndoTransaction::clear ()
+{
+       actions.clear ();
+}
+
+void
+UndoTransaction::operator() ()
+{
+       for (list<Command*>::iterator i = actions.begin(); i != actions.end(); ++i) {
+               (*(*i))();
+       }
+}
+
+void
+UndoTransaction::undo ()
+{
+       cerr << "Undo " << _name << endl;
+       for (list<Command*>::reverse_iterator i = actions.rbegin(); i != actions.rend(); ++i) {
+               (*i)->undo();
+       }
+}
+
+void
+UndoTransaction::redo ()
+{
+       cerr << "Redo " << _name << endl;
+        (*this)();
+}
+
+XMLNode &UndoTransaction::serialize()
+{
+    XMLNode *node = new XMLNode ("UndoTransaction");
+    // TODO
+    return *node;
+}
+
+void
+UndoHistory::add (UndoTransaction ut)
+{
+       UndoList.push_back (ut);
+}
+
+void
+UndoHistory::undo (unsigned int n)
+{
+       while (n--) {
+               if (UndoList.size() == 0) {
+                       return;
+               }
+               UndoTransaction ut = UndoList.back ();
+               UndoList.pop_back ();
+               ut.undo ();
+               RedoList.push_back (ut);
+       }
+}
+
+void
+UndoHistory::redo (unsigned int n)
+{
+       while (n--) {
+               if (RedoList.size() == 0) {
+                       return;
+               }
+               UndoTransaction ut = RedoList.back ();
+               RedoList.pop_back ();
+               ut.redo ();
+               UndoList.push_back (ut);
+       }
+}
+
+void
+UndoHistory::clear_redo ()
+{
+       RedoList.clear ();
+}
+
+void
+UndoHistory::clear_undo ()
+{
+       UndoList.clear ();
+}
+
+void
+UndoHistory::clear ()
+{
+       RedoList.clear ();
+       UndoList.clear ();
+}
diff --git a/libs/pbd/whitespace.cc b/libs/pbd/whitespace.cc
new file mode 100644 (file)
index 0000000..e35a8a8
--- /dev/null
@@ -0,0 +1,44 @@
+#include <pbd/whitespace.h>
+
+using namespace std;
+
+void
+strip_whitespace_edges (string& str)
+{   
+    string::size_type i; 
+    string::size_type len;    
+    string::size_type s;
+                                   
+    len = str.length();
+
+    /* strip front */
+                                       
+    for (i = 0; i < len; ++i) {
+        if (isgraph (str[i])) {
+            break;
+        }
+    }
+
+    /* strip back */
+    
+    if (len > 1) {
+    
+           s = i;
+           i = len - 1;
+           
+           do {
+                   if (isgraph (str[i]) || i == 0) {
+                           break;
+                   }
+
+                   --i;
+
+           } while (true); 
+           
+           str = str.substr (s, (i - s) + 1);
+
+    } else {
+           str = str.substr (s);
+    }
+}
+
diff --git a/libs/pbd/xml++.cc b/libs/pbd/xml++.cc
new file mode 100644 (file)
index 0000000..03fa116
--- /dev/null
@@ -0,0 +1,420 @@
+/* xml++.cc
+ * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
+ * are covered by the GNU Lesser General Public License, which should be
+ * included with libxml++ as the file COPYING.
+ */
+
+#include <pbd/xml++.h>
+#include <libxml/debugXML.h>
+
+static XMLNode *readnode(xmlNodePtr);
+static void writenode(xmlDocPtr, XMLNode *, xmlNodePtr, int);
+
+XMLTree::XMLTree() 
+       : _filename(), 
+       _root(0), 
+       _compression(0)
+{ 
+}
+
+XMLTree::XMLTree(const string &fn)
+       : _filename(fn), 
+       _root(0), 
+       _compression(0)
+{ 
+       read(); 
+}
+
+XMLTree::XMLTree(const XMLTree * from)
+{
+       _filename = from->filename();
+       _root = new XMLNode(*from->root());
+       _compression = from->compression();
+}
+
+XMLTree::~XMLTree()
+{
+       if (_root) {
+               delete _root;
+       }
+}
+
+int 
+XMLTree::set_compression(int c)
+{
+       if (c > 9) {
+               c = 9;
+       } else if (c < 0) {
+               c = 0;
+       }
+       
+       _compression = c;
+       
+       return _compression;
+}
+
+bool 
+XMLTree::read(void)
+{
+       xmlDocPtr doc;
+       
+       if (_root) {
+               delete _root;
+               _root = 0;
+       }
+       
+       xmlKeepBlanksDefault(0);
+       
+       doc = xmlParseFile(_filename.c_str());
+       if (!doc) {
+               return false;
+       }
+       
+       _root = readnode(xmlDocGetRootElement(doc));
+       xmlFreeDoc(doc);
+       
+       return true;
+}
+
+bool 
+XMLTree::read_buffer(const string & buffer)
+{
+       xmlDocPtr doc;
+       
+       _filename = "";
+       
+       if (_root) {
+               delete _root;
+               _root = 0;
+       }
+       
+       doc = xmlParseMemory((char *) buffer.c_str(), buffer.length());
+       if (!doc) {
+               return false;
+       }
+       
+       _root = readnode(xmlDocGetRootElement(doc));
+       xmlFreeDoc(doc);
+       
+       return true;
+}
+
+bool 
+XMLTree::write(void) const
+{
+       xmlDocPtr doc;
+       XMLNodeList children;
+       int result;
+       
+       xmlKeepBlanksDefault(0);
+       doc = xmlNewDoc((xmlChar *) "1.0");
+       xmlSetDocCompressMode(doc, _compression);
+       writenode(doc, _root, doc->children, 1);
+       result = xmlSaveFormatFile(_filename.c_str(), doc, 1);
+       xmlFreeDoc(doc);
+       
+       if (result == -1) {
+               return false;
+       }
+       
+       return true;
+}
+
+void
+XMLTree::debug(FILE* out) const
+{
+    xmlDocPtr doc;
+    XMLNodeList children;
+
+    xmlKeepBlanksDefault(0);
+    doc = xmlNewDoc((xmlChar *) "1.0");
+    xmlSetDocCompressMode(doc, _compression);
+    writenode(doc, _root, doc->children, 1);
+    xmlDebugDumpDocument (out, doc);
+    xmlFreeDoc(doc);
+}
+
+const string & 
+XMLTree::write_buffer(void) const
+{
+       static string retval;
+       char *ptr;
+       int len;
+       xmlDocPtr doc;
+       XMLNodeList children;
+       
+       xmlKeepBlanksDefault(0);
+       doc = xmlNewDoc((xmlChar *) "1.0");
+       xmlSetDocCompressMode(doc, _compression);
+       writenode(doc, _root, doc->children, 1);
+       xmlDocDumpMemory(doc, (xmlChar **) & ptr, &len);
+       xmlFreeDoc(doc);
+       
+       retval = ptr;
+       
+       free(ptr);
+       
+       return retval;
+}
+
+XMLNode::XMLNode(const string & n)
+       :  _name(n), _is_content(false), _content(string())
+{
+}
+
+XMLNode::XMLNode(const string & n, const string & c)
+       :_name(n), _is_content(true), _content(c)
+{
+}
+
+XMLNode::XMLNode(const XMLNode& from)
+{
+       XMLPropertyList props;
+       XMLPropertyIterator curprop;
+       XMLNodeList nodes;
+       XMLNodeIterator curnode;
+       
+       _name = from.name();
+       set_content(from.content());
+       
+       props = from.properties();
+       for (curprop = props.begin(); curprop != props.end(); ++curprop) {
+               add_property((*curprop)->name().c_str(), (*curprop)->value());
+       }
+       
+       nodes = from.children();
+       for (curnode = nodes.begin(); curnode != nodes.end(); ++curnode) {
+               add_child_copy(**curnode);
+       }
+}
+
+XMLNode::~XMLNode()
+{
+       XMLNodeIterator curchild;
+       XMLPropertyIterator curprop;
+       
+       for (curchild = _children.begin(); curchild != _children.end(); ++curchild) {
+               delete *curchild;
+       }
+           
+       for (curprop = _proplist.begin(); curprop != _proplist.end(); ++curprop) {
+               delete *curprop;
+       }
+}
+
+const string & 
+XMLNode::set_content(const string & c)
+{
+       if (c.empty()) {
+               _is_content = false;
+       } else {
+               _is_content = true;
+       }
+           
+       _content = c;
+       
+       return _content;
+}
+
+const XMLNodeList & 
+XMLNode::children(const string & n) const
+{
+       static XMLNodeList retval;
+       XMLNodeConstIterator cur;
+       
+       if (n.length() == 0) {
+               return _children;
+       }
+           
+       retval.erase(retval.begin(), retval.end());
+       
+       for (cur = _children.begin(); cur != _children.end(); ++cur) {
+               if ((*cur)->name() == n) {
+                       retval.insert(retval.end(), *cur);
+               }
+       }
+           
+       return retval;
+}
+
+XMLNode *
+XMLNode::add_child(const char * n)
+{
+       return add_child_copy(XMLNode (n));
+}
+
+void
+XMLNode::add_child_nocopy (XMLNode& n)
+{
+       _children.insert(_children.end(), &n);
+}
+
+XMLNode *
+XMLNode::add_child_copy(const XMLNode& n)
+{
+       XMLNode *copy = new XMLNode (n);
+       _children.insert(_children.end(), copy);
+       return copy;
+}
+
+XMLNode *
+XMLNode::add_content(const string & c)
+{
+       return add_child_copy(XMLNode (string(), c));
+}
+
+XMLProperty *
+XMLNode::property(const char * n)
+{
+       string ns(n);
+       if (_propmap.find(ns) == _propmap.end()) {
+               return 0;
+       }
+       
+       return _propmap[ns];
+}
+
+XMLProperty *
+XMLNode::add_property(const char * n, const string & v)
+{
+       string ns(n);
+       if(_propmap.find(ns) != _propmap.end()){
+               remove_property(ns);
+       }
+
+       XMLProperty *tmp = new XMLProperty(ns, v);
+
+       if (!tmp) {
+               return 0;
+       }
+
+       _propmap[tmp->name()] = tmp;
+       _proplist.insert(_proplist.end(), tmp);
+
+       return tmp;
+}
+
+XMLProperty *
+XMLNode::add_property(const char * n, const char * v)
+{
+       string vs(v);
+       return add_property(n, vs);
+}
+
+void 
+XMLNode::remove_property(const string & n)
+{
+       if (_propmap.find(n) != _propmap.end()) {
+               _proplist.remove(_propmap[n]);
+               _propmap.erase(n);
+       }
+}
+
+void 
+XMLNode::remove_nodes(const string & n)
+{
+       XMLNodeIterator i = _children.begin();
+       XMLNodeIterator tmp;
+       
+       while (i != _children.end()) {
+               tmp = i;
+               ++tmp;
+               if ((*i)->name() == n) {
+                       _children.erase (i);
+               }
+               i = tmp;
+       }
+}
+
+void 
+XMLNode::remove_nodes_and_delete(const string & n)
+{
+       XMLNodeIterator i = _children.begin();
+       XMLNodeIterator tmp;
+       
+       while (i != _children.end()) {
+               tmp = i;
+               ++tmp;
+               if ((*i)->name() == n) {
+                       delete *i;
+                       _children.erase (i);
+               }
+               i = tmp;
+       }
+}
+
+XMLProperty::XMLProperty(const string &n, const string &v)
+       : _name(n), 
+       _value(v) 
+{ 
+}
+
+XMLProperty::~XMLProperty()
+{
+}
+
+static XMLNode *
+readnode(xmlNodePtr node)
+{
+       string name, content;
+       xmlNodePtr child;
+       XMLNode *tmp;
+       xmlAttrPtr attr;
+       
+       if (node->name) {
+               name = (char *) node->name;
+       }
+       
+       tmp = new XMLNode(name);
+       
+       for (attr = node->properties; attr; attr = attr->next) {
+               content = "";
+               if (attr->children) {
+                       content = (char *) attr->children->content;
+               }
+               tmp->add_property((char *) attr->name, content);
+       }
+       
+       if (node->content) {
+               tmp->set_content((char *) node->content);
+       } else {
+               tmp->set_content(string());
+       }
+       
+       for (child = node->children; child; child = child->next) {
+               tmp->add_child_nocopy (*readnode(child));
+       }
+       
+       return tmp;
+}
+
+static void 
+writenode(xmlDocPtr doc, XMLNode * n, xmlNodePtr p, int root = 0)
+{
+       XMLPropertyList props;
+       XMLPropertyIterator curprop;
+       XMLNodeList children;
+       XMLNodeIterator curchild;
+       xmlNodePtr node;
+       
+       if (root) {
+               node = doc->children = xmlNewDocNode(doc, 0, (xmlChar *) n->name().c_str(), 0);
+       } else {
+               node = xmlNewChild(p, 0, (xmlChar *) n->name().c_str(), 0);
+       }
+           
+       if (n->is_content()) {
+               node->type = XML_TEXT_NODE;
+               xmlNodeSetContentLen(node, (const xmlChar *) n->content().c_str(), n->content().length());
+       }
+       
+       props = n->properties();
+       for (curprop = props.begin(); curprop != props.end(); ++curprop) {
+               xmlSetProp(node, (xmlChar *) (*curprop)->name().c_str(), (xmlChar *) (*curprop)->value().c_str());
+       }
+           
+       children = n->children();
+       for (curchild = children.begin(); curchild != children.end(); ++curchild) {
+               writenode(doc, *curchild, node);
+       }
+}
diff --git a/libs/pbd3/.cvsignore b/libs/pbd3/.cvsignore
deleted file mode 100644 (file)
index e9a15e8..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-libpbd.pc
-libpbd.spec
-version.cc
-*.os
-*.dylib
diff --git a/libs/pbd3/AUTHORS b/libs/pbd3/AUTHORS
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/libs/pbd3/COPYING b/libs/pbd3/COPYING
deleted file mode 100644 (file)
index d60c31a..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-                   GNU GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                           Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-\f
-                   GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-\f
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-\f
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-\f
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                           NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                    END OF TERMS AND CONDITIONS
-\f
-           How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year  name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/libs/pbd3/ChangeLog b/libs/pbd3/ChangeLog
deleted file mode 100644 (file)
index 59e9291..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-2005-12-02 Taybin Rutkin <taybin@earthlink.net>
-       * libpbd now allocates warning, info, error, and fatal itself.
-       * Incremented version to 3.1.
-
-2005-04-01 Taybin Rutkin <taybin@earthlink.net>
-       * Updated to support sigc++-2.0.
-       * Incremented version to 3.0.0.
-
-2004-08-04 Taybin Rutkin <taybin@earthlink.net>
-       * Added support for gcc-3.4
diff --git a/libs/pbd3/NEWS b/libs/pbd3/NEWS
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/libs/pbd3/README b/libs/pbd3/README
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/libs/pbd3/SConscript b/libs/pbd3/SConscript
deleted file mode 100644 (file)
index fedb3cd..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-# -*- python -*-
-
-import os
-import os.path
-import glob
-
-Import('env libraries i18n install_prefix')
-
-pbd3 = env.Copy()
-
-domain = 'libpbd'
-
-pbd3.Append(DOMAIN=domain,MAJOR=4,MINOR=0,MICRO=0)
-pbd3.Append(CXXFLAGS="-DPACKAGE=\\\"" + domain + "\\\"")
-pbd3.Append(CXXFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
-pbd3.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
-pbd3.Append(PACKAGE=domain)
-pbd3.Append(POTFILE=domain + '.pot')
-
-pbd3_files = Split("""
-basename.cc
-base_ui.cc
-convert.cc
-command.cc
-dmalloc.cc
-error.cc
-mountpoint.cc
-pathscanner.cc
-pool.cc
-pthread_utils.cc
-receiver.cc
-stacktrace.cc
-strsplit.cc
-textreceiver.cc
-transmitter.cc
-undo.cc
-version.cc
-whitespace.cc
-xml++.cc
-""")
-
-conf = Configure(pbd3)
-if conf.CheckFunc('getmntent'):
-    conf.env.Append(CCFLAGS="-DHAVE_GETMNTENT")
-if conf.CheckCHeader('execinfo.h'):
-    conf.env.Append(CXXFLAGS="-DHAVE_EXECINFO")
-pbd3 = conf.Finish()
-
-pbd3.Merge ([ libraries['sigc2'], libraries['xml'], libraries['glibmm2'], libraries['glib2'] ])
-
-pbd3.VersionBuild(['version.cc','pbd/version.h'], 'SConscript')
-
-libpbd3 = pbd3.SharedLibrary('pbd', pbd3_files)
-
-Default(libpbd3)
-
-if env['NLS']:
-    i18n (pbd3, pbd3_files, env)
-
-env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2'), libpbd3))
-
-env.Alias('tarball', env.Distribute (env['DISTTREE'],
-                                     [ 'SConscript', 'i18n.h', 'gettext.h', 'pbd/abstract_ui.cc' ] +
-                                     pbd3_files +
-                                     glob.glob('po/*.po') +
-                                     glob.glob('pbd/*.h')))
diff --git a/libs/pbd3/base_ui.cc b/libs/pbd3/base_ui.cc
deleted file mode 100644 (file)
index d3c8d5e..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-#include <stdint.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <pbd/base_ui.h>
-#include <pbd/error.h>
-#include <pbd/compose.h>
-#include <pbd/failed_constructor.h>
-
-#include "i18n.h"
-
-using namespace std;
-using namespace PBD;
-       
-uint32_t BaseUI::rt_bit = 1;
-BaseUI::RequestType BaseUI::CallSlot = BaseUI::new_request_type();
-
-BaseUI::BaseUI (string str, bool with_signal_pipe)
-       : _name (str)
-{
-       /* odd pseudo-singleton semantics */
-
-       base_ui_instance = this;
-
-       signal_pipe[0] = -1;
-       signal_pipe[1] = -1;
-
-       if (with_signal_pipe) {
-               if (setup_signal_pipe ()) {
-                       throw failed_constructor ();
-               }
-       }
-}
-
-BaseUI::~BaseUI()
-{
-       if (signal_pipe[0] >= 0) {
-               close (signal_pipe[0]);
-       } 
-
-       if (signal_pipe[1] >= 0) {
-               close (signal_pipe[1]);
-       } 
-}
-
-BaseUI::RequestType
-BaseUI::new_request_type ()
-{
-       RequestType rt;
-
-       /* XXX catch out-of-range */
-
-       rt = RequestType (rt_bit);
-       rt_bit <<= 1;
-
-       return rt;
-}
-
-int
-BaseUI::setup_signal_pipe ()
-{
-       /* setup the pipe that other threads send us notifications/requests
-          through.
-       */
-
-       if (pipe (signal_pipe)) {
-               error << string_compose (_("%1-UI: cannot create error signal pipe (%2)"), _name, std::strerror (errno))
-                     << endmsg;
-
-               return -1;
-       }
-
-       if (fcntl (signal_pipe[0], F_SETFL, O_NONBLOCK)) {
-               error << string_compose (_("%1-UI: cannot set O_NONBLOCK on signal read pipe (%2)"), _name, std::strerror (errno))
-                     << endmsg;
-               return -1;
-       }
-
-       if (fcntl (signal_pipe[1], F_SETFL, O_NONBLOCK)) {
-               error << string_compose (_("%1-UI: cannot set O_NONBLOCK on signal write pipe (%2)"), _name, std::strerror (errno))
-                     << endmsg;
-               return -1;
-       }
-
-       return 0;
-}
-
diff --git a/libs/pbd3/basename.cc b/libs/pbd3/basename.cc
deleted file mode 100644 (file)
index a51e393..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <iostream>
-#include <string.h>
-#include <pbd/basename.h>
-
-
-// implement this using Glib::path_get_basename
-std::string 
-PBD::basename_nosuffix (const std::string& str)
-{
-       std::string::size_type slash = str.find_last_of ('/');
-       std::string noslash;
-
-       if (slash == std::string::npos) {
-               noslash = str;
-       } else {
-               noslash = str.substr (slash+1);
-       }
-
-       return noslash.substr (0, noslash.find_last_of ('.'));
-}
diff --git a/libs/pbd3/command.cc b/libs/pbd3/command.cc
deleted file mode 100644 (file)
index 3f5aca8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <pbd/command.h>
-
-class XMLNode;
-
-XMLNode &Command::serialize()
-{
-    XMLNode *node = new XMLNode ("Command");
-    // TODO
-    return *node;
-}
diff --git a/libs/pbd3/convert.cc b/libs/pbd3/convert.cc
deleted file mode 100644 (file)
index 60d39c9..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
-    Copyright (C) 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
-    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 <cmath>
-#include <stdint.h>
-
-#include "pbd/convert.h"
-
-#include "i18n.h"
-
-using std::string;
-using std::vector;
-
-namespace PBD {
-
-string
-short_version (string orig, string::size_type target_length)
-{
-       /* this tries to create a recognizable abbreviation
-          of "orig" by removing characters until we meet
-          a certain target length.
-
-          note that we deliberately leave digits in the result
-          without modification.
-       */
-
-
-       string::size_type pos;
-
-       /* remove white-space and punctuation, starting at end */
-
-       while (orig.length() > target_length) {
-               if ((pos = orig.find_last_of (_("\"\n\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="))) == string::npos) {
-                       break;
-               }
-               orig.replace (pos, 1, "");
-       }
-
-       /* remove lower-case vowels, starting at end */
-
-       while (orig.length() > target_length) {
-               if ((pos = orig.find_last_of (_("aeiou"))) == string::npos) {
-                       break;
-               }
-               orig.replace (pos, 1, "");
-       }
-
-       /* remove upper-case vowels, starting at end */
-
-       while (orig.length() > target_length) {
-               if ((pos = orig.find_last_of (_("AEIOU"))) == string::npos) {
-                       break;
-               }
-               orig.replace (pos, 1, "");
-       }
-
-       /* remove lower-case consonants, starting at end */
-
-       while (orig.length() > target_length) {
-               if ((pos = orig.find_last_of (_("bcdfghjklmnpqrtvwxyz"))) == string::npos) {
-                       break;
-               }
-               orig.replace (pos, 1, "");
-       }
-
-       /* remove upper-case consonants, starting at end */
-
-       while (orig.length() > target_length) {
-               if ((pos = orig.find_last_of (_("BCDFGHJKLMNPQRTVWXYZ"))) == string::npos) {
-                       break;
-               }
-               orig.replace (pos, 1, "");
-       }
-
-       /* whatever the length is now, use it */
-       
-       return orig;
-}
-
-int
-atoi (const string& s)
-{
-       return std::atoi (s.c_str());
-}
-
-double
-atof (const string& s)
-{
-       return std::atof (s.c_str());
-}
-
-vector<string>
-internationalize (const char **array)
-{
-       vector<string> v;
-
-       for (uint32_t i = 0; array[i]; ++i) {
-               v.push_back (_(array[i]));
-       }
-
-       return v;
-}
-
-static int32_t 
-int_from_hex (char hic, char loc) 
-{
-       int hi;         /* hi byte */
-       int lo;         /* low byte */
-
-       hi = (int) hic;
-
-       if( ('0'<=hi) && (hi<='9') ) {
-               hi -= '0';
-       } else if( ('a'<= hi) && (hi<= 'f') ) {
-               hi -= ('a'-10);
-       } else if( ('A'<=hi) && (hi<='F') ) {
-               hi -= ('A'-10);
-       }
-       
-       lo = (int) loc;
-       
-       if( ('0'<=lo) && (lo<='9') ) {
-               lo -= '0';
-       } else if( ('a'<=lo) && (lo<='f') ) {
-               lo -= ('a'-10);
-       } else if( ('A'<=lo) && (lo<='F') ) {
-               lo -= ('A'-10);
-       }
-
-       return lo + (16 * hi);
-}
-
-void
-url_decode (string& url)
-{
-       string::iterator last;
-       string::iterator next;
-
-       for (string::iterator i = url.begin(); i != url.end(); ++i) {
-               if ((*i) == '+') {
-                       *i = ' ';
-               }
-       }
-
-       if (url.length() <= 3) {
-               return;
-       }
-
-       last = url.end();
-
-       --last; /* points at last char */
-       --last; /* points at last char - 1 */
-
-       for (string::iterator i = url.begin(); i != last; ) {
-
-               if (*i == '%') {
-
-                       next = i;
-
-                       url.erase (i);
-                       
-                       i = next;
-                       ++next;
-                       
-                       if (isxdigit (*i) && isxdigit (*next)) {
-                               /* replace first digit with char */
-                               *i = int_from_hex (*i,*next);
-                               ++i; /* points at 2nd of 2 digits */
-                               url.erase (i);
-                       }
-               } else {
-                       ++i;
-               }
-       }
-}
-
-string
-length2string (const int32_t frames, const float sample_rate)
-{
-    int secs = (int) (frames / sample_rate);
-    int hrs =  secs / 3600;
-    secs -= (hrs * 3600);
-    int mins = secs / 60;
-    secs -= (mins * 60);
-
-    int total_secs = (hrs * 3600) + (mins * 60) + secs;
-    int frames_remaining = (int) floor (frames - (total_secs * sample_rate));
-    float fractional_secs = (float) frames_remaining / sample_rate;
-
-    char duration_str[32];
-    sprintf (duration_str, "%02d:%02d:%05.2f", hrs, mins, (float) secs + fractional_secs);
-
-    return duration_str;
-}
-
-} // namespace PBD
diff --git a/libs/pbd3/dmalloc.cc b/libs/pbd3/dmalloc.cc
deleted file mode 100644 (file)
index 0e73094..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * file that facilitates C++ program debugging.
- *
- * Copyright 1995 by Gray Watson
- *
- * This file is part of the dmalloc package.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * NON-COMMERCIAL purpose and without fee is hereby granted, provided
- * that the above copyright notice and this permission notice appear
- * in all copies, and that the name of Gray Watson not be used in
- * advertising or publicity pertaining to distribution of the document
- * or software without specific, written prior permission.
- *
- * Please see the PERMISSIONS file or contact the author for information
- * about commercial licenses.
- *
- * Gray Watson makes no representations about the suitability of the
- * software described herein for any purpose.  It is provided "as is"
- * without express or implied warranty.
- *
- * The author may be contacted via http://www.letters.com/~gray/
- *
- * $Id$
- */
-
-/*
- * This file is used to effectively redirect new to the more familiar
- * malloc and delete to the more familiar free so they can be debugged
- * with the debug malloc library..  They also give the known error
- * behavior, too.
- *
- * Compile and link this in with the C++ program you want to debug.
- *
- * NOTE: I am not a C++ hacker so feedback in the form of other hints
- * and ideas for C++ users would be much appreciated.
- */
-
-#ifdef DEBUG_MALLOC
-
-extern "C" {
-#include <stdlib.h>
-#include <dmalloc.h>
-#include "/usr/local/src/dmalloc-4.1.2/return.h"
-}
-
-/*
- * An overload function for the C++ new.
- */
-void *
-operator new(size_t size)
-{
-  char *file;
-  GET_RET_ADDR(file);
-
-  /* handle correct C++ semantics for an alloc of size 0 */
-  
-  if (size == 0) size = 1;
-  
-  return _malloc_leap(file, 0, size);
-}
-
-/*
- * An overload function for the C++ new[].
- */
-void *
-operator new[](size_t size)
-{
-  char *file;
-  GET_RET_ADDR(file);
-
-  /* handle correct C++ semantics for an alloc of size 0 */
-  
-  if (size == 0) size = 1;
-
-  return _malloc_leap(file, 0, size);
-}
-
-/*
- * An overload function for the C++ delete.
- */
-void
-operator delete(void *pnt)
-{
-  char *file;
-  GET_RET_ADDR(file);
-  _free_leap(file, 0, pnt);
-}
-
-/*
- * An overload function for the C++ delete[].  Thanks to Jens Krinke
- * <j.krinke@gmx.de>
- */
-void
-operator delete[](void *pnt)
-{
-  char *file;
-  GET_RET_ADDR(file);
-  _free_leap(file, 0, pnt);
-}
-
-#endif
diff --git a/libs/pbd3/error.cc b/libs/pbd3/error.cc
deleted file mode 100644 (file)
index a6f8fb7..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <pbd/error.h>
-
-Transmitter  PBD::error (Transmitter::Error);
-Transmitter  PBD::info (Transmitter::Info);
-Transmitter  PBD::fatal (Transmitter::Fatal);
-Transmitter  PBD::warning (Transmitter::Warning);
-
diff --git a/libs/pbd3/gettext.h b/libs/pbd3/gettext.h
deleted file mode 100644 (file)
index 339c74f..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Convenience header for conditional use of GNU <libintl.h>.
-   Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify it
-   under the terms of the GNU Library General Public License as published
-   by the Free Software Foundation; either version 2, 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
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
-   USA.  */
-
-#ifndef _LIBGETTEXT_H
-#define _LIBGETTEXT_H 1
-
-/* NLS can be disabled through the configure --disable-nls option.  */
-#if ENABLE_NLS
-
-/* Get declarations of GNU message catalog functions.  */
-# include <libintl.h>
-
-#else
-
-/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
-   chokes if dcgettext is defined as a macro.  So include it now, to make
-   later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
-   as well because people using "gettext.h" will not include <libintl.h>,
-   and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
-   is OK.  */
-#if defined(__sun)
-# include <locale.h>
-#endif
-
-/* Disabled NLS.
-   The casts to 'const char *' serve the purpose of producing warnings
-   for invalid uses of the value returned from these functions.
-   On pre-ANSI systems without 'const', the config.h file is supposed to
-   contain "#define const".  */
-
-/* other headers may have included libintl.h */
-
-# undef gettext
-# undef dgettext
-# undef dcgettext
-# undef ngettext
-# undef dngettext
-# undef dcngettext
-# undef textdomain
-# undef bindtextdomain
-# undef bind_textdomain_codeset
-
-# define gettext(Msgid) ((const char *) (Msgid))
-# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
-# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
-# define ngettext(Msgid1, Msgid2, N) \
-    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
-# define dngettext(Domainname, Msgid1, Msgid2, N) \
-    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
-# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
-    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
-# define textdomain(Domainname) ((const char *) (Domainname))
-# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
-# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
-
-#endif
-
-/* A pseudo function call that serves as a marker for the automated
-   extraction of messages, but does not call gettext().  The run-time
-   translation is done at a different place in the code.
-   The argument, String, should be a literal string.  Concatenated strings
-   and other string expressions won't work.
-   The macro's expansion is not parenthesized, so that it is suitable as
-   initializer for static 'char[]' or 'const char[]' variables.  */
-#define gettext_noop(String) String
-
-#endif /* _LIBGETTEXT_H */
diff --git a/libs/pbd3/i18n.h b/libs/pbd3/i18n.h
deleted file mode 100644 (file)
index 7c79d2e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __i18n_h__
-#define __i18n_h__
-
-#include <pbd/compose.h>
-#include "gettext.h"
-
-#define _(Text) dgettext (PACKAGE, Text)
-#define N_(Text) gettext_noop (Text)
-#define X_(Text) (Text)
-
-#endif // __i18n_h__
diff --git a/libs/pbd3/libpbd.pc.in b/libs/pbd3/libpbd.pc.in
deleted file mode 100644 (file)
index 14d0208..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@/pbd
-
-Name: libpbd
-Version: @VERSION@
-Description: libpbd, a library of useful, generic C++ objects
-Requires: 
-Libs: -L${libdir} -lpbd @NON_PKG_LIBS@
-Cflags: -I${includedir} @NON_PKG_CFLAGS@
diff --git a/libs/pbd3/libpbd.spec.in b/libs/pbd3/libpbd.spec.in
deleted file mode 100644 (file)
index d50622d..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-Summary: A general purpose programming library
-%define lib_name pbd
-Name: lib%{lib_name}
-Version: @VERSION@
-Release: 2
-Copyright: GPL
-Source: .
-Url: http://www.quasimodo.org
-Vendor: Paul Davis <paul@linuxaudiosystems.com>
-Packager: jfm3 <jfm3@acm.org>
-Group: System Environment/Libraries
-Prefix: %{_prefix}
-BuildRoot: %{_tmppath}/%{name}-%{version}-root
-
-%description
-
-This library implements a number of programming utilities used by Paul
-Davis (formerly Paul Barton-Davis, hence the name).  It is used in
-some of his Open Source software projects.  See
-http://ardour.sf.net/ for examples.
-
-%prep
-%setup -q
-
-%build
-CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" ./configure $ARCH_FLAGS --prefix=%{prefix}
-make
-
-%install
-rm -rf $RPM_BUILD_ROOT
-install -d -m 755 $RPM_BUILD_ROOT%{prefix}/{{include,lib}/%{lib_name}}
-make install INSTALL="%(which install) -p" prefix=$RPM_BUILD_ROOT%{prefix}
-
-%post
-/sbin/ldconfig
-
-%postun
-/sbin/ldconfig
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%files
-%defattr(-,root,root)
-%doc README AUTHORS NEWS COPYING*
-%{prefix}/lib/libpbd.so*
-
-%package devel
-Summary: A general purpose programming library -- developer version.
-Group: System Environment/Libraries
-
-%description devel
-
-This library implements a number of programming utilities used by Paul
-Davis (formerly Paul Barton-Davis, hence the name).  It is used in
-some of his Open Source software projects.  See
-http://ardour.sf.net/ for examples.
-
-This package holds static libraries and headers needed by developers
-who wish to use libpbd in their programs.
-
-%files devel
-%defattr(-,root,root)
-%{prefix}/include/pbd/*
-%{prefix}/lib/libpbd.a
-%{prefix}/lib/libpbd.la
-%{prefix}/bin/pbd-config
-%{prefix}/share/aclocal/pbd.m4
-%{prefix}/share/aclocal/unique_args.m4
-
diff --git a/libs/pbd3/mountpoint.cc b/libs/pbd3/mountpoint.cc
deleted file mode 100644 (file)
index 160f5e9..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
-    Copyright (C) 2002 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$
-*/
-
-#include <cstdio>
-#include <string>
-#include <limits.h>
-
-#include <pbd/mountpoint.h>
-
-using std::string;
-
-#if HAVE_GETMNTENT
-#include <mntent.h>
-
-struct mntent_sorter {
-    bool operator() (const mntent *a, const mntent *b) {
-           return strcmp (a->mnt_dir, b->mnt_dir);
-    }
-};
-
-string
-mountpoint (string path)
-{
-       FILE *mntf;
-       mntent *mnt;
-       unsigned int maxmatch = 0;
-       unsigned int matchlen;
-       const char *cpath = path.c_str();
-       char best[PATH_MAX+1];
-       
-       if ((mntf = setmntent ("/etc/mtab", "r")) == 0) {
-               return "";
-       }
-
-       best[0] = '\0';
-
-       while ((mnt = getmntent (mntf))) {
-               unsigned int n;
-
-               n = 0;
-               matchlen = 0;
-
-               /* note: strcmp's semantics are not 
-                  strict enough to use for this.
-               */
-
-               while (cpath[n] && mnt->mnt_dir[n]) {
-                       if (cpath[n] != mnt->mnt_dir[n]) {
-                               break;
-                       }
-                       matchlen++;
-                       n++;
-               }
-
-               if (cpath[matchlen] == '\0') {
-
-                       endmntent (mntf);
-                       return mnt->mnt_dir;
-
-               } else {
-
-                       if (matchlen > maxmatch) {
-                               snprintf (best, sizeof(best), "%s", mnt->mnt_dir);
-                               maxmatch = matchlen;
-                       }
-               }
-       }
-
-       endmntent (mntf);
-
-       return best;
-}
-
-#else // no getmntent()
-
-#include <sys/param.h>
-#include <sys/ucred.h>
-#include <sys/mount.h>
-
-string
-mountpoint (string path)
-{
-//XXX IMPLEMENT ME using getmntinfo() or getfsstat().
-       return "/";
-}
-#endif
-
-#ifdef TEST_MOUNTPOINT
-               
-main (int argc, char *argv[])
-{
-       printf ("mp of %s = %s\n", argv[1], mountpoint (argv[1]).c_str());
-       exit (0);
-}
-
-#endif
diff --git a/libs/pbd3/pathscanner.cc b/libs/pbd3/pathscanner.cc
deleted file mode 100644 (file)
index 2af227a..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#include <cstdlib>
-#include <cstdio>
-#include <vector>
-#include <dirent.h>
-
-#include <pbd/error.h>
-#include <pbd/pathscanner.h>
-#include <pbd/stl_delete.h>
-
-using namespace PBD;
-
-vector<string *> *
-PathScanner::operator() (const string &dirpath, const string &regexp,
-                        bool match_fullpath, bool return_fullpath, 
-                        long limit)
-
-{
-       int err;
-       char msg[256];
-
-       if ((err = regcomp (&compiled_pattern, regexp.c_str(),
-                           REG_EXTENDED|REG_NOSUB))) {
-               
-               regerror (err, &compiled_pattern,
-                         msg, sizeof (msg));
-               
-               error << "Cannot compile soundfile regexp for use (" 
-                     << msg 
-                     << ")" 
-                     << endmsg;
-               
-               return 0;
-       }
-       
-       return run_scan (dirpath, &PathScanner::regexp_filter, 
-                        (bool (*)(const string &, void *)) 0,
-                        0,
-                        match_fullpath,
-                        return_fullpath,
-                        limit);
-}      
-
-vector<string *> *
-PathScanner::run_scan (const string &dirpath, 
-                      bool (PathScanner::*memberfilter)(const string &),
-                      bool (*filter)(const string &, void *),
-                      void *arg,
-                      bool match_fullpath, bool return_fullpath,
-                      long limit)
-
-{
-       vector<string *> *result = 0;
-       DIR *dir;
-       struct dirent *finfo;
-       char *pathcopy = strdup (dirpath.c_str());
-       char *thisdir;
-       char fullpath[PATH_MAX+1];
-       string search_str;
-       string *newstr;
-       long nfound = 0;
-
-       if ((thisdir = strtok (pathcopy, ":")) == 0 ||
-           strlen (thisdir) == 0) {
-               free (pathcopy);
-               return 0;
-       }
-
-       result = new vector<string *>;
-
-       do {
-
-               if ((dir = opendir (thisdir)) == 0) {
-                       continue;
-               }
-               
-               while ((finfo = readdir (dir)) != 0) {
-
-                       snprintf (fullpath, sizeof(fullpath), "%s/%s",
-                                 thisdir, finfo->d_name);
-
-                       if (match_fullpath) {
-                               search_str = fullpath;
-                       } else {
-                               search_str = finfo->d_name;
-                       }
-
-                       /* handle either type of function ptr */
-
-                       if (memberfilter) {
-                               if (!(this->*memberfilter)(search_str)) {
-                                       continue;
-                               } 
-                       } else {
-                               if (!filter(search_str, arg)) {
-                                       continue;
-                               }
-                       }
-
-                       if (return_fullpath) {
-                               newstr = new string (fullpath);
-                       } else {
-                               newstr = new string (finfo->d_name);
-                       } 
-
-                       result->push_back (newstr);
-                       nfound++;
-               }
-
-               closedir (dir);
-               
-       } while ((limit < 0 || (nfound < limit)) && (thisdir = strtok (0, ":")));
-
-       free (pathcopy);
-       return result;
-}
-
-string *
-PathScanner::find_first (const string &dirpath,
-                        const string &regexp,
-                        bool match_fullpath,
-                        bool return_fullpath)
-{
-       vector<string *> *res;
-       string *ret;
-       int err;
-       char msg[256];
-
-       if ((err = regcomp (&compiled_pattern, regexp.c_str(),
-                           REG_EXTENDED|REG_NOSUB))) {
-               
-               regerror (err, &compiled_pattern,
-                         msg, sizeof (msg));
-               
-               error << "Cannot compile soundfile regexp for use (" << msg << ")" << endmsg;
-
-               
-               return 0;
-       }
-       
-       res = run_scan (dirpath, 
-                       &PathScanner::regexp_filter,
-                       (bool (*)(const string &, void *)) 0,
-                       0,
-                       match_fullpath,
-                       return_fullpath, 
-                       1);
-       
-       if (res->size() == 0) {
-               ret = 0;
-       } else {
-               ret = res->front();
-       }
-       vector_delete (res);
-       delete res;
-       return ret;
-}
-
-string *
-PathScanner::find_first (const string &dirpath,
-                        bool (*filter)(const string &, void *),
-                        void *arg,
-                        bool match_fullpath,
-                        bool return_fullpath)
-{
-       vector<string *> *res;
-       string *ret;
-
-       res = run_scan (dirpath, 
-                       (bool (PathScanner::*)(const string &)) 0,
-                       filter,
-                       0,
-                       match_fullpath,
-                       return_fullpath, 1);
-       
-       if (res->size() == 0) {
-               ret = 0;
-       } else {
-               ret = res->front();
-       }
-       vector_delete (res);
-       delete res;
-       return ret;
-}
diff --git a/libs/pbd3/pbd/.DS_Store b/libs/pbd3/pbd/.DS_Store
deleted file mode 100644 (file)
index 5008ddf..0000000
Binary files a/libs/pbd3/pbd/.DS_Store and /dev/null differ
diff --git a/libs/pbd3/pbd/.cvsignore b/libs/pbd3/pbd/.cvsignore
deleted file mode 100644 (file)
index 6702033..0000000
+++ /dev/null
@@ -1 +0,0 @@
-version.h
diff --git a/libs/pbd3/pbd/abstract_ui.cc b/libs/pbd3/pbd/abstract_ui.cc
deleted file mode 100644 (file)
index 0e34787..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-#include <unistd.h>
-
-#include <pbd/abstract_ui.h>
-#include <pbd/pthread_utils.h>
-#include <pbd/failed_constructor.h>
-
-template <typename RequestObject>
-AbstractUI<RequestObject>::AbstractUI (string name, bool with_signal_pipes)
-       : BaseUI (name, with_signal_pipes)
-{
-       if (pthread_key_create (&thread_request_buffer_key, 0)) {
-               cerr << _("cannot create thread request buffer key") << endl;
-               throw failed_constructor();
-       }
-
-       PBD::ThreadCreated.connect (mem_fun (*this, &AbstractUI<RequestObject>::register_thread));
-       PBD::ThreadCreatedWithRequestSize.connect (mem_fun (*this, &AbstractUI<RequestObject>::register_thread_with_request_count));
-}
-
-template <typename RequestObject> void
-AbstractUI<RequestObject>::register_thread (pthread_t thread_id, string name)
-{
-       register_thread_with_request_count (thread_id, name, 256);
-}
-
-template <typename RequestObject> void
-AbstractUI<RequestObject>::register_thread_with_request_count (pthread_t thread_id, string thread_name, uint32_t num_requests)
-{
-       RequestBuffer* b = new RequestBuffer (num_requests);
-
-       {
-        Glib::Mutex::Lock lm (request_buffer_map_lock);
-               request_buffers[thread_id] = b;
-       }
-
-       pthread_setspecific (thread_request_buffer_key, b);
-}
-
-template <typename RequestObject> RequestObject*
-AbstractUI<RequestObject>::get_request (RequestType rt)
-{
-       RequestBuffer* rbuf = static_cast<RequestBuffer*>(pthread_getspecific (thread_request_buffer_key));
-       
-       if (rbuf == 0) {
-               /* Cannot happen, but if it does we can't use the error reporting mechanism */
-               cerr << _("programming error: ")
-                    << string_compose (X_("no %1-UI request buffer found for thread %2"), name(), pthread_name())
-                    << endl;
-               abort ();
-       }
-       
-       RequestBufferVector vec;
-       
-       rbuf->get_write_vector (&vec);
-
-       if (vec.len[0] == 0) {
-               if (vec.len[1] == 0) {
-                       cerr << string_compose (X_("no space in %1-UI request buffer for thread %2"), name(), pthread_name())
-                            << endl;
-                       return 0;
-               } else {
-                       vec.buf[1]->type = rt;
-                       return vec.buf[1];
-               }
-       } else {
-               vec.buf[0]->type = rt;
-               return vec.buf[0];
-       }
-}
-
-template <typename RequestObject> void
-AbstractUI<RequestObject>::handle_ui_requests ()
-{
-       RequestBufferMapIterator i;
-
-       request_buffer_map_lock.lock ();
-
-       for (i = request_buffers.begin(); i != request_buffers.end(); ++i) {
-
-               RequestBufferVector vec;
-
-               while (true) {
-
-                       /* we must process requests 1 by 1 because
-                          the request may run a recursive main
-                          event loop that will itself call
-                          handle_ui_requests. when we return
-                          from the request handler, we cannot
-                          expect that the state of queued requests
-                          is even remotely consistent with
-                          the condition before we called it.
-                       */
-
-                       i->second->get_read_vector (&vec);
-
-                       if (vec.len[0] == 0) {
-                               break;
-                       } else {
-                               /* request_factory/copy constructor does a deep
-                                  copy of the Request object,
-                                  unlike Ringbuffer::read()
-                               */
-
-                               RequestObject req (*vec.buf[0]);
-                               i->second->increment_read_ptr (1);
-                               request_buffer_map_lock.unlock ();
-                               do_request (&req);
-                               request_buffer_map_lock.lock ();
-                       } 
-               }
-       }
-
-       request_buffer_map_lock.unlock ();
-}
-
-template <typename RequestObject> void
-AbstractUI<RequestObject>::send_request (RequestObject *req)
-{
-       if (base_instance() == 0) {
-               return; /* XXX is this the right thing to do ? */
-       }
-       
-       if (caller_is_ui_thread()) {
-               // cerr << "GUI thread sent request " << req << " type = " << req->type << endl;
-               do_request (req);
-       } else {        
-               RequestBuffer* rbuf = static_cast<RequestBuffer*> (pthread_getspecific (thread_request_buffer_key));
-
-               if (rbuf == 0) {
-                       /* can't use the error system to report this, because this
-                          thread isn't registered!
-                       */
-                       cerr << _("programming error: ")
-                            << string_compose (X_("AbstractUI::send_request() called from %1, but no request buffer exists for that thread"), pthread_name())
-                            << endl;
-                       abort ();
-               }
-               
-               // cerr << "thread " << pthread_self() << " sent request " << req << " type = " << req->type << endl;
-
-               rbuf->increment_write_ptr (1);
-
-               if (signal_pipe[1] >= 0) {
-                       const char c = 0;
-                       write (signal_pipe[1], &c, 1);
-               }
-       }
-}
-
diff --git a/libs/pbd3/pbd/abstract_ui.h b/libs/pbd3/pbd/abstract_ui.h
deleted file mode 100644 (file)
index f80db7b..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#ifndef __pbd_abstract_ui_h__
-#define __pbd_abstract_ui_h__
-
-#include <map>
-#include <string>
-#include <pthread.h>
-
-#include <sigc++/sigc++.h>
-
-#include <glibmm/thread.h>
-
-#include <pbd/receiver.h>
-#include <pbd/ringbufferNPT.h>
-#include <pbd/base_ui.h>
-
-class Touchable;
-
-template <class RequestObject>
-class AbstractUI : public BaseUI
-{
-  public:
-       AbstractUI (std::string name, bool with_signal_pipe);
-       virtual ~AbstractUI() {}
-
-       virtual bool caller_is_ui_thread() = 0;
-
-       void call_slot (sigc::slot<void> el_slot) {
-               RequestObject *req = get_request (BaseUI::CallSlot);
-               
-               if (req == 0) {
-                       return;
-               }
-               
-               req->slot = el_slot;
-               send_request (req);
-       }       
-
-       void register_thread (pthread_t, std::string);
-       void register_thread_with_request_count (pthread_t, std::string, uint32_t num_requests);
-
-  protected:
-       typedef RingBufferNPT<RequestObject> RequestBuffer;
-       typedef typename RequestBuffer::rw_vector RequestBufferVector;
-       typedef typename std::map<pthread_t,RequestBuffer*>::iterator RequestBufferMapIterator;
-
-    Glib::Mutex request_buffer_map_lock;
-       typedef std::map<pthread_t,RequestBuffer*> RequestBufferMap;
-       RequestBufferMap request_buffers;
-       pthread_key_t thread_request_buffer_key;
-       RequestObject* get_request (RequestType);
-       void handle_ui_requests ();
-       void send_request (RequestObject *);
-
-       virtual void do_request (RequestObject *) = 0;
-};
-
-#endif /* __pbd_abstract_ui_h__ */
-
-
diff --git a/libs/pbd3/pbd/base_ui.h b/libs/pbd3/pbd/base_ui.h
deleted file mode 100644 (file)
index b4570f8..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef __pbd_base_ui_h__
-#define __pbd_base_ui_h__
-
-#include <string>
-#include <stdint.h>
-
-#include <sigc++/slot.h>
-#include <sigc++/trackable.h>
-
-class BaseUI : virtual public sigc::trackable {
-  public:
-       BaseUI (std::string name, bool with_signal_pipes);
-       virtual ~BaseUI();
-
-       BaseUI* base_instance() { return base_ui_instance; }
-
-       std::string name() const { return _name; }
-
-       bool ok() const { return _ok; }
-
-       enum RequestType {
-               range_guarantee = ~0
-       };
-
-       struct BaseRequestObject {
-           RequestType type;
-           sigc::slot<void> the_slot;
-       };
-
-       static RequestType new_request_type();
-       static RequestType CallSlot;
-
-  protected:
-       int signal_pipe[2];
-       bool _ok; 
-
-  private:
-       std::string _name; 
-       BaseUI* base_ui_instance;
-
-       static uint32_t rt_bit;
-
-       int setup_signal_pipe ();
-};
-
-#endif /* __pbd_base_ui_h__ */
diff --git a/libs/pbd3/pbd/basename.h b/libs/pbd3/pbd/basename.h
deleted file mode 100644 (file)
index 35aebe1..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __stupid_basename_h__
-#define __stupid_basename_h__
-
-#include <string>
-
-namespace PBD
-{
-       
-extern std::string basename_nosuffix (const std::string&);
-
-};
-
-#endif  // __stupid_basename_h__
diff --git a/libs/pbd3/pbd/command.h b/libs/pbd3/pbd/command.h
deleted file mode 100644 (file)
index 35ae011..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 
-   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/serializable.h>
-
-class Command : public Serializable
-{
-    public:
-       virtual ~Command() {}
-       virtual void operator() () = 0;
-        virtual void undo() = 0;
-        virtual void redo() { (*this)(); }
-        virtual XMLNode &serialize();
-};
-
-#endif // __lib_pbd_command_h_
diff --git a/libs/pbd3/pbd/compose.h b/libs/pbd3/pbd/compose.h
deleted file mode 100644 (file)
index 0df9519..0000000
+++ /dev/null
@@ -1,393 +0,0 @@
-/* Defines String::compose(fmt, arg...) for easy, i18n-friendly
- * composition of strings.
- *
- * Version 1.0.
- *
- * Copyright (c) 2002 Ole Laursen <olau@hardworking.dk>.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA.
- */
-
-//
-// Basic usage is like
-//
-//   std::cout << String::compose("This is a %1x%2 matrix.", rows, cols);
-//
-// See http://www.cs.auc.dk/~olau/compose/ or the included README.compose for
-// more details.
-//
-
-#ifndef STRING_COMPOSE_H
-#define STRING_COMPOSE_H
-
-#include <sstream>
-#include <string>
-#include <list>
-#include <map>                 // for multimap
-
-namespace StringPrivate
-{
-  // the actual composition class - using string::compose is cleaner, so we
-  // hide it here
-  class Composition
-  {
-  public:
-    // initialize and prepare format string on the form "text %1 text %2 etc."
-    explicit Composition(std::string fmt);
-
-    // supply an replacement argument starting from %1
-    template <typename T>
-    Composition &arg(const T &obj);
-
-    // compose and return string
-    std::string str() const;
-
-  private:
-    std::ostringstream os;
-    int arg_no;
-
-    // we store the output as a list - when the output string is requested, the
-    // list is concatenated to a string; this way we can keep iterators into
-    // the list instead of into a string where they're possibly invalidated on
-    // inserting a specification string
-    typedef std::list<std::string> output_list;
-    output_list output;
-
-    // the initial parse of the format string fills in the specification map
-    // with positions for each of the various %?s
-    typedef std::multimap<int, output_list::iterator> specification_map;
-    specification_map specs;
-  };
-
-  // helper for converting spec string numbers
-  inline int char_to_int(char c)
-  {
-    switch (c) {
-    case '0': return 0;
-    case '1': return 1;
-    case '2': return 2;
-    case '3': return 3;
-    case '4': return 4;
-    case '5': return 5;
-    case '6': return 6;
-    case '7': return 7;
-    case '8': return 8;
-    case '9': return 9;
-    default: return -1000;
-    }
-  }
-
-  inline bool is_number(int n)
-  {
-    switch (n) {
-    case '0':
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-    case '8':
-    case '9':
-      return true;
-    
-    default:
-      return false;
-    }
-  }
-
-
-  // implementation of class Composition
-  template <typename T>
-  inline Composition &Composition::arg(const T &obj)
-  {
-    os << obj;
-
-    std::string rep = os.str();
-  
-    if (!rep.empty()) {                // manipulators don't produce output
-      for (specification_map::const_iterator i = specs.lower_bound(arg_no),
-            end = specs.upper_bound(arg_no); i != end; ++i) {
-       output_list::iterator pos = i->second;
-       ++pos;
-      
-       output.insert(pos, rep);
-      }
-    
-      os.str(std::string());
-      //os.clear();
-      ++arg_no;
-    }
-  
-    return *this;
-  }
-
-  inline Composition::Composition(std::string fmt)
-    : arg_no(1)
-  {
-    std::string::size_type b = 0, i = 0;
-  
-    // fill in output with the strings between the %1 %2 %3 etc. and
-    // fill in specs with the positions
-    while (i < fmt.length()) {
-      if (fmt[i] == '%' && i + 1 < fmt.length()) {
-       if (fmt[i + 1] == '%') {        // catch %%
-         fmt.replace(i, 2, "%");
-         ++i;
-       }
-       else if (is_number(fmt[i + 1])) { // aha! a spec!
-         // save string
-         output.push_back(fmt.substr(b, i - b));
-       
-         int n = 1;            // number of digits
-         int spec_no = 0;
-
-         do {
-           spec_no += char_to_int(fmt[i + n]);
-           spec_no *= 10;
-           ++n;
-         } while (i + n < fmt.length() && is_number(fmt[i + n]));
-
-         spec_no /= 10;
-         output_list::iterator pos = output.end();
-         --pos;                // safe since we have just inserted a string>
-       
-         specs.insert(specification_map::value_type(spec_no, pos));
-       
-         // jump over spec string
-         i += n;
-         b = i;
-       }
-       else
-         ++i;
-      }
-      else
-       ++i;
-    }
-  
-    if (i - b > 0)             // add the rest of the string
-      output.push_back(fmt.substr(b, i - b));
-  }
-
-  inline std::string Composition::str() const
-  {
-    // assemble string
-    std::string str;
-  
-    for (output_list::const_iterator i = output.begin(), end = output.end();
-        i != end; ++i)
-      str += *i;
-  
-    return str;
-  }
-}
-
-// now for the real thing(s)
-//namespace PBD
-//{
-  // a series of functions which accept a format string on the form "text %1
-  // more %2 less %3" and a number of templated parameters and spits out the
-  // composited string
-  template <typename T1>
-  inline std::string string_compose(const std::string &fmt, const T1 &o1)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1);
-    return c.str();
-  }
-
-  template <typename T1, typename T2>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2);
-    return c.str();
-  }
-
-  template <typename T1, typename T2, typename T3>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2, const T3 &o3)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2).arg(o3);
-    return c.str();
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2, const T3 &o3,
-                            const T4 &o4)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2).arg(o3).arg(o4);
-    return c.str();
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2, const T3 &o3,
-                            const T4 &o4, const T5 &o5)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5);
-    return c.str();
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5,
-           typename T6>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2, const T3 &o3,
-                            const T4 &o4, const T5 &o5, const T6 &o6)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6);
-    return c.str();
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5,
-           typename T6, typename T7>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2, const T3 &o3,
-                            const T4 &o4, const T5 &o5, const T6 &o6,
-                            const T7 &o7)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7);
-    return c.str();
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5,
-           typename T6, typename T7, typename T8>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2, const T3 &o3,
-                            const T4 &o4, const T5 &o5, const T6 &o6,
-                            const T7 &o7, const T8 &o8)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8);
-    return c.str();
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5,
-           typename T6, typename T7, typename T8, typename T9>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2, const T3 &o3,
-                            const T4 &o4, const T5 &o5, const T6 &o6,
-                            const T7 &o7, const T8 &o8, const T9 &o9)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9);
-    return c.str();
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5,
-           typename T6, typename T7, typename T8, typename T9, typename T10>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2, const T3 &o3,
-                            const T4 &o4, const T5 &o5, const T6 &o6,
-                            const T7 &o7, const T8 &o8, const T9 &o9,
-                            const T10 &o10)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
-      .arg(o10);
-    return c.str();
-  }
-  
-  template <typename T1, typename T2, typename T3, typename T4, typename T5,
-           typename T6, typename T7, typename T8, typename T9, typename T10,
-           typename T11>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2, const T3 &o3,
-                            const T4 &o4, const T5 &o5, const T6 &o6,
-                            const T7 &o7, const T8 &o8, const T9 &o9,
-                            const T10 &o10, const T11 &o11)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
-      .arg(o10).arg(o11);
-    return c.str();
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5,
-           typename T6, typename T7, typename T8, typename T9, typename T10,
-           typename T11, typename T12>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2, const T3 &o3,
-                            const T4 &o4, const T5 &o5, const T6 &o6,
-                            const T7 &o7, const T8 &o8, const T9 &o9,
-                            const T10 &o10, const T11 &o11, const T12 &o12)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
-      .arg(o10).arg(o11).arg(o12);
-    return c.str();
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5,
-           typename T6, typename T7, typename T8, typename T9, typename T10,
-           typename T11, typename T12, typename T13>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2, const T3 &o3,
-                            const T4 &o4, const T5 &o5, const T6 &o6,
-                            const T7 &o7, const T8 &o8, const T9 &o9,
-                            const T10 &o10, const T11 &o11, const T12 &o12,
-                            const T13 &o13)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
-      .arg(o10).arg(o11).arg(o12).arg(o13);
-    return c.str();
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5,
-           typename T6, typename T7, typename T8, typename T9, typename T10,
-           typename T11, typename T12, typename T13, typename T14>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2, const T3 &o3,
-                            const T4 &o4, const T5 &o5, const T6 &o6,
-                            const T7 &o7, const T8 &o8, const T9 &o9,
-                            const T10 &o10, const T11 &o11, const T12 &o12,
-                            const T13 &o13, const T14 &o14)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
-      .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14);
-    return c.str();
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5,
-           typename T6, typename T7, typename T8, typename T9, typename T10,
-           typename T11, typename T12, typename T13, typename T14,
-           typename T15>
-  inline std::string string_compose(const std::string &fmt,
-                            const T1 &o1, const T2 &o2, const T3 &o3,
-                            const T4 &o4, const T5 &o5, const T6 &o6,
-                            const T7 &o7, const T8 &o8, const T9 &o9,
-                            const T10 &o10, const T11 &o11, const T12 &o12,
-                            const T13 &o13, const T14 &o14, const T15 &o15)
-  {
-    StringPrivate::Composition c(fmt);
-    c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9)
-      .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15);
-    return c.str();
-  }
-//}
-
-
-#endif // STRING_COMPOSE_H
diff --git a/libs/pbd3/pbd/convert.h b/libs/pbd3/pbd/convert.h
deleted file mode 100644 (file)
index 12e63ba..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-    Copyright (C) 2002 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.
-
-*/
-
-#ifndef __pbd_convert_h__
-#define __pbd_convert_h__
-
-#include <string>
-#include <vector>
-
-namespace PBD {
-
-std::string short_version (std::string, std::string::size_type target_length);
-
-int    atoi (const std::string&);
-double atof (const std::string&);
-void   url_decode (std::string&);
-
-std::string length2string (const int32_t frames, const float sample_rate);
-
-std::vector<std::string> internationalize (const char **);
-
-} //namespace PBD
-
-#endif /* __pbd_convert_h__ */
diff --git a/libs/pbd3/pbd/error.h b/libs/pbd3/pbd/error.h
deleted file mode 100644 (file)
index 4136f02..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-    Copyright (C) 1998-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
-    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$
-*/
-#ifndef __libpbd_error_h__
-#define __libpbd_error_h__
-
-#include "transmitter.h"
-
-namespace PBD {
-       extern Transmitter error;
-       extern Transmitter info;
-       extern Transmitter warning;
-       extern Transmitter fatal;
-}
-
-#endif  // __libpbd_error_h__
diff --git a/libs/pbd3/pbd/failed_constructor.h b/libs/pbd3/pbd/failed_constructor.h
deleted file mode 100644 (file)
index 62eb6c0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __pbd_failed_constructor_h__
-#define __pbd_failed_constructor_h__
-
-#include <exception>
-
-class failed_constructor : public std::exception {
-  public:
-       virtual const char *what() const throw() { return "failed constructor"; }
-};
-
-#endif /* __pbd_failed_constructor_h__ */
diff --git a/libs/pbd3/pbd/fastlog.h b/libs/pbd3/pbd/fastlog.h
deleted file mode 100644 (file)
index 4269705..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright unknown. Code by Laurent de Soras <laurent@ohmforce.com>.
- */
-
-#ifndef __pbd_fastlog_h__
-#define __pbd_fastlog_h__
-
-#include <math.h> /* for HUGE_VAL */
-
-static inline float fast_log2 (float val)
-{
-       /* don't use reinterpret_cast<> because that prevents this
-          from being used by pure C code (for example, GnomeCanvasItems)
-       */
-       union {float f; int i;} t;
-       t.f = val;
-       int * const    exp_ptr =  &t.i;
-       int            x = *exp_ptr;
-       const int      log_2 = ((x >> 23) & 255) - 128;
-       x &= ~(255 << 23);
-       x += 127 << 23;
-       *exp_ptr = x;
-       
-       val = ((-1.0f/3) * t.f + 2) * t.f - 2.0f/3;
-       
-       return (val + log_2);
-}
-
-static inline float fast_log (const float val)
-{
-       return (fast_log2 (val) * 0.69314718f);
-}
-
-static inline float fast_log10 (const float val)
-{
-       return fast_log2(val) / 3.312500f;
-}
-
-static inline float minus_infinity() { return -HUGE_VAL; }
-
-#endif /* __pbd_fastlog_h__ */
diff --git a/libs/pbd3/pbd/forkexec.h b/libs/pbd3/pbd/forkexec.h
deleted file mode 100644 (file)
index 2af3711..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __forkexec_h__
-#define __forkexec_h__
-
-#include <unistd.h>
-
-pid_t forkexec(char **argv, char **envp, int outpipe[2], int inpipe[2]);
-pid_t forkexec_cmd(char *cmd, char **envp, int outpipe[2], int inpipe[2]);
-
-#endif // __forkexec_h__
diff --git a/libs/pbd3/pbd/mathfix.h b/libs/pbd3/pbd/mathfix.h
deleted file mode 100644 (file)
index f0dc7e4..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-    Copyright (C) 2005 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$
-*/
-
-#ifndef __pbd_mathfix_h__
-#define __pbd_mathfix_h__
-
-/* this is necessary to support older releases of OSX where
-   they moved around some of the standard math functions
-*/
-
-#ifdef __APPLE__
-#define powf pow
-#define sqrtf sqrt
-#endif
-
-
-#endif
diff --git a/libs/pbd3/pbd/memento_command.h b/libs/pbd3/pbd/memento_command.h
deleted file mode 100644 (file)
index c8bfe5d..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/* 
-   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 <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 &serialize() {}
-        //{
-            // obj.id
-            // key is "MementoCommand" or something
-            // before and after mementos
-        //}
-        // 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 &serialize() {}
-    //{
-        // obj.id
-        // key is "MementoCommand" or something
-        // before and after mementos
-    //}
-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 &serialize() {}
-    //{
-        // obj.id
-        // key is "MementoCommand" or something
-        // before and after mementos
-    //}
-protected:
-    obj_T &obj;
-    XMLNode &after;
-};
-
-#endif // __lib_pbd_memento_h__
diff --git a/libs/pbd3/pbd/mountpoint.h b/libs/pbd3/pbd/mountpoint.h
deleted file mode 100644 (file)
index 86ccc58..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#ifndef __pbd_mountpoint_h__
-#define __pbd_mountpoint_h__
-
-#include <string>
-
-std::string mountpoint (std::string path);
-
-#endif // __pbd_mountpoint_h__
diff --git a/libs/pbd3/pbd/pathscanner.h b/libs/pbd3/pbd/pathscanner.h
deleted file mode 100644 (file)
index 346e785..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef __libmisc_pathscanner_h__
-#define __libmisc_pathscanner_h__
-
-#include <vector>
-#include <string>
-#include <regex.h>
-
-using std::string;
-using std::vector;
-
-class PathScanner
-
-{
-  public:
-    vector<string *> *operator() (const string &dirpath,
-                                 bool (*filter)(const string &, void *arg),
-                                 void *arg, 
-                                 bool match_fullpath = true,
-                                 bool return_fullpath = true,
-                                 long limit = -1) {
-           return run_scan (dirpath,
-                            (bool (PathScanner::*)(const string &)) 0, 
-                            filter, 
-                            arg,
-                            match_fullpath,
-                            return_fullpath, 
-                            limit);
-    }
-
-    vector<string *> *operator() (const string &dirpath,
-                                 const string &regexp,
-                                 bool match_fullpath = true,
-                                 bool return_fullpath = true,
-                                 long limit = -1);
-
-    
-    string *find_first (const string &dirpath,
-                       const string &regexp,
-                       bool match_fullpath = true,
-                       bool return_fullpath = true);
-
-    string *find_first (const string &dirpath,
-                       bool (*filter)(const string &, void *),
-                       void *arg,
-                       bool match_fullpath = true,
-                       bool return_fullpath = true);
-
-  private:
-    regex_t compiled_pattern;
-    
-    bool regexp_filter (const string &str) {
-           return regexec (&compiled_pattern, str.c_str(), 0, 0, 0) == 0;
-    }
-
-    vector<string *> *run_scan (const string &dirpath,
-                               bool (PathScanner::*mfilter) (const string &),
-                               bool (*filter)(const string &, void *),
-                               void *arg,
-                               bool match_fullpath,
-                               bool return_fullpath,
-                               long limit);
-    
-
-};
-
-#endif // __libmisc_pathscanner_h__
diff --git a/libs/pbd3/pbd/pool.h b/libs/pbd3/pbd/pool.h
deleted file mode 100644 (file)
index f8e19e7..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#ifndef __qm_pool_h__
-#define __qm_pool_h__
-
-#include <vector>
-#include <string>
-
-#include <glibmm/thread.h>
-
-#include <pbd/ringbuffer.h>
-
-class Pool 
-{
-  public:
-       Pool (std::string name, unsigned long item_size, unsigned long nitems);
-       virtual ~Pool ();
-
-       virtual void *alloc ();
-       virtual void release (void *);
-       
-       std::string name() const { return _name; }
-
-  private:
-       RingBuffer<void*>* free_list;
-       std::string _name;
-       void *block;
-};
-
-class SingleAllocMultiReleasePool : public Pool
-{
-  public:
-       SingleAllocMultiReleasePool (std::string name, unsigned long item_size, unsigned long nitems);
-       ~SingleAllocMultiReleasePool ();
-
-       virtual void *alloc ();
-       virtual void release (void *);
-
-  private:
-    Glib::Mutex* m_lock;
-};
-
-
-class MultiAllocSingleReleasePool : public Pool
-{
-  public:
-       MultiAllocSingleReleasePool (std::string name, unsigned long item_size, unsigned long nitems);
-       ~MultiAllocSingleReleasePool ();
-
-       virtual void *alloc ();
-       virtual void release (void *);
-
-  private:
-    Glib::Mutex* m_lock;
-};
-
-#endif // __qm_pool_h__
diff --git a/libs/pbd3/pbd/pthread_utils.h b/libs/pbd3/pbd/pthread_utils.h
deleted file mode 100644 (file)
index 482b5b5..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef __pbd_pthread_utils__
-#define __pbd_pthread_utils__
-
-#include <pthread.h>
-#include <signal.h>
-#include <string>
-#include <stdint.h>
-
-#include <sigc++/sigc++.h>
-
-int  pthread_create_and_store (std::string name, pthread_t  *thread, pthread_attr_t *attr, void * (*start_routine)(void *), void * arg);
-void pthread_cancel_one (pthread_t thread);
-void pthread_kill_all (int signum);
-void pthread_cancel_all ();
-void pthread_exit_pbd (void* status);
-std::string pthread_name ();
-
-namespace PBD {
-  extern sigc::signal<void,pthread_t,std::string> ThreadCreated;
-  extern sigc::signal<void,pthread_t,std::string,uint32_t> ThreadCreatedWithRequestSize;
-}
-
-#endif /* __pbd_pthread_utils__ */
diff --git a/libs/pbd3/pbd/receiver.h b/libs/pbd3/pbd/receiver.h
deleted file mode 100644 (file)
index 5ce238d..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#ifndef __libmisc_receiver_h__
-#define __libmisc_receiver_h__
-
-#include <vector>
-
-#include <sigc++/sigc++.h>
-
-#include "transmitter.h"
-
-using std::vector;
-
-class strstream;
-
-class Receiver : virtual public sigc::trackable
-{
-  public:
-       Receiver ();
-       virtual ~Receiver ();
-       
-       void listen_to (Transmitter &);
-       void hangup ();
-
-  protected:
-       virtual void receive (Transmitter::Channel, const char *) = 0;
-
-  private:
-       vector<sigc::connection *> connections;
-};
-
-#endif  // __libmisc_receiver_h__
diff --git a/libs/pbd3/pbd/restartable_rw.h b/libs/pbd3/pbd/restartable_rw.h
deleted file mode 100644 (file)
index ee84e4e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __libmisc_restartable_rw__h__
-#define __libmisc_restartable_rw__h__
-
-extern int restartable_write (int fd, unsigned char *buf, size_t cnt);
-extern int restartable_read (int fd, unsigned char *buf, size_t cnt);
-
-#endif // __libmisc_restartable_rw__h__
diff --git a/libs/pbd3/pbd/ringbuffer.h b/libs/pbd3/pbd/ringbuffer.h
deleted file mode 100644 (file)
index 1d9c9b0..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
-    Copyright (C) 2000 Paul Davis & Benno Senoner
-
-    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$
-*/
-
-#ifndef ringbuffer_h
-#define ringbuffer_h
-
-//#include <sys/mman.h>
-
-#include <glib.h>
-
-template<class T>
-class RingBuffer 
-{
-  public:
-       RingBuffer (size_t sz) {
-               size_t power_of_two;
-               
-               for (power_of_two = 1; 1U<<power_of_two < sz; power_of_two++);
-               
-               size = 1<<power_of_two;
-               size_mask = size;
-               size_mask -= 1;
-               buf = new T[size];
-               reset ();
-
-       };
-       
-       virtual ~RingBuffer() {
-               delete [] buf;
-       }
-
-       void reset () {
-               /* !!! NOT THREAD SAFE !!! */
-               g_atomic_int_set (&write_ptr, 0);
-               g_atomic_int_set (&read_ptr, 0);
-       }
-
-       void set (size_t r, size_t w) {
-               /* !!! NOT THREAD SAFE !!! */
-               g_atomic_int_set (&write_ptr, w);
-               g_atomic_int_set (&read_ptr, r);
-       }
-       
-       size_t  read  (T *dest, size_t cnt);
-       size_t  write (T *src, size_t cnt);
-
-       struct rw_vector {
-           T *buf[2];
-           size_t len[2];
-       };
-
-       void get_read_vector (rw_vector *);
-       void get_write_vector (rw_vector *);
-       
-       void decrement_read_ptr (size_t cnt) {
-               g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) - cnt) & size_mask);
-       }                
-
-       void increment_read_ptr (size_t cnt) {
-               g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) + cnt) & size_mask);
-       }                
-
-       void increment_write_ptr (size_t cnt) {
-               g_atomic_int_set (&write_ptr,  (g_atomic_int_get(&write_ptr) + cnt) & size_mask);
-       }                
-
-       size_t write_space () {
-               size_t w, r;
-               
-               w = g_atomic_int_get (&write_ptr);
-               r = g_atomic_int_get (&read_ptr);
-               
-               if (w > r) {
-                       return ((r - w + size) & size_mask) - 1;
-               } else if (w < r) {
-                       return (r - w) - 1;
-               } else {
-                       return size - 1;
-               }
-       }
-       
-       size_t read_space () {
-               size_t w, r;
-               
-               w = g_atomic_int_get (&write_ptr);
-               r = g_atomic_int_get (&read_ptr);
-               
-               if (w > r) {
-                       return w - r;
-               } else {
-                       return (w - r + size) & size_mask;
-               }
-       }
-
-       T *buffer () { return buf; }
-       size_t get_write_ptr () const { return g_atomic_int_get (&write_ptr); }
-       size_t get_read_ptr () const { return g_atomic_int_get (&read_ptr); }
-       size_t bufsize () const { return size; }
-
-  protected:
-       T *buf;
-       size_t size;
-       mutable gint write_ptr;
-       mutable gint read_ptr;
-       size_t size_mask;
-};
-
-template<class T> size_t
-RingBuffer<T>::read (T *dest, size_t cnt)
-{
-        size_t free_cnt;
-        size_t cnt2;
-        size_t to_read;
-        size_t n1, n2;
-        size_t priv_read_ptr;
-
-        priv_read_ptr=g_atomic_int_get(&read_ptr);
-
-        if ((free_cnt = read_space ()) == 0) {
-                return 0;
-        }
-
-        to_read = cnt > free_cnt ? free_cnt : cnt;
-        
-        cnt2 = priv_read_ptr + to_read;
-
-        if (cnt2 > size) {
-                n1 = size - priv_read_ptr;
-                n2 = cnt2 & size_mask;
-        } else {
-                n1 = to_read;
-                n2 = 0;
-        }
-        
-        memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T));
-        priv_read_ptr = (priv_read_ptr + n1) & size_mask;
-
-        if (n2) {
-                memcpy (dest+n1, buf, n2 * sizeof (T));
-                priv_read_ptr = n2;
-        }
-
-        g_atomic_int_set(&read_ptr, priv_read_ptr);
-        return to_read;
-}
-
-template<class T> size_t
-RingBuffer<T>::write (T *src, size_t cnt)
-
-{
-        size_t free_cnt;
-        size_t cnt2;
-        size_t to_write;
-        size_t n1, n2;
-        size_t priv_write_ptr;
-
-        priv_write_ptr=g_atomic_int_get(&write_ptr);
-
-        if ((free_cnt = write_space ()) == 0) {
-                return 0;
-        }
-
-        to_write = cnt > free_cnt ? free_cnt : cnt;
-        
-        cnt2 = priv_write_ptr + to_write;
-
-        if (cnt2 > size) {
-                n1 = size - priv_write_ptr;
-                n2 = cnt2 & size_mask;
-        } else {
-                n1 = to_write;
-                n2 = 0;
-        }
-
-        memcpy (&buf[priv_write_ptr], src, n1 * sizeof (T));
-        priv_write_ptr = (priv_write_ptr + n1) & size_mask;
-
-        if (n2) {
-                memcpy (buf, src+n1, n2 * sizeof (T));
-                priv_write_ptr = n2;
-        }
-
-        g_atomic_int_set(&write_ptr, priv_write_ptr);
-        return to_write;
-}
-
-template<class T> void
-RingBuffer<T>::get_read_vector (RingBuffer<T>::rw_vector *vec)
-
-{
-       size_t free_cnt;
-       size_t cnt2;
-       size_t w, r;
-       
-       w = g_atomic_int_get (&write_ptr);
-       r = g_atomic_int_get (&read_ptr);
-       
-       if (w > r) {
-               free_cnt = w - r;
-       } else {
-               free_cnt = (w - r + size) & size_mask;
-       }
-
-       cnt2 = r + free_cnt;
-
-       if (cnt2 > size) {
-               /* Two part vector: the rest of the buffer after the
-                  current write ptr, plus some from the start of 
-                  the buffer.
-               */
-
-               vec->buf[0] = &buf[r];
-               vec->len[0] = size - r;
-               vec->buf[1] = buf;
-               vec->len[1] = cnt2 & size_mask;
-
-       } else {
-               
-               /* Single part vector: just the rest of the buffer */
-               
-               vec->buf[0] = &buf[r];
-               vec->len[0] = free_cnt;
-               vec->len[1] = 0;
-       }
-}
-
-template<class T> void
-RingBuffer<T>::get_write_vector (RingBuffer<T>::rw_vector *vec)
-
-{
-       size_t free_cnt;
-       size_t cnt2;
-       size_t w, r;
-       
-       w = g_atomic_int_get (&write_ptr);
-       r = g_atomic_int_get (&read_ptr);
-       
-       if (w > r) {
-               free_cnt = ((r - w + size) & size_mask) - 1;
-       } else if (w < r) {
-               free_cnt = (r - w) - 1;
-       } else {
-               free_cnt = size - 1;
-       }
-       
-       cnt2 = w + free_cnt;
-
-       if (cnt2 > size) {
-               
-               /* Two part vector: the rest of the buffer after the
-                  current write ptr, plus some from the start of 
-                  the buffer.
-               */
-
-               vec->buf[0] = &buf[w];
-               vec->len[0] = size - w;
-               vec->buf[1] = buf;
-               vec->len[1] = cnt2 & size_mask;
-       } else {
-               vec->buf[0] = &buf[w];
-               vec->len[0] = free_cnt;
-               vec->len[1] = 0;
-       }
-}
-
-
-#endif /* __ringbuffer_h__ */
diff --git a/libs/pbd3/pbd/ringbufferNPT.h b/libs/pbd3/pbd/ringbufferNPT.h
deleted file mode 100644 (file)
index fee2efc..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
-    Copyright (C) 2000 Paul Davis & Benno Senoner
-
-    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$
-*/
-
-#ifndef ringbuffer_npt_h
-#define ringbuffer_npt_h
-
-//#include <sys/mman.h>
-
-#include <glib.h>
-
-/* ringbuffer class where the element size is not required to be a power of two */
-
-template<class T>
-class RingBufferNPT
-{
-  public:
-       RingBufferNPT (size_t sz) {
-               size = sz;
-               buf = new T[size];
-               reset ();
-
-       };
-       
-       virtual ~RingBufferNPT() {
-               delete [] buf;
-       }
-
-       void reset () {
-               /* !!! NOT THREAD SAFE !!! */
-               g_atomic_int_set (&write_ptr, 0);
-               g_atomic_int_set (&read_ptr, 0);
-       }
-
-       void set (size_t r, size_t w) {
-               /* !!! NOT THREAD SAFE !!! */
-               g_atomic_int_set (&write_ptr, w);
-               g_atomic_int_set (&read_ptr, r);
-       }
-       
-       size_t  read  (T *dest, size_t cnt);
-       size_t  write (T *src, size_t cnt);
-
-       struct rw_vector {
-           T *buf[2];
-           size_t len[2];
-       };
-
-       void get_read_vector (rw_vector *);
-       void get_write_vector (rw_vector *);
-       
-       void decrement_read_ptr (size_t cnt) {
-               g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) - cnt) % size);
-       }                
-
-       void increment_read_ptr (size_t cnt) {
-               g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) + cnt) % size);
-       }                
-
-       void increment_write_ptr (size_t cnt) {
-               g_atomic_int_set (&write_ptr,  (g_atomic_int_get(&write_ptr) + cnt) % size);
-       }                
-
-       size_t write_space () {
-               size_t w, r;
-               
-               w = g_atomic_int_get (&write_ptr);
-               r = g_atomic_int_get (&read_ptr);
-               
-               if (w > r) {
-                       return ((r - w + size) % size) - 1;
-               } else if (w < r) {
-                       return (r - w) - 1;
-               } else {
-                       return size - 1;
-               }
-       }
-       
-       size_t read_space () {
-               size_t w, r;
-               
-               w = g_atomic_int_get (&write_ptr);
-               r = g_atomic_int_get (&read_ptr);
-               
-               if (w > r) {
-                       return w - r;
-               } else {
-                       return (w - r + size) % size;
-               }
-       }
-
-       T *buffer () { return buf; }
-       size_t get_write_ptr () const { return g_atomic_int_get (&write_ptr); }
-       size_t get_read_ptr () const { return g_atomic_int_get (&read_ptr); }
-       size_t bufsize () const { return size; }
-
-  protected:
-       T *buf;
-       size_t size;
-       mutable gint write_ptr;
-       mutable gint read_ptr;
-};
-
-template<class T> size_t
-RingBufferNPT<T>::read (T *dest, size_t cnt)
-{
-        size_t free_cnt;
-        size_t cnt2;
-        size_t to_read;
-        size_t n1, n2;
-        size_t priv_read_ptr;
-
-        priv_read_ptr=g_atomic_int_get(&read_ptr);
-
-        if ((free_cnt = read_space ()) == 0) {
-                return 0;
-        }
-
-        to_read = cnt > free_cnt ? free_cnt : cnt;
-        
-        cnt2 = priv_read_ptr + to_read;
-
-        if (cnt2 > size) {
-                n1 = size - priv_read_ptr;
-                n2 = cnt2 % size;
-        } else {
-                n1 = to_read;
-                n2 = 0;
-        }
-        
-        memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T));
-        priv_read_ptr = (priv_read_ptr + n1) % size;
-
-        if (n2) {
-                memcpy (dest+n1, buf, n2 * sizeof (T));
-                priv_read_ptr = n2;
-        }
-
-        g_atomic_int_set(&read_ptr, priv_read_ptr);
-        return to_read;
-}
-
-template<class T> size_t
-RingBufferNPT<T>::write (T *src, size_t cnt)
-{
-        size_t free_cnt;
-        size_t cnt2;
-        size_t to_write;
-        size_t n1, n2;
-        size_t priv_write_ptr;
-
-        priv_write_ptr=g_atomic_int_get(&write_ptr);
-
-        if ((free_cnt = write_space ()) == 0) {
-                return 0;
-        }
-
-        to_write = cnt > free_cnt ? free_cnt : cnt;
-        
-        cnt2 = priv_write_ptr + to_write;
-
-        if (cnt2 > size) {
-                n1 = size - priv_write_ptr;
-                n2 = cnt2 % size;
-        } else {
-                n1 = to_write;
-                n2 = 0;
-        }
-
-        memcpy (&buf[priv_write_ptr], src, n1 * sizeof (T));
-        priv_write_ptr = (priv_write_ptr + n1) % size;
-
-        if (n2) {
-                memcpy (buf, src+n1, n2 * sizeof (T));
-                priv_write_ptr = n2;
-        }
-
-        g_atomic_int_set(&write_ptr, priv_write_ptr);
-        return to_write;
-}
-
-template<class T> void
-RingBufferNPT<T>::get_read_vector (RingBufferNPT<T>::rw_vector *vec)
-{
-       size_t free_cnt;
-       size_t cnt2;
-       size_t w, r;
-       
-       w = g_atomic_int_get (&write_ptr);
-       r = g_atomic_int_get (&read_ptr);
-       
-       if (w > r) {
-               free_cnt = w - r;
-       } else {
-               free_cnt = (w - r + size) % size;
-       }
-
-       cnt2 = r + free_cnt;
-
-       if (cnt2 > size) {
-               /* Two part vector: the rest of the buffer after the
-                  current write ptr, plus some from the start of 
-                  the buffer.
-               */
-
-               vec->buf[0] = &buf[r];
-               vec->len[0] = size - r;
-               vec->buf[1] = buf;
-               vec->len[1] = cnt2 % size;
-
-       } else {
-               
-               /* Single part vector: just the rest of the buffer */
-               
-               vec->buf[0] = &buf[r];
-               vec->len[0] = free_cnt;
-               vec->len[1] = 0;
-       }
-}
-
-template<class T> void
-RingBufferNPT<T>::get_write_vector (RingBufferNPT<T>::rw_vector *vec)
-{
-       size_t free_cnt;
-       size_t cnt2;
-       size_t w, r;
-       
-       w = g_atomic_int_get (&write_ptr);
-       r = g_atomic_int_get (&read_ptr);
-       
-       if (w > r) {
-               free_cnt = ((r - w + size) % size) - 1;
-       } else if (w < r) {
-               free_cnt = (r - w) - 1;
-       } else {
-               free_cnt = size - 1;
-       }
-       
-       cnt2 = w + free_cnt;
-
-       if (cnt2 > size) {
-               
-               /* Two part vector: the rest of the buffer after the
-                  current write ptr, plus some from the start of 
-                  the buffer.
-               */
-
-               vec->buf[0] = &buf[w];
-               vec->len[0] = size - w;
-               vec->buf[1] = buf;
-               vec->len[1] = cnt2 % size;
-       } else {
-               vec->buf[0] = &buf[w];
-               vec->len[0] = free_cnt;
-               vec->len[1] = 0;
-       }
-}
-
-#endif /* __ringbuffer_npt_h__ */
diff --git a/libs/pbd3/pbd/selectable.h b/libs/pbd3/pbd/selectable.h
deleted file mode 100644 (file)
index 470bc3c..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#ifndef __selectable_h__
-#define __selectable_h__
-
-#include <list>
-#include <string>
-#include <stdio.h>
-
-#include <sigc++/sigc++.h>
-
-#include <sys/types.h>
-
-namespace Select {
-    enum Condition {
-               Readable = 0x1,
-               Writable = 0x2,
-               Exception = 0x4
-    };
-
-class Selectable : public sigc::trackable
-
-{
-  public:
-       Selectable (int fd);
-       Selectable (const std::string &, int flags, int mode = 0);
-       Selectable (FILE *);
-       ~Selectable ();
-
-       sigc::signal<void,Selectable *,Select::Condition> readable;
-       sigc::signal<void,Selectable *,Select::Condition> writable;
-       sigc::signal<void,Selectable *,Select::Condition> exceptioned;
-
-       int  fd() { return _fd; }
-       bool ok() { return _ok; }
-
-  protected:
-       void selected (unsigned int condition);
-       int condition;
-       int _fd;
-
-       friend class Selector;
-
-  private:
-       enum {
-               fromFD,
-               fromPath,
-               fromFILE
-       };
-               
-       bool _ok;
-       int _type;
-       std::string path;
-};
-
-class Selector {
-  private:
-       int post_select (fd_set *, fd_set *, fd_set *);
-       int _max_fd;
-
-       typedef std::list<Selectable *> Selectables;
-       Selectables selectables;
-       pthread_mutex_t list_lock;
-
-       static bool use_list_lock;
-
-  public:
-       Selector ();
-
-       void multithreaded (bool yn) {
-               use_list_lock = yn;
-       }
-       
-       void add (int condition, Selectable *s);
-       void remove (Selectable *);
-       int select (unsigned long usecs);
-};
-
-
-
-} /* namespace */
-
-
-#endif // __selectable_h__
diff --git a/libs/pbd3/pbd/serializable.h b/libs/pbd3/pbd/serializable.h
deleted file mode 100644 (file)
index f6ac4e9..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/* 
-   Copyright (C) 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
-    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 59 2006-06-15T18:16:20.960977Z fugalh  $
-*/
-
-#ifndef __lib_pbd_serializable_h__
-#define __lib_pbd_serializable_h__
-
-#include <pbd/xml++.h>
-
-class Serializable 
-{
-public:
-    virtual XMLNode &serialize() = 0;
-    virtual ~Serializable() {}
-};
-
-#endif // __lib_pbd_serializable_h__
diff --git a/libs/pbd3/pbd/stacktrace.h b/libs/pbd3/pbd/stacktrace.h
deleted file mode 100644 (file)
index d7278bd..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __libpbd_stacktrace_h__
-#define __libpbd_stacktrace_h__
-
-#include <ostream>
-
-namespace PBD {
-       void stacktrace (std::ostream& out);
-}
-
-#endif /* __libpbd_stacktrace_h__ */
diff --git a/libs/pbd3/pbd/stl_delete.h b/libs/pbd3/pbd/stl_delete.h
deleted file mode 100644 (file)
index 6e5bfa0..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#ifndef __libmisc_stl_delete_h__
-#define __libmisc_stl_delete_h__
-
-/* To actually use any of these deletion functions, you need to
-   first include the revelant container type header.
-*/
-#if defined(_CPP_VECTOR) || defined(_GLIBCXX_VECTOR) || defined(__SGI_STL_VECTOR)
-template<class T> void vector_delete (std::vector<T *> *vec) 
-{
-       typename std::vector<T *>::iterator i;
-       
-       for (i = vec->begin(); i != vec->end(); i++) {
-               delete *i;
-       }
-       vec->clear ();
-}
-#endif // _CPP_VECTOR || _GLIBCXX_VECTOR || __SGI_STL_VECTOR
-
-#if defined(_CPP_MAP) || defined(_GLIBCXX_MAP) || defined(__SGI_STL_MAP)
-template<class K, class T> void map_delete (std::map<K, T *> *m) 
-{
-       typename std::map<K, T *>::iterator i;
-
-       for (i = m->begin(); i != m->end(); i++) {
-               delete (*i).second;
-       }
-       m->clear ();
-}
-#endif // _CPP_MAP || _GLIBCXX_MAP || __SGI_STL_MAP
-
-#if defined(_CPP_LIST) || defined(_GLIBCXX_LIST) || defined(__SGI_STL_LIST)
-template<class T> void list_delete (std::list<T *> *l) 
-{
-       typename std::list<T *>::iterator i;
-
-       for (i = l->begin(); i != l->end(); i++) {
-               delete (*i);
-       }
-
-       l->clear ();
-}
-#endif // _CPP_LIST || _GLIBCXX_LIST || __SGI_STL_LIST
-
-#if defined(_CPP_SLIST) || defined(_GLIBCXX_SLIST) || defined(__SGI_STL_SLIST)
-template<class T> void slist_delete (std::slist<T *> *l) 
-{
-       typename std::slist<T *>::iterator i;
-
-       for (i = l->begin(); i != l->end(); i++) {
-               delete (*i);
-       }
-
-       l->clear ();
-}
-#endif // _CPP_SLIST || _GLIBCXX_SLIST || __SGI_STL_SLIST
-
-#if defined(_CPP_SET) || defined(_GLIBCXX_SET) || defined(__SGI_STL_SET)
-template<class T> void set_delete (std::set<T *> *sset) 
-{
-       typename std::set<T *>::iterator i;
-       
-       for (i = sset->begin(); i != sset->end(); i++) {
-               delete *i;
-       }
-       sset->erase (sset->begin(), sset->end());
-}
-#endif // _CPP_SET || _GLIBCXX_SET || __SGI_STL_SET
-
-#endif // __libmisc_stl_delete_h__
diff --git a/libs/pbd3/pbd/stl_functors.h b/libs/pbd3/pbd/stl_functors.h
deleted file mode 100644 (file)
index 4a96e91..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#ifndef __stl_functors_h__
-#define __stl_functors_h__
-
-#include <string>
-
-#ifndef LESS_STRING_P
-struct less<std::string *> {
-    bool operator()(std::string *s1, std::string *s2) const {
-      return *s1 < *s2;
-    }
-};
-#define LESS_STRING_P
-#endif // LESS_STRING_P
-
-#ifndef LESS_CONST_STRING_P
-struct less<const std::string *> {
-    bool operator()(const std::string *s1, const std::string *s2) const {
-       return *s1 < *s2;
-    }
-};
-#define LESS_CONST_STRING_P
-#endif // LESS_CONST_STRING_P
-
-#ifndef LESS_CONST_CHAR_P
-struct less<const char *>
-{
-       bool operator()(const char* s1, const char* s2) const {
-               return strcmp(s1, s2) < 0;
-       }
-};
-#define LESS_CONST_CHAR_P
-#endif // LESS_CONST_CHAR_P
-
-#ifndef LESS_CONST_FLOAT_P
-struct less<const float *>
-{
-       bool operator()(const float *n1, const float *n2) const {
-               return *n1 < *n2;
-       }
-};
-#define LESS_CONST_FLOAT_P
-#endif // LESS_CONST_FLOAT_P
-
-#ifndef EQUAL_TO_CONST_CHAR_P
-struct equal_to<const char *>
-{
-        bool operator()(const char *s1, const char *s2) const {
-               return strcmp (s1, s2) == 0;
-       }
-};
-#define EQUAL_TO_CONST_CHAR_P
-#endif // EQUAL_TO_CONST_CHAR_P
-
-#ifndef EQUAL_TO_STRING_P
-struct equal_to<std::string *>
-{
-        bool operator()(const std::string *s1, const std::string *s2) const {
-               return *s1 == *s2;
-       }
-};
-#define EQUAL_TO_STRING_P
-#endif // EQUAL_TO_STRING_P
-
-#ifndef LESS_CONST_STRING_R
-struct less<const std::string &> {
-    bool operator() (const std::string &s1, const std::string &s2) {
-           return s1 < s2; 
-    }
-};
-#define LESS_CONST_STRING_R
-#endif // EQUAL_TO_STRING_P
-
-#endif // __stl_functors_h__
diff --git a/libs/pbd3/pbd/strsplit.h b/libs/pbd3/pbd/strsplit.h
deleted file mode 100644 (file)
index e55ad1c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __pbd_strplit_h__
-#define __pbd_strplit_h__
-
-#include <string>
-#include <vector>
-
-extern void split (std::string, std::vector<std::string>&, char);
-
-#endif // __pbd_strplit_h__
diff --git a/libs/pbd3/pbd/textreceiver.h b/libs/pbd3/pbd/textreceiver.h
deleted file mode 100644 (file)
index b8bfe5b..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#ifndef __libmisc_textreceiver_h__
-#define __libmisc_textreceiver_h__
-
-#include <string>
-
-#include "receiver.h"
-
-using std::string;
-using std::cout;
-using std::endl;
-
-class TextReceiver : public Receiver 
-{
-  public:
-       TextReceiver (const string &n);
-
-  protected:
-       void receive (Transmitter::Channel, const char *);
-
-  private:
-       string name;
-};
-
-#endif //__libmisc_textreceiver_h__
diff --git a/libs/pbd3/pbd/thrown_error.h b/libs/pbd3/pbd/thrown_error.h
deleted file mode 100644 (file)
index 83cf8ac..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-#ifndef __qm_thrown_error_h__
-#define __qm_thrown_error_h__
-
-#include "transmitter.h"
-
-#define SAFE_THROW(T) \
-        T *sent = new T; \
-        (*sent) << rdbuf(); \
-        throw sent
-
-class ThrownError : public Transmitter {
-  public:
-       ThrownError () : Transmitter (Transmitter::Throw) {}
-  protected:
-       virtual void deliver () = 0;
-};
-
-#endif // __qm_thrown_error_h__
-
-
diff --git a/libs/pbd3/pbd/touchable.h b/libs/pbd3/pbd/touchable.h
deleted file mode 100644 (file)
index 0298574..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-    Copyright (C) 1999 Paul Barton-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$
-*/
-
-#ifndef __pbd_touchable_h__
-#define __pbd_touchable_h__
-
-class Touchable
-{
-  public:
-       Touchable() : _delete_after_touch (false) {}
-       virtual ~Touchable() {}
-
-       void set_delete_after_touch (bool yn) { _delete_after_touch = yn; }
-       bool delete_after_touch() const { return _delete_after_touch; }
-
-       virtual void touch () = 0;
-
-  protected:
-       bool _delete_after_touch;
-};
-
-template<class T>
-class DynamicTouchable : public Touchable
-{
-  public:
-       DynamicTouchable (T& t, void (T::*m)(void)) 
-               : object (t), method (m) { set_delete_after_touch (true); }
-
-       void touch () {
-               (object.*method)();
-       }
-       
-  protected:
-       T& object;
-       void (T::*method)(void);
-};
-
-template<class T1, class T2>
-class DynamicTouchable1 : public Touchable
-{
-  public:
-       DynamicTouchable1 (T1& t, void (T1::*m)(T2), T2 a) 
-               : object (t), method (m), arg (a) { set_delete_after_touch (true); }
-
-       void touch () {
-               (object.*method)(arg);
-       }
-       
-  protected:
-       T1& object;
-       void (T1::*method)(T2);
-       T2 arg;
-};
-
-template<class T1, class T2, class T3>
-class DynamicTouchable2 : public Touchable
-{
-  public:
-       DynamicTouchable2 (T1& t, void (T1::*m)(T2, T3), T2 a1, T3 a2) 
-               : object (t), method (m), arg1 (a1), arg2 (a2) { set_delete_after_touch (true); }
-
-       void touch () {
-               (object.*method)(arg1, arg2);
-       }
-       
-  protected:
-       T1& object;
-       void (T1::*method)(T2,T3);
-       T2 arg1;
-       T3 arg2;
-};
-       
-#endif // __pbd_touchable_h__
diff --git a/libs/pbd3/pbd/transmitter.h b/libs/pbd3/pbd/transmitter.h
deleted file mode 100644 (file)
index 357cb99..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#ifndef __libmisc_transmitter_h__
-#define __libmisc_transmitter_h__
-
-#include <sstream>
-#include <iostream>
-
-#include <sigc++/sigc++.h>
-
-using std::cout;
-using std::cerr;
-using std::endl;
-
-class Transmitter : public std::stringstream
-
-{
-  public:
-       enum Channel {
-               Info,
-               Error,
-               Warning,
-               Fatal,
-               Throw
-       };
-
-       Transmitter (Channel);
-
-       sigc::signal<void,Channel, const char *> &sender() { 
-               return *send;
-       }
-
-       bool does_not_return ();
-
-  protected:
-       virtual void deliver ();
-       friend std::ostream& endmsg (std::ostream &);
-
-  private:
-       Channel channel;
-       sigc::signal<void, Channel, const char *> *send;
-
-       sigc::signal<void, Channel, const char *> info;
-       sigc::signal<void, Channel, const char *> warning;
-       sigc::signal<void, Channel, const char *> error;
-       sigc::signal<void, Channel, const char *> fatal;
-};
-
-/* for EGCS 2.91.66, if this function is not compiled within the same
-   compilation unit as the one where a ThrownError is thrown, then 
-   nothing will catch the error. This is a pretty small function, so
-   inlining it here seems like a reasonable workaround.
-*/
-
-inline std::ostream &
-endmsg (std::ostream &ostr)
-
-{
-       Transmitter *t;
-
-       /* There is a serious bug in the Cygnus/GCC libstdc++ library:
-          cout is not actually an ostream, but a trick was played
-          to make the compiler think that it is. This will cause
-          the dynamic_cast<> to fail with SEGV. So, first check to
-          see if ostr == cout, and handle it specially.
-       */
-
-       if (&ostr == &cout) {
-               cout << endl;
-               return ostr;
-       } else if (&ostr == &cerr) {
-               cerr << endl;
-               return ostr;
-       }
-
-       if ((t = dynamic_cast<Transmitter *> (&ostr)) != 0) {
-               t->deliver ();
-       } else {
-               /* hmm. not a Transmitter, so just put a newline on
-                  it and assume that that will be enough.
-               */
-               
-               ostr << endl;
-       }
-
-       return ostr;
-}
-
-
-extern "C" { void pbd_c_error (const char *); }
-
-#endif // __libmisc_transmitter_h__
diff --git a/libs/pbd3/pbd/undo.h b/libs/pbd3/pbd/undo.h
deleted file mode 100644 (file)
index 33577ed..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/* 
-   Copyright (C) 2002 Brett Viren & 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$
-*/
-
-#ifndef __lib_pbd_undo_h__
-#define __lib_pbd_undo_h__
-
-#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 UndoTransaction : public Command
-{
-  public:
-       UndoTransaction ();
-       UndoTransaction (const UndoTransaction&);
-       UndoTransaction& operator= (const UndoTransaction&);
-
-       void clear ();
-
-       void add_command (Command *const);
-
-        void operator() ();
-       void undo();
-       void redo();
-
-       XMLNode &serialize();
-       
-       void set_name (const string& str) {
-               _name = str;
-       }
-       const string& name() const { return _name; }
-
-       void set_timestamp (struct timeval &t) {
-               _timestamp = t;
-       }
-
-       const struct timeval& timestamp() const {
-               return _timestamp;
-       }
-
-  private:
-       list<Command*>   actions;
-       struct timeval   _timestamp;
-       string           _name;
-};
-
-class UndoHistory
-{
-  public:
-       UndoHistory() {}
-       ~UndoHistory() {}
-       
-       void add (UndoTransaction ut);
-       void undo (unsigned int n);
-       void redo (unsigned int n);
-       
-       unsigned long undo_depth() const { return UndoList.size(); }
-       unsigned long redo_depth() const { return RedoList.size(); }
-       
-       string next_undo() const { return (UndoList.empty() ? string("") : UndoList.back().name()); }
-       string next_redo() const { return (RedoList.empty() ? string("") : RedoList.back().name()); }
-
-       void clear ();
-       void clear_undo ();
-       void clear_redo ();
-
-  private:
-       list<UndoTransaction> UndoList;
-       list<UndoTransaction> RedoList;
-};
-
-
-#endif /* __lib_pbd_undo_h__ */
diff --git a/libs/pbd3/pbd/whitespace.h b/libs/pbd3/pbd/whitespace.h
deleted file mode 100644 (file)
index 6620a8f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __pbd_whitespace_h__
-#define __pbd_whitespace_h__
-
-#include <string>
-
-extern void strip_whitespace_edges (std::string& str);
-
-#endif // __pbd_whitespace_h__
diff --git a/libs/pbd3/pbd/xml++.h b/libs/pbd3/pbd/xml++.h
deleted file mode 100644 (file)
index afb896e..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/* xml++.h
- * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
- * are covered by the GNU Lesser General Public License, which should be
- * included with libxml++ as the file COPYING.
- */
-
-#include <string>
-#include <list>
-#include <map>
-#include <cstdio>
-#include <cstdarg>
-
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-
-#ifndef __XML_H
-#define __XML_H
-
-using std::string;
-using std::map;
-using std::list;
-
-class XMLTree;
-class XMLNode;
-class XMLProperty;
-
-typedef list<XMLNode *> XMLNodeList;
-typedef XMLNodeList::iterator XMLNodeIterator;
-typedef XMLNodeList::const_iterator XMLNodeConstIterator;
-typedef list<XMLProperty*> XMLPropertyList;
-typedef XMLPropertyList::iterator XMLPropertyIterator;
-typedef XMLPropertyList::const_iterator XMLPropertyConstIterator;
-typedef map<string, XMLProperty*> XMLPropertyMap;
-
-class XMLTree {
-private:
-  string _filename;
-  XMLNode *_root;
-  int _compression;
-  bool _initialized;
-
-public:
-  XMLTree();
-  XMLTree(const string &fn);
-  XMLTree(const XMLTree *);
-  ~XMLTree();
-
-  bool initialized() const { return _initialized; };
-  XMLNode *root() const { return _root; };
-  XMLNode *set_root(XMLNode *n) { _initialized = true; return _root = n; };
-
-  const string & filename() const { return _filename; };
-  const string & set_filename(const string &fn) { return _filename = fn; };
-
-  int compression() const { return _compression; };
-  int set_compression(int);
-
-  bool read();
-  bool read(const string &fn) { set_filename(fn); return read(); };
-  bool read_buffer(const string &);
-
-  bool write() const;
-  bool write(const string &fn) { set_filename(fn); return write(); };
-
-  void debug (FILE*) const;
-
-  const string & write_buffer() const;
-};
-
-class XMLNode {
-private:
-  bool _initialized;
-  string _name;
-  bool _is_content;
-  string _content;
-  XMLNodeList _children;
-  XMLPropertyList _proplist;
-  XMLPropertyMap _propmap;
-
-public:
-  XMLNode(const string &);
-  XMLNode(const string &, const string &);
-  XMLNode(const XMLNode&);
-  ~XMLNode();
-
-  bool initialized() const { return _initialized; };
-  const string name() const { return _name; };
-
-  bool is_content() const { return _is_content; };
-  const string & content() const { return _content; };
-  const string & set_content(const string &);
-  XMLNode *add_content(const string & = string());
-
-  const XMLNodeList & children(const string & = string()) const;
-  XMLNode *add_child(const char *);
-  XMLNode *add_child_copy(const XMLNode&);
-  void     add_child_nocopy (XMLNode&);
-
-  const XMLPropertyList & properties() const { return _proplist; };
-  XMLProperty *property(const char * );
-  const XMLProperty *property(const char * n) const
-       { return ((XMLNode *) this)->property(n); };
-  XMLProperty *add_property(const char *, const string &);
-  XMLProperty *add_property(const char *, const char * = "");
-
-  void remove_property(const string &);
-
-  /** Remove all nodes with the name passed to remove_nodes */
-  void remove_nodes(const string &);
-  /** Remove and delete all nodes with the name passed to remove_nodes */
-  void remove_nodes_and_delete(const string &);
-};
-
-class XMLProperty {
-private:
-  string _name;
-  string _value;
-
-public:
-  XMLProperty(const string &n, const string &v = string());
-  ~XMLProperty();
-
-  const string & name() const { return _name; };
-  const string & value() const { return _value; };
-  const string & set_value(const string &v) { return _value = v; };
-};
-
-#endif /* __XML_H */
-
diff --git a/libs/pbd3/pool.cc b/libs/pbd3/pool.cc
deleted file mode 100644 (file)
index 0897664..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#include <iostream>
-#include <vector>
-
-#include <pbd/pool.h>
-#include <pbd/error.h>
-
-using namespace std;
-using namespace PBD;
-
-Pool::Pool (string n, unsigned long item_size, unsigned long nitems)
-{
-       _name = n;
-
-       free_list = new RingBuffer<void*> (nitems);
-
-       /* since some overloaded ::operator new() might use this,
-          its important that we use a "lower level" allocator to
-          get more space.  
-       */
-
-       block = malloc (nitems * item_size);
-
-       void **ptrlist = (void **) malloc (sizeof (void *)  * nitems);
-
-       for (unsigned long i = 0; i < nitems; i++) {
-               ptrlist[i] = static_cast<void *> (static_cast<char*>(block) + (i * item_size));
-       }
-
-       free_list->write (ptrlist, nitems);
-
-       free (ptrlist);
-}
-
-Pool::~Pool ()
-{
-       free (block);
-}
-
-void *
-Pool::alloc ()
-{
-       void *ptr;
-
-//     cerr << _name << " pool " << " alloc, thread = " << pthread_name() << " space = " << free_list->read_space() << endl;
-
-       if (free_list->read (&ptr, 1) < 1) {
-               fatal << "CRITICAL: " << _name << " POOL OUT OF MEMORY - RECOMPILE WITH LARGER SIZE!!" << endmsg;
-               /*NOTREACHED*/
-               return 0;
-       } else {
-               return ptr;
-       }
-};
-
-void           
-Pool::release (void *ptr)
-{
-       free_list->write (&ptr, 1);
-//     cerr << _name << ": release, now has " << free_list->read_space() << endl;
-}
-
-/*---------------------------------------------*/
-
-MultiAllocSingleReleasePool::MultiAllocSingleReleasePool (string n, unsigned long isize, unsigned long nitems) 
-       : Pool (n, isize, nitems),
-        m_lock(0)
-{
-}
-
-MultiAllocSingleReleasePool::~MultiAllocSingleReleasePool ()
-{
-    if(m_lock) delete m_lock;
-}
-
-SingleAllocMultiReleasePool::SingleAllocMultiReleasePool (string n, unsigned long isize, unsigned long nitems) 
-       : Pool (n, isize, nitems),
-    m_lock(0)
-{
-}
-
-SingleAllocMultiReleasePool::~SingleAllocMultiReleasePool ()
-{
-    if(m_lock) delete m_lock;
-}
-
-void*
-MultiAllocSingleReleasePool::alloc ()
-{
-       void *ptr;
-    if(!m_lock) {
-        m_lock = new Glib::Mutex();
-        // umm, I'm not sure that this doesn't also allocate memory.
-        if(!m_lock) error << "cannot create Glib::Mutex in pool.cc" << endmsg;
-    }
-    
-    Glib::Mutex::Lock guard(*m_lock);
-       ptr = Pool::alloc ();
-       return ptr;
-}
-
-void
-MultiAllocSingleReleasePool::release (void* ptr)
-{
-       Pool::release (ptr);
-}
-
-void*
-SingleAllocMultiReleasePool::alloc ()
-{
-       return Pool::alloc ();
-}
-
-void
-SingleAllocMultiReleasePool::release (void* ptr)
-{
-    if(!m_lock) {
-        m_lock = new Glib::Mutex();
-        // umm, I'm not sure that this doesn't also allocate memory.
-        if(!m_lock) error << "cannot create Glib::Mutex in pool.cc" << endmsg;
-    }
-    Glib::Mutex::Lock guard(*m_lock);
-       Pool::release (ptr);
-}
-
diff --git a/libs/pbd3/pthread_utils.cc b/libs/pbd3/pthread_utils.cc
deleted file mode 100644 (file)
index db242ce..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
-    Copyright (C) 2002 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$
-*/
-
-#include <map>
-#include <iostream>
-#include <string>
-#include <stdint.h>
-
-#include <pbd/pthread_utils.h>
-
-using namespace std;
-
-typedef std::map<string,pthread_t> ThreadMap;
-static ThreadMap all_threads;
-static pthread_mutex_t thread_map_lock = PTHREAD_MUTEX_INITIALIZER;
-
-namespace PBD {
-   sigc::signal<void,pthread_t,std::string> ThreadCreated;
-   sigc::signal<void,pthread_t,std::string,uint32_t> ThreadCreatedWithRequestSize;
-}
-
-using namespace PBD;
-
-int  
-pthread_create_and_store (string name, pthread_t  *thread, pthread_attr_t *attr, void * (*start_routine)(void *), void * arg)
-{
-       int ret;
-
-       if ((ret = pthread_create (thread, attr, start_routine, arg)) == 0) {
-               std::pair<string,pthread_t> newpair;
-               newpair.first = name;
-               newpair.second = *thread;
-
-               pthread_mutex_lock (&thread_map_lock);
-               all_threads.insert (newpair);
-
-               pthread_mutex_unlock (&thread_map_lock);
-       }
-       
-       return ret;
-}
-
-string
-pthread_name ()
-{
-       pthread_t self = pthread_self();
-       string str;
-
-       pthread_mutex_lock (&thread_map_lock);
-       for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
-               if (i->second == self) {
-                       str = i->first;
-                       pthread_mutex_unlock (&thread_map_lock);
-                       return str;
-               }
-       }
-       pthread_mutex_unlock (&thread_map_lock);
-       return "unknown";
-}
-
-void
-pthread_kill_all (int signum) 
-{      
-       pthread_mutex_lock (&thread_map_lock);
-       for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
-               if (i->second != pthread_self()) {
-                       pthread_kill (i->second, signum);
-               }
-       }
-       all_threads.clear();
-       pthread_mutex_unlock (&thread_map_lock);
-}
-
-void
-pthread_cancel_all () 
-{      
-       pthread_mutex_lock (&thread_map_lock);
-       for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
-               if (i->second != pthread_self()) {
-                       pthread_cancel (i->second);
-               }
-       }
-       all_threads.clear();
-       pthread_mutex_unlock (&thread_map_lock);
-}
-
-void
-pthread_cancel_one (pthread_t thread) 
-{      
-       pthread_mutex_lock (&thread_map_lock);
-       for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
-               if (i->second == thread) {
-                       all_threads.erase (i);
-                       break;
-               }
-       }
-
-       pthread_cancel (thread);
-       pthread_mutex_unlock (&thread_map_lock);
-}
-
-void
-pthread_exit_pbd (void* status) 
-{      
-       pthread_t thread = pthread_self();
-
-       pthread_mutex_lock (&thread_map_lock);
-       for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
-               if (i->second == thread) {
-                       all_threads.erase (i);
-                       break;
-               }
-       }
-       pthread_mutex_unlock (&thread_map_lock);
-       pthread_exit (status);
-}
diff --git a/libs/pbd3/receiver.cc b/libs/pbd3/receiver.cc
deleted file mode 100644 (file)
index 5e7c10d..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#include <vector>
-
-#include <pbd/receiver.h>
-#include <pbd/transmitter.h>
-
-using namespace sigc;
-
-Receiver::Receiver () {}
-
-Receiver::~Receiver ()
-
-{
-       hangup ();
-}
-
-void
-Receiver::hangup ()
-{
-       vector<sigc::connection *>::iterator i;
-
-       for (i = connections.begin(); i != connections.end (); i++) {
-               (*i)->disconnect ();
-               delete *i;
-       }
-
-       connections.erase (connections.begin(), connections.end());
-}
-
-void
-Receiver::listen_to (Transmitter &transmitter)
-
-{
-       sigc::connection *c = new sigc::connection;
-
-       (*c) = transmitter.sender().connect(mem_fun(*this, &Receiver::receive));
-
-       connections.push_back (c);
-}
diff --git a/libs/pbd3/stacktrace.cc b/libs/pbd3/stacktrace.cc
deleted file mode 100644 (file)
index 1e7dfa0..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#include <pbd/stacktrace.h>
-#include <iostream>
-
-/* Obtain a backtrace and print it to stdout. */
-
-#ifdef HAVE_EXECINFO
-
-#include <execinfo.h>
-#include <stdlib.h>
-
-void
-PBD::stacktrace (std::ostream& out)
-{
-       void *array[200];
-       size_t size;
-       char **strings;
-       size_t i;
-     
-       size = backtrace (array, 200);
-       strings = backtrace_symbols (array, size);
-     
-       if (strings) {
-
-               printf ("Obtained %zd stack frames.\n", size);
-               
-               for (i = 0; i < size; i++) {
-                       out << strings[i] << std::endl;
-               }
-               
-               free (strings);
-       }
-}
-
-#else
-
-void
-PBD::stacktrace (std::ostream& out)
-{
-       out << "stack tracing is not enabled on this platform" << std::endl;
-}
-
-#endif /* HAVE_EXECINFO */
diff --git a/libs/pbd3/strsplit.cc b/libs/pbd3/strsplit.cc
deleted file mode 100644 (file)
index 7f29a77..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <pbd/strsplit.h>
-
-using namespace std;
-
-void
-split (string str, vector<string>& result, char splitchar)
-{      
-       string::size_type pos;
-       string remaining;
-       string::size_type len = str.length();
-       int cnt;
-
-       cnt = 0;
-
-       if (str.empty()) {
-               return;
-       }
-
-       for (string::size_type n = 0; n < len; ++n) {
-               if (str[n] == splitchar) {
-                       cnt++;
-               }
-       }
-
-       if (cnt == 0) {
-               result.push_back (str);
-               return;
-       }
-
-       remaining = str;
-
-       while ((pos = remaining.find_first_of (':')) != string::npos) {
-               result.push_back (remaining.substr (0, pos));
-               remaining = remaining.substr (pos+1);
-       }
-
-       if (remaining.length()) {
-
-               result.push_back (remaining);
-       }
-}
diff --git a/libs/pbd3/textreceiver.cc b/libs/pbd3/textreceiver.cc
deleted file mode 100644 (file)
index 43620e9..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#include <iostream>
-#include <cstdlib>
-
-#include <pbd/textreceiver.h>
-
-TextReceiver::TextReceiver (const string &n)
-
-{
-       name = n;
-}
-
-void
-TextReceiver::receive (Transmitter::Channel chn, const char *str)
-
-{
-       const char *prefix = "";
-
-       switch (chn) {
-       case Transmitter::Error:
-               prefix = ": [ERROR]: ";
-               break;
-       case Transmitter::Info:
-               prefix = ": [INFO]: ";
-               break;
-       case Transmitter::Warning:
-               prefix = ": [WARNING]: ";
-               break;
-       case Transmitter::Fatal:
-               prefix = ": [FATAL]: ";
-               break;
-       case Transmitter::Throw:
-               /* this isn't supposed to happen */
-               abort ();
-       }
-
-       /* note: iostreams are already thread-safe: no external
-          lock required.
-       */
-       
-       cout << name << prefix << str << endl;
-
-       if (chn == Transmitter::Fatal) {
-               exit (9);
-       }
-}
-
diff --git a/libs/pbd3/transmitter.cc b/libs/pbd3/transmitter.cc
deleted file mode 100644 (file)
index 876a9d8..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-    Copyright (C) 1998-99 Paul Barton-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$
-*/
-
-#include <cstdlib>
-#include <signal.h>
-#include <iostream>
-#include <string>
-
-#include <pbd/transmitter.h>
-#include <pbd/error.h>
-
-using std::string;
-using std::ios;
-
-Transmitter::Transmitter (Channel c)
-{
-       channel = c;
-       switch (c) {
-       case Error:
-               send = &error;
-               break;
-       case Warning:
-               send = &warning;
-               break;
-       case Info:
-               send = &info;
-               break;
-       case Fatal:
-               send = &fatal;
-               break;
-       case Throw:
-               /* we should never call Transmitter::deliver
-                  for thrown messages (because its overridden in the
-                  class heirarchy). force a segv if we do.
-               */
-               send = 0;
-               break;
-       }
-}              
-
-void
-Transmitter::deliver ()
-
-{
-       string foo;
-
-       /* NOTE: this is just a default action for a Transmitter or a
-          derived class. Any class can override this to produce some
-          other action when deliver() is called. 
-       */
-
-       *this << '\0';
-
-       /* send the SigC++ signal */
-
-       foo = str();
-       (*send) (channel, foo.c_str());
-
-       /* XXX when or how can we delete this ? */
-       // delete foo;
-
-       /* return to a pristine state */
-
-       clear ();
-       seekp (0, ios::beg);
-       seekg (0, ios::beg);
-
-       /* do the right thing if this should not return */
-       
-       if (does_not_return()) {
-               sigset_t mask;
-               
-               sigemptyset (&mask);
-               sigsuspend (&mask);
-               /*NOTREACHED*/
-               exit (1);
-       } 
-}
-
-bool
-Transmitter::does_not_return ()
-
-{
-       if (channel == Fatal || channel == Throw) {
-               return true;
-       } else {
-               return false;
-       }
-}
-
-
-extern "C" {
-  void pbd_c_error (const char *str)
-  {
-       PBD::error << str << endmsg;
-  }
-}
diff --git a/libs/pbd3/undo.cc b/libs/pbd3/undo.cc
deleted file mode 100644 (file)
index aa27f95..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/* 
-    Copyright (C) 2001 Brett Viren & 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$
-*/
-
-#include <iostream>
-
-#include <pbd/undo.h>
-
-using namespace std;
-using namespace sigc;
-
-UndoTransaction::UndoTransaction ()
-{
-}
-
-UndoTransaction::UndoTransaction (const UndoTransaction& rhs)
-{
-       _name = rhs._name;
-       clear ();
-       actions.insert(actions.end(),rhs.actions.begin(),rhs.actions.end());
-}
-
-UndoTransaction& 
-UndoTransaction::operator= (const UndoTransaction& rhs)
-{
-       if (this == &rhs) return *this;
-       _name = rhs._name;
-       clear ();
-       actions.insert(actions.end(),rhs.actions.begin(),rhs.actions.end());
-       return *this;
-}
-
-void
-UndoTransaction::add_command (Command *const action)
-{
-       actions.push_back (action);
-}
-
-void
-UndoTransaction::clear ()
-{
-       actions.clear ();
-}
-
-void
-UndoTransaction::operator() ()
-{
-       for (list<Command*>::iterator i = actions.begin(); i != actions.end(); ++i) {
-               (*(*i))();
-       }
-}
-
-void
-UndoTransaction::undo ()
-{
-       cerr << "Undo " << _name << endl;
-       for (list<Command*>::reverse_iterator i = actions.rbegin(); i != actions.rend(); ++i) {
-               (*i)->undo();
-       }
-}
-
-void
-UndoTransaction::redo ()
-{
-       cerr << "Redo " << _name << endl;
-        (*this)();
-}
-
-XMLNode &UndoTransaction::serialize()
-{
-    XMLNode *node = new XMLNode ("UndoTransaction");
-    // TODO
-    return *node;
-}
-
-void
-UndoHistory::add (UndoTransaction ut)
-{
-       UndoList.push_back (ut);
-}
-
-void
-UndoHistory::undo (unsigned int n)
-{
-       while (n--) {
-               if (UndoList.size() == 0) {
-                       return;
-               }
-               UndoTransaction ut = UndoList.back ();
-               UndoList.pop_back ();
-               ut.undo ();
-               RedoList.push_back (ut);
-       }
-}
-
-void
-UndoHistory::redo (unsigned int n)
-{
-       while (n--) {
-               if (RedoList.size() == 0) {
-                       return;
-               }
-               UndoTransaction ut = RedoList.back ();
-               RedoList.pop_back ();
-               ut.redo ();
-               UndoList.push_back (ut);
-       }
-}
-
-void
-UndoHistory::clear_redo ()
-{
-       RedoList.clear ();
-}
-
-void
-UndoHistory::clear_undo ()
-{
-       UndoList.clear ();
-}
-
-void
-UndoHistory::clear ()
-{
-       RedoList.clear ();
-       UndoList.clear ();
-}
diff --git a/libs/pbd3/whitespace.cc b/libs/pbd3/whitespace.cc
deleted file mode 100644 (file)
index 7f74940..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <pbd/whitespace.h>
-
-using namespace std;
-
-void
-strip_whitespace_edges (string& str)
-{   
-    string::size_type i; 
-    string::size_type len;    
-       string::size_type s;
-                                   
-    len = str.length();
-                                       
-    for (i = 0; i < len; ++i) {
-        if (isgraph (str[i])) {
-            break;
-        }
-    }
-
-    s = i;
-
-    for (i = len - 1; i >= 0; --i) {
-        if (isgraph (str[i])) {
-            break;
-        }
-    }
-
-    str = str.substr (s, (i - s) + 1);
-}
-
diff --git a/libs/pbd3/xml++.cc b/libs/pbd3/xml++.cc
deleted file mode 100644 (file)
index e496d8b..0000000
+++ /dev/null
@@ -1,422 +0,0 @@
-/* xml++.cc
- * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and
- * are covered by the GNU Lesser General Public License, which should be
- * included with libxml++ as the file COPYING.
- */
-
-#include <pbd/xml++.h>
-#include <libxml/debugXML.h>
-
-static XMLNode *readnode(xmlNodePtr);
-static void writenode(xmlDocPtr, XMLNode *, xmlNodePtr, int);
-
-XMLTree::XMLTree() 
-       : _filename(), 
-       _root(), 
-       _compression(0), 
-       _initialized(false) 
-{ 
-}
-
-XMLTree::XMLTree(const string &fn)
-       : _filename(fn), 
-       _root(0), 
-       _compression(0), 
-       _initialized(false) 
-{ 
-       read(); 
-}
-
-XMLTree::XMLTree(const XMLTree * from)
-{
-    _filename = from->filename();
-    _root = new XMLNode(*from->root());
-    _compression = from->compression();
-    _initialized = true;
-}
-
-XMLTree::~XMLTree()
-{
-    if (_initialized && _root)
-               delete _root;
-}
-
-int 
-XMLTree::set_compression(int c)
-{
-    if (c > 9)
-               c = 9;
-
-    if (c < 0)
-               c = 0;
-
-    _compression = c;
-
-    return _compression;
-}
-
-bool 
-XMLTree::read(void)
-{
-    xmlDocPtr doc;
-
-    if (_root) {
-               delete _root;
-               _root = 0;
-    }
-
-    xmlKeepBlanksDefault(0);
-
-    doc = xmlParseFile(_filename.c_str());
-    if (!doc) {
-               _initialized = false;
-               return false;
-    }
-
-    _root = readnode(xmlDocGetRootElement(doc));
-    xmlFreeDoc(doc);
-    _initialized = true;
-
-    return true;
-}
-
-bool 
-XMLTree::read_buffer(const string & buffer)
-{
-    xmlDocPtr doc;
-
-    _filename = "";
-
-    if (_root) {
-               delete _root;
-               _root = 0;
-    }
-
-    doc = xmlParseMemory((char *) buffer.c_str(), buffer.length());
-    if (!doc) {
-               _initialized = false;
-               return false;
-    }
-
-    _root = readnode(xmlDocGetRootElement(doc));
-    xmlFreeDoc(doc);
-    _initialized = true;
-
-    return true;
-}
-
-bool 
-XMLTree::write(void) const
-{
-    xmlDocPtr doc;
-    XMLNodeList children;
-    int result;
-
-    xmlKeepBlanksDefault(0);
-    doc = xmlNewDoc((xmlChar *) "1.0");
-    xmlSetDocCompressMode(doc, _compression);
-    writenode(doc, _root, doc->children, 1);
-    result = xmlSaveFormatFile(_filename.c_str(), doc, 1);
-    xmlFreeDoc(doc);
-
-    if (result == -1)
-               return false;
-
-    return true;
-}
-
-void
-XMLTree::debug(FILE* out) const
-{
-    xmlDocPtr doc;
-    XMLNodeList children;
-
-    xmlKeepBlanksDefault(0);
-    doc = xmlNewDoc((xmlChar *) "1.0");
-    xmlSetDocCompressMode(doc, _compression);
-    writenode(doc, _root, doc->children, 1);
-    xmlDebugDumpDocument (out, doc);
-    xmlFreeDoc(doc);
-}
-
-const string & 
-XMLTree::write_buffer(void) const
-{
-    static string retval;
-    char *ptr;
-    int len;
-    xmlDocPtr doc;
-    XMLNodeList children;
-
-    xmlKeepBlanksDefault(0);
-    doc = xmlNewDoc((xmlChar *) "1.0");
-    xmlSetDocCompressMode(doc, _compression);
-    writenode(doc, _root, doc->children, 1);
-    xmlDocDumpMemory(doc, (xmlChar **) & ptr, &len);
-    xmlFreeDoc(doc);
-
-    retval = ptr;
-
-    free(ptr);
-
-    return retval;
-}
-
-XMLNode::XMLNode(const string & n)
-       :  _name(n), _is_content(false), _content(string())
-{
-
-    if (_name.empty())
-               _initialized = false;
-    else
-               _initialized = true;
-}
-
-XMLNode::XMLNode(const string & n, const string & c)
-       :_name(string()), _is_content(true), _content(c)
-{
-    _initialized = true;
-}
-
-XMLNode::XMLNode(const XMLNode& from)
-       : _initialized(false)
-{
-    XMLPropertyList props;
-    XMLPropertyIterator curprop;
-    XMLNodeList nodes;
-    XMLNodeIterator curnode;
-
-    _name = from.name();
-    set_content(from.content());
-
-    props = from.properties();
-    for (curprop = props.begin(); curprop != props.end(); curprop++)
-       add_property((*curprop)->name().c_str(), (*curprop)->value());
-
-    nodes = from.children();
-    for (curnode = nodes.begin(); curnode != nodes.end(); curnode++)
-               add_child_copy(**curnode);
-}
-
-XMLNode::~XMLNode()
-{
-    XMLNodeIterator curchild;
-    XMLPropertyIterator curprop;
-
-    for (curchild = _children.begin(); curchild != _children.end();
-                       curchild++)
-               delete *curchild;
-
-    for (curprop = _proplist.begin(); curprop != _proplist.end();
-                       curprop++)
-               delete *curprop;
-}
-
-const string & 
-XMLNode::set_content(const string & c)
-{
-    if (c.empty())
-               _is_content = false;
-    else
-               _is_content = true;
-
-    _content = c;
-
-    return _content;
-}
-
-const XMLNodeList & 
-XMLNode::children(const string & n) const
-{
-    static XMLNodeList retval;
-    XMLNodeConstIterator cur;
-
-    if (n.length() == 0)
-               return _children;
-
-    retval.erase(retval.begin(), retval.end());
-
-    for (cur = _children.begin(); cur != _children.end(); cur++)
-               if ((*cur)->name() == n)
-                   retval.insert(retval.end(), *cur);
-
-    return retval;
-}
-
-XMLNode *
-XMLNode::add_child(const char * n)
-{
-       return add_child_copy(XMLNode (n));
-}
-
-void
-XMLNode::add_child_nocopy (XMLNode& n)
-{
-       _children.insert(_children.end(), &n);
-}
-
-XMLNode *
-XMLNode::add_child_copy(const XMLNode& n)
-{
-       XMLNode *copy = new XMLNode (n);
-       _children.insert(_children.end(), copy);
-       return copy;
-}
-
-XMLNode *
-XMLNode::add_content(const string & c)
-{
-       return add_child_copy(XMLNode (string(), c));
-}
-
-XMLProperty *
-XMLNode::property(const char * n)
-{
-       string ns(n);
-       if (_propmap.find(ns) == _propmap.end())
-               return 0;
-       return _propmap[ns];
-}
-
-XMLProperty *
-XMLNode::add_property(const char * n, const string & v)
-{
-       string ns(n);
-       if(_propmap.find(ns) != _propmap.end()){
-               remove_property(ns);
-       }
-
-       XMLProperty *tmp = new XMLProperty(ns, v);
-
-       if (!tmp)
-               return 0;
-
-       _propmap[tmp->name()] = tmp;
-       _proplist.insert(_proplist.end(), tmp);
-
-       return tmp;
-}
-
-XMLProperty *
-XMLNode::add_property(const char * n, const char * v)
-{
-       string vs(v);
-       return add_property(n, vs);
-}
-
-void 
-XMLNode::remove_property(const string & n)
-{
-    if (_propmap.find(n) != _propmap.end()) {
-               _proplist.remove(_propmap[n]);
-               _propmap.erase(n);
-    }
-}
-
-void 
-XMLNode::remove_nodes(const string & n)
-{
-    XMLNodeIterator i = _children.begin();
-    XMLNodeIterator tmp;
-
-    while (i != _children.end()) {
-           tmp = i;
-           ++tmp;
-           if ((*i)->name() == n) {
-                   _children.erase (i);
-           }
-           i = tmp;
-    }
-}
-
-void 
-XMLNode::remove_nodes_and_delete(const string & n)
-{
-    XMLNodeIterator i = _children.begin();
-    XMLNodeIterator tmp;
-
-    while (i != _children.end()) {
-           tmp = i;
-           ++tmp;
-           if ((*i)->name() == n) {
-                   delete *i;
-                   _children.erase (i);
-           }
-           i = tmp;
-    }
-}
-
-XMLProperty::XMLProperty(const string &n, const string &v)
-       : _name(n), 
-       _value(v) 
-{ 
-}
-
-XMLProperty::~XMLProperty()
-{
-}
-
-static XMLNode *
-readnode(xmlNodePtr node)
-{
-    string name, content;
-    xmlNodePtr child;
-    XMLNode *tmp;
-    xmlAttrPtr attr;
-
-    if (node->name)
-               name = (char *) node->name;
-
-    tmp = new XMLNode(name);
-
-    for (attr = node->properties; attr; attr = attr->next) {
-               content = "";
-               if (attr->children)
-                   content = (char *) attr->children->content;
-               tmp->add_property((char *) attr->name, content);
-    }
-
-    if (node->content)
-               tmp->set_content((char *) node->content);
-    else
-               tmp->set_content(string());
-
-    for (child = node->children; child; child = child->next)
-           tmp->add_child_nocopy (*readnode(child));
-
-    return tmp;
-}
-
-static void 
-writenode(xmlDocPtr doc, XMLNode * n, xmlNodePtr p, int root =
-                     0)
-{
-    XMLPropertyList props;
-    XMLPropertyIterator curprop;
-    XMLNodeList children;
-    XMLNodeIterator curchild;
-    xmlNodePtr node;
-
-    if (root)
-               node = doc->children =
-                           xmlNewDocNode(doc, 0, (xmlChar *) n->name().c_str(), 0);
-
-    else
-               node = xmlNewChild(p, 0, (xmlChar *) n->name().c_str(), 0);
-
-    if (n->is_content()) {
-               node->type = XML_TEXT_NODE;
-               xmlNodeSetContentLen(node, (const xmlChar *) n->content().c_str(),
-                            n->content().length());
-    }
-
-    props = n->properties();
-    for (curprop = props.begin(); curprop != props.end(); curprop++)
-               xmlSetProp(node, (xmlChar *) (*curprop)->name().c_str(),
-                          (xmlChar *) (*curprop)->value().c_str());
-
-    children = n->children();
-    for (curchild = children.begin(); curchild != children.end();
-                        curchild++)
-               writenode(doc, *curchild, node);
-}
index dc6a97001accb8caa4c7378cef799358ea7189ff..c404675ecdefb7fb4f2b2b354d325d64d878344c 100644 (file)
@@ -105,6 +105,6 @@ namespace soundtouch
         #endif
 
     #endif  // INTEGER_SAMPLES
-};
+}
 
 #endif
index f8a7d574f56622c573b0f57e3fa566890d746414..ce59b1c67c8aabaf93c695d8616576906b3b7fd9 100644 (file)
@@ -34,7 +34,7 @@ cp.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
 cp.Merge ([
     libraries['ardour'],
     libraries['sigc2'],
-    libraries['pbd3'],
+    libraries['pbd'],
     libraries['midi++2'],
     libraries['xml'],
     libraries['usb'],
index 10295bc698d522d970d045db1b5d3c8c170bc11f..dd9adc206e87092dedbba97bc91efcce60879354 100644 (file)
@@ -49,7 +49,7 @@ void
 ControlProtocol::next_track (uint32_t initial_id)
 {
        uint32_t limit = session->nroutes();
-       Route* cr = route_table[0];
+       boost::shared_ptr<Route> cr = route_table[0];
        uint32_t id;
 
        if (cr) {
@@ -88,7 +88,7 @@ void
 ControlProtocol::prev_track (uint32_t initial_id)
 {
        uint32_t limit = session->nroutes() - 1;
-       Route* cr = route_table[0];
+       boost::shared_ptr<Route> cr = route_table[0];
        uint32_t id;
 
        if (cr) {
@@ -128,29 +128,32 @@ void
 ControlProtocol::set_route_table_size (uint32_t size)
 {
        while (route_table.size() < size) {
-               route_table.push_back (0);
+               route_table.push_back (boost::shared_ptr<Route> ((Route*) 0));
        }
 }
 
 void
-ControlProtocol::set_route_table (uint32_t table_index, ARDOUR::Route*)
+ControlProtocol::set_route_table (uint32_t table_index, boost::shared_ptr<ARDOUR::Route> r)
 {
+       if (table_index >= route_table.size()) {
+               return;
+       }
+       
+       route_table[table_index] = r;
+
+       // XXX SHAREDPTR need to handle r->GoingAway
 }
 
 bool
 ControlProtocol::set_route_table (uint32_t table_index, uint32_t remote_control_id)
 {
-       if (table_index >= route_table.size()) {
-               return false;
-       }
-               
-       Route* r = session->route_by_remote_id (remote_control_id);
+       boost::shared_ptr<Route> r = session->route_by_remote_id (remote_control_id);
 
        if (!r) {
                return false;
        }
-       
-       route_table[table_index] = r;
+
+       set_route_table (table_index, r);
 
        return true;
 }
@@ -162,9 +165,9 @@ ControlProtocol::route_set_rec_enable (uint32_t table_index, bool yn)
                return;
        }
 
-       Route* r = route_table[table_index];
+       boost::shared_ptr<Route> r = route_table[table_index];
 
-       AudioTrack* at = dynamic_cast<AudioTrack*>(r);
+       boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack>(r);
 
        if (at) {
                at->set_record_enable (yn, this);
@@ -178,9 +181,9 @@ ControlProtocol::route_get_rec_enable (uint32_t table_index)
                return false;
        }
 
-       Route* r = route_table[table_index];
+       boost::shared_ptr<Route> r = route_table[table_index];
 
-       AudioTrack* at = dynamic_cast<AudioTrack*>(r);
+       boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack>(r);
 
        if (at) {
                return at->record_enabled ();
@@ -197,7 +200,7 @@ ControlProtocol::route_get_gain (uint32_t table_index)
                return 0.0f;
        }
 
-       Route* r = route_table[table_index];
+       boost::shared_ptr<Route> r = route_table[table_index];
 
        if (r == 0) {
                return 0.0f;
@@ -213,7 +216,7 @@ ControlProtocol::route_set_gain (uint32_t table_index, float gain)
                return;
        }
 
-       Route* r = route_table[table_index];
+       boost::shared_ptr<Route> r = route_table[table_index];
        
        if (r != 0) {
                r->set_gain (gain, this);
@@ -227,7 +230,7 @@ ControlProtocol::route_get_effective_gain (uint32_t table_index)
                return 0.0f;
        }
 
-       Route* r = route_table[table_index];
+       boost::shared_ptr<Route> r = route_table[table_index];
 
        if (r == 0) {
                return 0.0f;
@@ -244,7 +247,7 @@ ControlProtocol::route_get_peak_input_power (uint32_t table_index, uint32_t whic
                return 0.0f;
        }
 
-       Route* r = route_table[table_index];
+       boost::shared_ptr<Route> r = route_table[table_index];
 
        if (r == 0) {
                return 0.0f;
@@ -261,7 +264,7 @@ ControlProtocol::route_get_muted (uint32_t table_index)
                return false;
        }
 
-       Route* r = route_table[table_index];
+       boost::shared_ptr<Route> r = route_table[table_index];
 
        if (r == 0) {
                return false;
@@ -277,7 +280,7 @@ ControlProtocol::route_set_muted (uint32_t table_index, bool yn)
                return;
        }
 
-       Route* r = route_table[table_index];
+       boost::shared_ptr<Route> r = route_table[table_index];
 
        if (r != 0) {
                r->set_mute (yn, this);
@@ -292,7 +295,7 @@ ControlProtocol::route_get_soloed (uint32_t table_index)
                return false;
        }
 
-       Route* r = route_table[table_index];
+       boost::shared_ptr<Route> r = route_table[table_index];
 
        if (r == 0) {
                return false;
@@ -308,7 +311,7 @@ ControlProtocol::route_set_soloed (uint32_t table_index, bool yn)
                return;
        }
 
-       Route* r = route_table[table_index];
+       boost::shared_ptr<Route> r = route_table[table_index];
 
        if (r != 0) {
                r->set_solo (yn, this);
@@ -322,7 +325,7 @@ ControlProtocol:: route_get_name (uint32_t table_index)
                return "";
        }
 
-       Route* r = route_table[table_index];
+       boost::shared_ptr<Route> r = route_table[table_index];
 
        if (r == 0) {
                return "";
index 69135f2b4b010c3f1a60603582cebed802632494..8be652b9df9d9285b0995b24f1f543716fa29735 100644 (file)
@@ -25,8 +25,9 @@
 #include <string>
 #include <vector>
 #include <list>
+#include <boost/shared_ptr.hpp>
 #include <sigc++/sigc++.h>
-
+#include <pbd/stateful.h>
 #include <control_protocol/basic_ui.h>
 
 namespace ARDOUR {
@@ -34,7 +35,7 @@ namespace ARDOUR {
 class Route;
 class Session;
 
-class ControlProtocol : public sigc::trackable, public BasicUI {
+class ControlProtocol : public sigc::trackable, public Stateful, public BasicUI {
   public:
        ControlProtocol (Session&, std::string name);
        virtual ~ControlProtocol();
@@ -73,7 +74,7 @@ class ControlProtocol : public sigc::trackable, public BasicUI {
        */
 
        void set_route_table_size (uint32_t size);
-       void set_route_table (uint32_t table_index, ARDOUR::Route*);
+       void set_route_table (uint32_t table_index, boost::shared_ptr<ARDOUR::Route>);
        bool set_route_table (uint32_t table_index, uint32_t remote_control_id);
 
        void route_set_rec_enable (uint32_t table_index, bool yn);
@@ -94,7 +95,7 @@ class ControlProtocol : public sigc::trackable, public BasicUI {
        std::string route_get_name (uint32_t table_index);
 
   protected:
-       std::vector<ARDOUR::Route*> route_table;
+       std::vector<boost::shared_ptr<ARDOUR::Route> > route_table;
        std::string _name;
        bool _active;
 
index 1760eb24e912386c1435267077b80a652ecd4587..f9c2de08f8da1be37234244a000aa8fdacf9cfdf 100644 (file)
@@ -23,6 +23,7 @@ genericmidi.Append(POTFILE = domain + '.pot')
 genericmidi_files=Split("""
 interface.cc
 generic_midi_control_protocol.cc
+midicontrollable.cc
 """)
 
 genericmidi.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
@@ -34,7 +35,7 @@ genericmidi.Merge ([
        libraries['ardour'],
        libraries['ardour_cp'],
        libraries['midi++2'],
-       libraries['pbd3'],
+       libraries['pbd'],
        libraries['sigc2'],
        libraries['usb'],
        libraries['xml'],
index 95b9d223931d0f3fc1a25589081922efea6b1556..d905c0bc41bcf1299007f3dedc57973811cd2a01 100644 (file)
@@ -1,20 +1,65 @@
+/*
+    Copyright (C) 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
+    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$
+*/
+
+#include <algorithm>
+
+#include <pbd/error.h>
+#include <pbd/failed_constructor.h>
+
 #include <midi++/port.h>
+#include <midi++/manager.h>
+#include <midi++/port_request.h>
 
 #include <ardour/route.h>
 #include <ardour/session.h>
 
 #include "generic_midi_control_protocol.h"
+#include "midicontrollable.h"
 
 using namespace ARDOUR;
+using namespace PBD;
 
 #include "i18n.h"
 
 GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
        : ControlProtocol  (s, _("GenericMIDI"))
 {
-       _port = s.midi_port();
-       s.MIDI_PortChanged.connect (mem_fun (*this, &GenericMidiControlProtocol::port_change));
+       MIDI::Manager* mm = MIDI::Manager::instance();
+
+       /* XXX it might be nice to run "control" through i18n, but thats a bit tricky because
+          the name is defined in ardour.rc which is likely not internationalized.
+       */
        
+       _port = mm->port (X_("control"));
+
+       if (_port == 0) {
+               error << _("no MIDI port named \"control\" exists - generic MIDI control disabled") << endmsg;
+               throw failed_constructor();
+       }
+
+       _feedback_interval = 10000; // microseconds
+       last_feedback_time = 0;
+
+       Controllable::StartLearning.connect (mem_fun (*this, &GenericMidiControlProtocol::start_learning));
+       Controllable::StopLearning.connect (mem_fun (*this, &GenericMidiControlProtocol::stop_learning));
+       Session::SendFeedback.connect (mem_fun (*this, &GenericMidiControlProtocol::send_feedback));
 }
 
 GenericMidiControlProtocol::~GenericMidiControlProtocol ()
@@ -24,42 +69,165 @@ GenericMidiControlProtocol::~GenericMidiControlProtocol ()
 int
 GenericMidiControlProtocol::set_active (bool yn)
 {
-       /* start delivery/outbound thread */
+       /* start/stop delivery/outbound thread */
        return 0;
 }
 
 void
-GenericMidiControlProtocol::port_change ()
+GenericMidiControlProtocol::set_feedback_interval (microseconds_t ms)
 {
-       _port = session->midi_port ();
+       _feedback_interval = ms;
 }
 
-void
-GenericMidiControlProtocol::set_port (MIDI::Port* p)
+void 
+GenericMidiControlProtocol::send_feedback ()
 {
-       _port = p;
+       microseconds_t now = get_microseconds ();
+
+       if (last_feedback_time != 0) {
+               if ((now - last_feedback_time) < _feedback_interval) {
+                       return;
+               }
+       }
+
+       _send_feedback ();
+       
+       last_feedback_time = now;
 }
 
 void 
-GenericMidiControlProtocol::send_route_feedback (list<Route*>& routes)
+GenericMidiControlProtocol::_send_feedback ()
 {
-       if (_port != 0) {
-
-               const int32_t bufsize = 16 * 1024;
-               MIDI::byte buf[bufsize];
-               int32_t bsize = bufsize;
-               MIDI::byte* end = buf;
-               
-               for (list<Route*>::iterator r = routes.begin(); r != routes.end(); ++r) {
-                       end = (*r)->write_midi_feedback (end, bsize);
+       const int32_t bufsize = 16 * 1024;
+       MIDI::byte buf[bufsize];
+       int32_t bsize = bufsize;
+       MIDI::byte* end = buf;
+       
+       for (MIDIControllables::iterator r = controllables.begin(); r != controllables.end(); ++r) {
+               end = (*r)->write_feedback (end, bsize);
+       }
+       
+       if (end == buf) {
+               return;
+       } 
+       
+       _port->write (buf, (int32_t) (end - buf));
+}
+
+bool
+GenericMidiControlProtocol::start_learning (Controllable* c)
+{
+       if (c == 0) {
+               return false;
+       }
+
+       MIDIControllable* mc = new MIDIControllable (*_port, *c);
+       
+       {
+               Glib::Mutex::Lock lm (pending_lock);
+               std::pair<MIDIControllables::iterator,bool> result;
+               result = pending_controllables.insert (mc);
+               if (result.second) {
+                       c->LearningFinished.connect (bind (mem_fun (*this, &GenericMidiControlProtocol::learning_stopped), mc));
                }
-               
-               if (end == buf) {
-                       return;
-               } 
-               
-               _port->write (buf, (int32_t) (end - buf));
-               //cerr << "MIDI feedback: wrote " << (int32_t) (end - buf) << " to midi port\n";
        }
+
+       mc->learn_about_external_control ();
+       return true;
 }
 
+void
+GenericMidiControlProtocol::learning_stopped (MIDIControllable* mc)
+{
+       Glib::Mutex::Lock lm (pending_lock);
+       Glib::Mutex::Lock lm2 (controllables_lock);
+       
+       MIDIControllables::iterator i = find (pending_controllables.begin(), pending_controllables.end(), mc);
+
+       if (i != pending_controllables.end()) {
+               pending_controllables.erase (i);
+       }
+
+       controllables.insert (mc);
+}
+
+void
+GenericMidiControlProtocol::stop_learning (Controllable* c)
+{
+       Glib::Mutex::Lock lm (pending_lock);
+
+       /* learning timed out, and we've been told to consider this attempt to learn to be cancelled. find the
+          relevant MIDIControllable and remove it from the pending list.
+       */
+
+       for (MIDIControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
+               if (&(*i)->get_controllable() == c) {
+                       (*i)->stop_learning ();
+                       delete (*i);
+                       pending_controllables.erase (i);
+                       break;
+               }
+       }
+}
+
+XMLNode&
+GenericMidiControlProtocol::get_state () 
+{
+       XMLNode* node = new XMLNode (_name); /* node name must match protocol name */
+       XMLNode* children = new XMLNode (X_("controls"));
+
+       node->add_child_nocopy (*children);
+
+       Glib::Mutex::Lock lm2 (controllables_lock);
+       for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
+               children->add_child_nocopy ((*i)->get_state());
+       }
+
+       return *node;
+}
+
+int
+GenericMidiControlProtocol::set_state (const XMLNode& node)
+{
+       XMLNodeList nlist;
+       XMLNodeConstIterator niter;
+       Controllable* c;
+
+       {
+               Glib::Mutex::Lock lm (pending_lock);
+               pending_controllables.clear ();
+       }
+
+       Glib::Mutex::Lock lm2 (controllables_lock);
+
+       controllables.clear ();
+
+       nlist = node.children();
+
+       if (nlist.empty()) {
+               return 0;
+       }
+
+       nlist = nlist.front()->children ();
+
+       for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+
+               XMLProperty* prop;
+
+               if ((prop = (*niter)->property ("id")) != 0) {
+
+                       ID id = prop->value ();
+
+                       c = session->controllable_by_id (id);
+
+                       if (c) {
+                               MIDIControllable* mc = new MIDIControllable (*_port, *c);
+                               if (mc->set_state (**niter) == 0) {
+                                       controllables.insert (mc);
+                               }
+                       }
+               }
+       }
+       
+       return 0;
+}
index 70cbd181c83210b4520bcb08f85241a26fc1926a..5f5a470b13c2c8b04c341a295067ffc54fb03675 100644 (file)
@@ -1,34 +1,58 @@
 #ifndef ardour_generic_midi_control_protocol_h
 #define ardour_generic_midi_control_protocol_h
 
+#include <set>
+#include <glibmm/thread.h>
+#include <ardour/types.h>
+
 #include <control_protocol/control_protocol.h>
 
 namespace MIDI {
        class Port;
 }
 
+namespace PBD {
+       class Controllable;
+}      
+
 namespace ARDOUR {
+       class Session;
+}
 
-class GenericMidiControlProtocol : public ControlProtocol {
+class MIDIControllable;
+
+class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
   public:
-       GenericMidiControlProtocol (Session&);
+       GenericMidiControlProtocol (ARDOUR::Session&);
        virtual ~GenericMidiControlProtocol();
 
        int set_active (bool yn);
        static bool probe() { return true; }
 
-       void set_port (MIDI::Port*);
        MIDI::Port* port () const { return _port; }
+       void set_feedback_interval (ARDOUR::microseconds_t);
+
+       XMLNode& get_state ();
+       int set_state (const XMLNode&);
 
-       void send_route_feedback (std::list<Route*>&);
-       
   private:
-       void route_feedback (ARDOUR::Route&, bool);
        MIDI::Port* _port;
+       ARDOUR::microseconds_t _feedback_interval;
+       ARDOUR::microseconds_t last_feedback_time;
 
-       void port_change ();
-};
+       void _send_feedback ();
+       void  send_feedback ();
 
-}
+       typedef std::set<MIDIControllable*> MIDIControllables;
+       MIDIControllables controllables;
+       MIDIControllables pending_controllables;
+       Glib::Mutex controllables_lock;
+       Glib::Mutex pending_lock;
+
+       bool start_learning (PBD::Controllable*);
+       void stop_learning (PBD::Controllable*);
+
+       void learning_stopped (MIDIControllable*);
+};
 
-#endif // ardour_generic_midi_control_protocol_h
+#endif /* ardour_generic_midi_control_protocol_h */
index c6c59c658992ec49e5f793074ed968ba184dddb6..230be694f23a66185c6ffdbaee6ce2c2cdf5c170 100644 (file)
@@ -1,3 +1,5 @@
+#include <pbd/failed_constructor.h>
+
 #include <control_protocol/control_protocol.h>
 #include "generic_midi_control_protocol.h"
 
@@ -6,7 +8,13 @@ using namespace ARDOUR;
 ControlProtocol*
 new_generic_midi_protocol (ControlProtocolDescriptor* descriptor, Session* s)
 {
-       GenericMidiControlProtocol* gmcp =  new GenericMidiControlProtocol (*s);
+       GenericMidiControlProtocol* gmcp;
+               
+       try {
+               gmcp =  new GenericMidiControlProtocol (*s);
+       } catch (failed_constructor& err) {
+               return 0;
+       }
        
        if (gmcp->set_active (true)) {
                delete gmcp;
diff --git a/libs/surfaces/generic_midi/midicontrollable.cc b/libs/surfaces/generic_midi/midicontrollable.cc
new file mode 100644 (file)
index 0000000..d6135fd
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+    Copyright (C) 1998-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
+    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: midicontrollable.cc 629 2006-06-21 23:01:03Z paul $
+*/
+
+#include <cstdio> /* for sprintf, sigh */
+#include <climits>
+#include <pbd/error.h>
+#include <pbd/xml++.h>
+#include <midi++/port.h>
+#include <midi++/channel.h>
+
+#include "midicontrollable.h"
+
+using namespace sigc;
+using namespace MIDI;
+using namespace PBD;
+using namespace ARDOUR;
+
+bool MIDIControllable::_send_feedback = false;
+
+MIDIControllable::MIDIControllable (Port& p, Controllable& c, bool is_bistate)
+       : controllable (c), _port (p), bistate (is_bistate)
+{
+       setting = false;
+       last_written = 0; // got a better idea ?
+       control_type = none;
+       _control_description = "MIDI Control: none";
+       control_additional = (byte) -1;
+       connections = 0;
+       feedback = true; // for now
+       
+       /* use channel 0 ("1") as the initial channel */
+
+       midi_rebind (0);
+}
+
+MIDIControllable::~MIDIControllable ()
+{
+       drop_external_control ();
+}
+
+void
+MIDIControllable::midi_forget ()
+{
+       /* stop listening for incoming messages, but retain
+          our existing event + type information.
+       */
+       
+       if (connections > 0) {
+               midi_sense_connection[0].disconnect ();
+       } 
+       
+       if (connections > 1) {
+               midi_sense_connection[1].disconnect ();
+       }
+       
+       connections = 0;
+       midi_learn_connection.disconnect ();
+       
+}
+
+void
+MIDIControllable::midi_rebind (channel_t c)
+{
+       if (c >= 0) {
+               bind_midi (c, control_type, control_additional);
+       } else {
+               midi_forget ();
+       }
+}
+
+void
+MIDIControllable::learn_about_external_control ()
+{
+       drop_external_control ();
+       midi_learn_connection = _port.input()->any.connect (mem_fun (*this, &MIDIControllable::midi_receiver));
+}
+
+void
+MIDIControllable::stop_learning ()
+{
+       midi_learn_connection.disconnect ();
+}
+
+void
+MIDIControllable::drop_external_control ()
+{
+       if (connections > 0) {
+               midi_sense_connection[0].disconnect ();
+       } 
+       if (connections > 1) {
+               midi_sense_connection[1].disconnect ();
+       }
+
+       connections = 0;
+       midi_learn_connection.disconnect ();
+
+       control_type = none;
+       control_additional = (byte) -1;
+}
+
+void 
+MIDIControllable::midi_sense_note_on (Parser &p, EventTwoBytes *tb) 
+{
+       midi_sense_note (p, tb, true);
+}
+
+void 
+MIDIControllable::midi_sense_note_off (Parser &p, EventTwoBytes *tb) 
+{
+       midi_sense_note (p, tb, false);
+}
+
+void
+MIDIControllable::midi_sense_note (Parser &p, EventTwoBytes *msg, bool is_on)
+{
+       if (!bistate) {
+               controllable.set_value (msg->note_number/127.0);
+       } else {
+
+               /* Note: parser handles the use of zero velocity to
+                  mean note off. if we get called with is_on=true, then we
+                  got a *real* note on.  
+               */
+
+               if (msg->note_number == control_additional) {
+                       controllable.set_value (is_on ? 1 : 0);
+               }
+       }
+}
+
+void
+MIDIControllable::midi_sense_controller (Parser &, EventTwoBytes *msg)
+{
+       if (control_additional == msg->controller_number) {
+               if (!bistate) {
+                       controllable.set_value (msg->value/127.0);
+               } else {
+                       if (msg->value > 64.0) {
+                               controllable.set_value (1);
+                       } else {
+                               controllable.set_value (0);
+                       }
+               }
+       }
+}
+
+void
+MIDIControllable::midi_sense_program_change (Parser &p, byte msg)
+{
+       /* XXX program change messages make no sense for bistates */
+
+       if (!bistate) {
+               controllable.set_value (msg/127.0);
+       } 
+}
+
+void
+MIDIControllable::midi_sense_pitchbend (Parser &p, pitchbend_t pb)
+{
+       /* pitchbend messages make no sense for bistates */
+
+       /* XXX gack - get rid of assumption about typeof pitchbend_t */
+
+       controllable.set_value ((pb/(float) SHRT_MAX));
+}                      
+
+void
+MIDIControllable::midi_receiver (Parser &p, byte *msg, size_t len)
+{
+       /* we only respond to channel messages */
+
+       if ((msg[0] & 0xF0) < 0x80 || (msg[0] & 0xF0) > 0xE0) {
+               return;
+       }
+
+       /* if the our port doesn't do input anymore, forget it ... */
+
+       if (!_port.input()) {
+               return;
+       }
+
+       bind_midi ((channel_t) (msg[0] & 0xf), eventType (msg[0] & 0xF0), msg[1]);
+
+       controllable.LearningFinished ();
+}
+
+void
+MIDIControllable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
+{
+       char buf[64];
+
+       drop_external_control ();
+
+       control_type = ev;
+       control_channel = chn;
+       control_additional = additional;
+
+       if (_port.input() == 0) {
+               return;
+       }
+       
+       Parser& p = *_port.input();
+
+       int chn_i = chn;
+       switch (ev) {
+       case MIDI::off:
+               midi_sense_connection[0] = p.channel_note_off[chn_i].connect
+                       (mem_fun (*this, &MIDIControllable::midi_sense_note_off));
+
+               /* if this is a bistate, connect to noteOn as well,
+                  and we'll toggle back and forth between the two.
+               */
+
+               if (bistate) {
+                       midi_sense_connection[1] = p.channel_note_on[chn_i].connect
+                               (mem_fun (*this, &MIDIControllable::midi_sense_note_on));
+                       connections = 2;
+               } else {
+                       connections = 1;
+               }
+               _control_description = "MIDI control: NoteOff";
+               break;
+
+       case MIDI::on:
+               midi_sense_connection[0] = p.channel_note_on[chn_i].connect
+                       (mem_fun (*this, &MIDIControllable::midi_sense_note_on));
+               if (bistate) {
+                       midi_sense_connection[1] = p.channel_note_off[chn_i].connect 
+                               (mem_fun (*this, &MIDIControllable::midi_sense_note_off));
+                       connections = 2;
+               } else {
+                       connections = 1;
+               }
+               _control_description = "MIDI control: NoteOn";
+               break;
+
+       case MIDI::controller:
+               midi_sense_connection[0] = p.channel_controller[chn_i].connect 
+                       (mem_fun (*this, &MIDIControllable::midi_sense_controller));
+               connections = 1;
+               snprintf (buf, sizeof (buf), "MIDI control: Controller %d", control_additional);
+               _control_description = buf;
+               break;
+
+       case MIDI::program:
+               if (!bistate) {
+                       midi_sense_connection[0] = p.channel_program_change[chn_i].connect
+                               (mem_fun (*this, 
+                                      &MIDIControllable::midi_sense_program_change));
+                       connections = 1;
+                       _control_description = "MIDI control: ProgramChange";
+               }
+               break;
+
+       case MIDI::pitchbend:
+               if (!bistate) {
+                       midi_sense_connection[0] = p.channel_pitchbend[chn_i].connect
+                               (mem_fun (*this, &MIDIControllable::midi_sense_pitchbend));
+                       connections = 1;
+                       _control_description = "MIDI control: Pitchbend";
+               }
+               break;
+
+       default:
+               break;
+       }
+}
+
+void
+MIDIControllable::send_feedback ()
+{
+       byte msg[3];
+
+       if (setting || !_send_feedback || control_type == none) {
+               return;
+       }
+       
+       msg[0] = (control_type & 0xF0) | (control_channel & 0xF); 
+       msg[1] = control_additional;
+       msg[2] = (byte) (controllable.get_value() * 127.0f);
+
+       _port.write (msg, 3);
+}
+
+MIDI::byte*
+MIDIControllable::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool force)
+{
+       if (control_type != none &&_send_feedback && bufsize > 2) {
+
+               MIDI::byte gm = (MIDI::byte) (controllable.get_value() * 127.0);
+               
+               if (gm != last_written) {
+                       *buf++ = (0xF0 & control_type) | (0xF & control_channel);
+                       *buf++ = control_additional; /* controller number */
+                       *buf++ = gm;
+                       last_written = gm;
+                       bufsize -= 3;
+               }
+       }
+       
+       return buf;
+}
+
+int 
+MIDIControllable::set_state (const XMLNode& node)
+{
+       const XMLProperty* prop;
+       int xx;
+
+       if ((prop = node.property ("event")) != 0) {
+               sscanf (prop->value().c_str(), "0x%x", &xx);
+               control_type = (MIDI::eventType) xx;
+       } else {
+               return -1;
+       }
+
+       if ((prop = node.property ("channel")) != 0) {
+               sscanf (prop->value().c_str(), "%d", &xx);
+               control_channel = (MIDI::channel_t) xx;
+       } else {
+               return -1;
+       }
+
+       if ((prop = node.property ("additional")) != 0) {
+               sscanf (prop->value().c_str(), "0x%x", &xx);
+               control_additional = (MIDI::byte) xx;
+       } else {
+               return -1;
+       }
+
+       return 0;
+}
+
+XMLNode&
+MIDIControllable::get_state ()
+{
+       char buf[32];
+       XMLNode& node (controllable.get_state ());
+
+       snprintf (buf, sizeof(buf), "0x%x", (int) control_type);
+       node.add_property ("event", buf);
+       snprintf (buf, sizeof(buf), "%d", (int) control_channel);
+       node.add_property ("channel", buf);
+       snprintf (buf, sizeof(buf), "0x%x", (int) control_additional);
+       node.add_property ("additional", buf);
+
+       return node;
+}
+
diff --git a/libs/surfaces/generic_midi/midicontrollable.h b/libs/surfaces/generic_midi/midicontrollable.h
new file mode 100644 (file)
index 0000000..ab15f9f
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+    Copyright (C) 1998-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
+    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: controllable.h 4 2005-05-13 20:47:18Z taybin $
+*/
+
+#ifndef __gm_midicontrollable_h__
+#define __gm_midicontrollable_h__
+
+#include <string>
+
+#include <sigc++/sigc++.h>
+
+#include <midi++/types.h>
+#include <pbd/controllable.h>
+#include <pbd/stateful.h>
+#include <ardour/types.h>
+
+namespace MIDI {
+
+class Channel;
+class Port;
+class Parser;
+
+}
+
+class MIDIControllable : public Stateful
+{
+  public:
+       MIDIControllable (MIDI::Port&, PBD::Controllable&, bool bistate = false);
+       virtual ~MIDIControllable ();
+
+       void send_feedback ();
+       MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, bool force = false);
+       
+       void midi_rebind (MIDI::channel_t channel=-1);
+       void midi_forget ();
+       void learn_about_external_control ();
+       void stop_learning ();
+       void drop_external_control ();
+
+       bool get_midi_feedback () { return feedback; }
+       void set_midi_feedback (bool val) { feedback = val; }
+
+       MIDI::Port& get_port() const { return _port; }
+       PBD::Controllable& get_controllable() const { return controllable; }
+
+       std::string control_description() const { return _control_description; }
+
+       XMLNode& get_state (void);
+       int set_state (const XMLNode&);
+
+  private:
+       PBD::Controllable& controllable;
+       MIDI::Port&     _port;
+       bool             setting;
+       MIDI::byte       last_written;
+       bool             bistate;
+       int              midi_msg_id;      /* controller ID or note number */
+       sigc::connection midi_sense_connection[2];
+       sigc::connection midi_learn_connection;
+       size_t           connections;
+       MIDI::eventType  control_type;
+       MIDI::byte       control_additional;
+       MIDI::channel_t  control_channel;
+       std::string     _control_description;
+       bool             feedback;
+       
+       static bool _send_feedback;
+
+       void midi_receiver (MIDI::Parser &p, MIDI::byte *, size_t);
+       void midi_sense_note (MIDI::Parser &, MIDI::EventTwoBytes *, bool is_on);
+       void midi_sense_note_on (MIDI::Parser &p, MIDI::EventTwoBytes *tb);
+       void midi_sense_note_off (MIDI::Parser &p, MIDI::EventTwoBytes *tb);
+       void midi_sense_controller (MIDI::Parser &, MIDI::EventTwoBytes *);
+       void midi_sense_program_change (MIDI::Parser &, MIDI::byte);
+       void midi_sense_pitchbend (MIDI::Parser &, MIDI::pitchbend_t);
+
+       void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte);
+};
+
+#endif // __gm_midicontrollable_h__
+
index 8f3568aa8f05642419b385d8bb3bfcb9e1e9f64c..3f9cc5cc1542633542fb8d88f96881c68f08ff6d 100644 (file)
@@ -34,7 +34,7 @@ tranzport.Merge ([
     libraries['ardour'],
     libraries['ardour_cp'],
     libraries['sigc2'],
-    libraries['pbd3'],
+    libraries['pbd'],
     libraries['midi++2'],
     libraries['xml'],
     libraries['usb'],
index ee8fa95bc262d51f904a47d4d62435feb5719ebd..426c837b2ffc6e969f2ad490c7c6ef3b882af17f 100644 (file)
@@ -579,7 +579,7 @@ TranzportControlProtocol::monitor_work ()
        
        if ((err = pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam)) != 0) {
                // do we care? not particularly.
-               info << string_compose (_("%1: thread not running with realtime scheduling (%2)"), name(), strerror (errno)) << endmsg;
+               PBD::info << string_compose (_("%1: thread not running with realtime scheduling (%2)"), name(), strerror (errno)) << endmsg;
        } 
 
        pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, 0);
@@ -693,7 +693,7 @@ TranzportControlProtocol::update_state ()
        /* per track */
 
        if (route_table[0]) {
-               AudioTrack* at = dynamic_cast<AudioTrack*> (route_table[0]);
+               boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack> (route_table[0]);
                if (at && at->record_enabled()) {
                        pending_lights[LightTrackrec] = true;
                } else {
@@ -1574,3 +1574,15 @@ TranzportControlProtocol::print (int row, int col, const char *text)
        }
 }      
 
+XMLNode&
+TranzportControlProtocol::get_state () 
+{
+       XMLNode* node = new XMLNode (_name); /* node name must match protocol name */
+       return *node;
+}
+
+int
+TranzportControlProtocol::set_state (const XMLNode& node)
+{
+       return 0;
+}
index 546cc2f2af3189ff5bbc85b59ee9a94fc79bc201..e6e1a83e46720607bd509eb9e50203cb23182811 100644 (file)
@@ -23,6 +23,9 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol
 
        static bool probe ();
 
+       XMLNode& get_state ();
+       int set_state (const XMLNode&);
+
   private:
        static const int VENDORID = 0x165b;
        static const int PRODUCTID = 0x8101;
diff --git a/tools/.cvsignore b/tools/.cvsignore
deleted file mode 100644 (file)
index 4149faf..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-ard_i18n
-Makefile.in
-Makefile
index 78f6b92cd3078ba368e8003a2f595c50a4e5f511..917bbc50f36af7527bb91465a90821815ecefcc4 100755 (executable)
@@ -1,9 +1,9 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
-timestamp='2003-01-10'
+timestamp='2005-07-08'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -17,13 +17,15 @@ timestamp='2003-01-10'
 #
 # 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
 # configuration script generated by Autoconf, you may include it under
 # the same distribution terms that you use for the rest of that program.
 
+
 # Originally written by Per Bothner <per@bothner.com>.
 # Please send patches to <config-patches@gnu.org>.  Submit a context
 # diff and a properly formatted ChangeLog entry.
@@ -53,7 +55,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -66,11 +68,11 @@ Try \`$me --help' for more information."
 while test $# -gt 0 ; do
   case $1 in
     --time-stamp | --time* | -t )
-       echo "$timestamp" ; exit ;;
+       echo "$timestamp" ; exit ;;
     --version | -v )
-       echo "$version" ; exit ;;
+       echo "$version" ; exit ;;
     --help | --h* | -h )
-       echo "$usage"; exit ;;
+       echo "$usage"; exit ;;
     -- )     # Stop option processing
        shift; break ;;
     - )        # Use stdin as input.
@@ -106,6 +108,7 @@ trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
 : ${TMPDIR=/tmp} ;
  { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
  { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
  { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
 dummy=$tmp/dummy ;
 tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
@@ -122,7 +125,7 @@ case $CC_FOR_BUILD,$HOST_CC,$CC in
        ;;
  ,,*)   CC_FOR_BUILD=$CC ;;
  ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
-esac ;'
+esac ; set_cc_for_build= ;'
 
 # This is needed to find uname on a Pyramid OSx when run in the BSD universe.
 # (ghazi@noc.rutgers.edu 1994-08-24)
@@ -195,141 +198,109 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
        # contains redundant information, the shorter form:
        # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
        echo "${machine}-${os}${release}"
-       exit 0 ;;
-    amiga:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    arc:OpenBSD:*:*)
-       echo mipsel-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    hp300:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    mac68k:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    macppc:OpenBSD:*:*)
-       echo powerpc-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    mvme68k:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    mvme88k:OpenBSD:*:*)
-       echo m88k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    mvmeppc:OpenBSD:*:*)
-       echo powerpc-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    pmax:OpenBSD:*:*)
-       echo mipsel-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    sgi:OpenBSD:*:*)
-       echo mipseb-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    sun3:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    wgrisc:OpenBSD:*:*)
-       echo mipsel-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
+       exit ;;
     *:OpenBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    *:MicroBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-microbsd${UNAME_RELEASE}
-       exit 0 ;;
+       UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+       echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+       exit ;;
+    *:ekkoBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+       exit ;;
+    macppc:MirBSD:*:*)
+       echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    *:MirBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
     alpha:OSF1:*:*)
-       if test $UNAME_RELEASE = "V4.0"; then
+       case $UNAME_RELEASE in
+       *4.0)
                UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
-       fi
+               ;;
+       *5.*)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+               ;;
+       esac
+       # According to Compaq, /usr/sbin/psrinfo has been available on
+       # OSF/1 and Tru64 systems produced since 1995.  I hope that
+       # covers most systems running today.  This code pipes the CPU
+       # types through head -n 1, so we only detect the type of CPU 0.
+       ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+       case "$ALPHA_CPU_TYPE" in
+           "EV4 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "EV4.5 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "LCA4 (21066/21068)")
+               UNAME_MACHINE="alpha" ;;
+           "EV5 (21164)")
+               UNAME_MACHINE="alphaev5" ;;
+           "EV5.6 (21164A)")
+               UNAME_MACHINE="alphaev56" ;;
+           "EV5.6 (21164PC)")
+               UNAME_MACHINE="alphapca56" ;;
+           "EV5.7 (21164PC)")
+               UNAME_MACHINE="alphapca57" ;;
+           "EV6 (21264)")
+               UNAME_MACHINE="alphaev6" ;;
+           "EV6.7 (21264A)")
+               UNAME_MACHINE="alphaev67" ;;
+           "EV6.8CB (21264C)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8AL (21264B)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8CX (21264D)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.9A (21264/EV69A)")
+               UNAME_MACHINE="alphaev69" ;;
+           "EV7 (21364)")
+               UNAME_MACHINE="alphaev7" ;;
+           "EV7.9 (21364A)")
+               UNAME_MACHINE="alphaev79" ;;
+       esac
+       # A Pn.n version is a patched version.
        # A Vn.n version is a released version.
        # A Tn.n version is a released field test version.
        # A Xn.n version is an unreleased experimental baselevel.
        # 1.2 uses "1.2" for uname -r.
-       eval $set_cc_for_build
-       cat <<EOF >$dummy.s
-       .data
-\$Lformat:
-       .byte 37,100,45,37,120,10,0     # "%d-%x\n"
-
-       .text
-       .globl main
-       .align 4
-       .ent main
-main:
-       .frame \$30,16,\$26,0
-       ldgp \$29,0(\$27)
-       .prologue 1
-       .long 0x47e03d80 # implver \$0
-       lda \$2,-1
-       .long 0x47e20c21 # amask \$2,\$1
-       lda \$16,\$Lformat
-       mov \$0,\$17
-       not \$1,\$18
-       jsr \$26,printf
-       ldgp \$29,0(\$26)
-       mov 0,\$16
-       jsr \$26,exit
-       .end main
-EOF
-       $CC_FOR_BUILD -o $dummy $dummy.s 2>/dev/null
-       if test "$?" = 0 ; then
-               case `$dummy` in
-                       0-0)
-                               UNAME_MACHINE="alpha"
-                               ;;
-                       1-0)
-                               UNAME_MACHINE="alphaev5"
-                               ;;
-                       1-1)
-                               UNAME_MACHINE="alphaev56"
-                               ;;
-                       1-101)
-                               UNAME_MACHINE="alphapca56"
-                               ;;
-                       2-303)
-                               UNAME_MACHINE="alphaev6"
-                               ;;
-                       2-307)
-                               UNAME_MACHINE="alphaev67"
-                               ;;
-                       2-1307)
-                               UNAME_MACHINE="alphaev68"
-                               ;;
-                       3-1307)
-                               UNAME_MACHINE="alphaev7"
-                               ;;
-               esac
-       fi
-       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-       exit 0 ;;
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       exit ;;
     Alpha\ *:Windows_NT*:*)
        # How do we know it's Interix rather than the generic POSIX subsystem?
        # Should we change UNAME_MACHINE based on the output of uname instead
        # of the specific Alpha model?
        echo alpha-pc-interix
-       exit ;;
+       exit ;;
     21064:Windows_NT:50:3)
        echo alpha-dec-winnt3.5
-       exit ;;
+       exit ;;
     Amiga*:UNIX_System_V:4.0:*)
        echo m68k-unknown-sysv4
-       exit 0;;
+       exit ;;
     *:[Aa]miga[Oo][Ss]:*:*)
        echo ${UNAME_MACHINE}-unknown-amigaos
-       exit ;;
+       exit ;;
     *:[Mm]orph[Oo][Ss]:*:*)
        echo ${UNAME_MACHINE}-unknown-morphos
-       exit ;;
+       exit ;;
     *:OS/390:*:*)
        echo i370-ibm-openedition
-       exit 0 ;;
+       exit ;;
+    *:z/VM:*:*)
+       echo s390-ibm-zvmoe
+       exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+       exit ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
        echo arm-acorn-riscix${UNAME_RELEASE}
-       exit 0;;
+       exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+       echo arm-unknown-riscos
+       exit ;;
     SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
        echo hppa1.1-hitachi-hiuxmpp
-       exit 0;;
+       exit ;;
     Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
        # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
        if test "`(/bin/universe) 2>/dev/null`" = att ; then
@@ -337,29 +308,32 @@ EOF
        else
                echo pyramid-pyramid-bsd
        fi
-       exit ;;
+       exit ;;
     NILE*:*:*:dcosx)
        echo pyramid-pyramid-svr4
-       exit 0 ;;
-    DRS?6000:UNIX_SV:4.2*:7*)
+       exit ;;
+    DRS?6000:unix:4.0:6*)
+       echo sparc-icl-nx6
+       exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
        case `/usr/bin/uname -p` in
-           sparc) echo sparc-icl-nx7 && exit 0 ;;
+           sparc) echo sparc-icl-nx7; exit ;;
        esac ;;
     sun4H:SunOS:5.*:*)
        echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit ;;
+       exit ;;
     sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
        echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit ;;
+       exit ;;
     i86pc:SunOS:5.*:*)
        echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit ;;
+       exit ;;
     sun4*:SunOS:6*:*)
        # According to config.sub, this is the proper way to canonicalize
        # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
        # it's likely to be more like Solaris than SunOS4.
        echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit ;;
+       exit ;;
     sun4*:SunOS:*:*)
        case "`/usr/bin/arch -k`" in
            Series*|S4*)
@@ -368,10 +342,10 @@ EOF
        esac
        # Japanese Language versions have a version number like `4.1.3-JL'.
        echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
-       exit ;;
+       exit ;;
     sun3*:SunOS:*:*)
        echo m68k-sun-sunos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     sun*:*:4.2BSD:*)
        UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
        test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
@@ -383,10 +357,10 @@ EOF
                echo sparc-sun-sunos${UNAME_RELEASE}
                ;;
        esac
-       exit ;;
+       exit ;;
     aushp:SunOS:*:*)
        echo sparc-auspex-sunos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     # The situation for MiNT is a little confusing.  The machine name
     # can be virtually everything (everything which is not
     # "atarist" or "atariste" at least should have a processor
@@ -397,37 +371,40 @@ EOF
     # be no problem.
     atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
         echo m68k-atari-mint${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
        echo m68k-atari-mint${UNAME_RELEASE}
-        exit ;;
+        exit ;;
     *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
         echo m68k-atari-mint${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
         echo m68k-milan-mint${UNAME_RELEASE}
-        exit ;;
+        exit ;;
     hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
         echo m68k-hades-mint${UNAME_RELEASE}
-        exit ;;
+        exit ;;
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
         echo m68k-unknown-mint${UNAME_RELEASE}
-        exit 0 ;;
+        exit ;;
+    m68k:machten:*:*)
+       echo m68k-apple-machten${UNAME_RELEASE}
+       exit ;;
     powerpc:machten:*:*)
        echo powerpc-apple-machten${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     RISC*:Mach:*:*)
        echo mips-dec-mach_bsd4.3
-       exit ;;
+       exit ;;
     RISC*:ULTRIX:*:*)
        echo mips-dec-ultrix${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     VAX*:ULTRIX*:*:*)
        echo vax-dec-ultrix${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     2020:CLIX:*:* | 2430:CLIX:*:*)
        echo clipper-intergraph-clix${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     mips:*:*:UMIPS | mips:*:*:RISCos)
        eval $set_cc_for_build
        sed 's/^        //' << EOF >$dummy.c
@@ -451,32 +428,33 @@ EOF
          exit (-1);
        }
 EOF
-       $CC_FOR_BUILD -o $dummy $dummy.c \
-         && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
-         && exit 0
+       $CC_FOR_BUILD -o $dummy $dummy.c &&
+         dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+         SYSTEM_NAME=`$dummy $dummyarg` &&
+           { echo "$SYSTEM_NAME"; exit; }
        echo mips-mips-riscos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     Motorola:PowerMAX_OS:*:*)
        echo powerpc-motorola-powermax
-       exit ;;
+       exit ;;
     Motorola:*:4.3:PL8-*)
        echo powerpc-harris-powermax
-       exit ;;
+       exit ;;
     Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
        echo powerpc-harris-powermax
-       exit ;;
+       exit ;;
     Night_Hawk:Power_UNIX:*:*)
        echo powerpc-harris-powerunix
-       exit ;;
+       exit ;;
     m88k:CX/UX:7*:*)
        echo m88k-harris-cxux7
-       exit ;;
+       exit ;;
     m88k:*:4*:R4*)
        echo m88k-motorola-sysv4
-       exit ;;
+       exit ;;
     m88k:*:3*:R3*)
        echo m88k-motorola-sysv3
-       exit ;;
+       exit ;;
     AViiON:dgux:*:*)
         # DG/UX returns AViiON for all architectures
         UNAME_PROCESSOR=`/usr/bin/uname -p`
@@ -492,29 +470,29 @@ EOF
        else
            echo i586-dg-dgux${UNAME_RELEASE}
        fi
-       exit ;;
+       exit ;;
     M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
        echo m88k-dolphin-sysv3
-       exit ;;
+       exit ;;
     M88*:*:R3*:*)
        # Delta 88k system running SVR3
        echo m88k-motorola-sysv3
-       exit ;;
+       exit ;;
     XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
        echo m88k-tektronix-sysv3
-       exit ;;
+       exit ;;
     Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
        echo m68k-tektronix-bsd
-       exit ;;
+       exit ;;
     *:IRIX*:*:*)
        echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
-       exit ;;
+       exit ;;
     ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
-       echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
-       exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+       echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+       exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
     i*86:AIX:*:*)
        echo i386-ibm-aix
-       exit ;;
+       exit ;;
     ia64:AIX:*:*)
        if [ -x /usr/bin/oslevel ] ; then
                IBM_REV=`/usr/bin/oslevel`
@@ -522,7 +500,7 @@ EOF
                IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
        fi
        echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
-       exit ;;
+       exit ;;
     *:AIX:2:3)
        if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
                eval $set_cc_for_build
@@ -537,14 +515,18 @@ EOF
                        exit(0);
                        }
 EOF
-               $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
-               echo rs6000-ibm-aix3.2.5
+               if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+               then
+                       echo "$SYSTEM_NAME"
+               else
+                       echo rs6000-ibm-aix3.2.5
+               fi
        elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
                echo rs6000-ibm-aix3.2.4
        else
                echo rs6000-ibm-aix3.2
        fi
-       exit ;;
+       exit ;;
     *:AIX:*:[45])
        IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
        if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
@@ -558,28 +540,28 @@ EOF
                IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
        fi
        echo ${IBM_ARCH}-ibm-aix${IBM_REV}
-       exit ;;
+       exit ;;
     *:AIX:*:*)
        echo rs6000-ibm-aix
-       exit ;;
+       exit ;;
     ibmrt:4.4BSD:*|romp-ibm:BSD:*)
        echo romp-ibm-bsd4.4
-       exit ;;
+       exit ;;
     ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
        echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
-       exit 0 ;;                           # report: romp-ibm BSD 4.3
+       exit ;;                             # report: romp-ibm BSD 4.3
     *:BOSX:*:*)
        echo rs6000-bull-bosx
-       exit ;;
+       exit ;;
     DPX/2?00:B.O.S.:*:*)
        echo m68k-bull-sysv3
-       exit ;;
+       exit ;;
     9000/[34]??:4.3bsd:1.*:*)
        echo m68k-hp-bsd
-       exit ;;
+       exit ;;
     hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
        echo m68k-hp-bsd4.4
-       exit ;;
+       exit ;;
     9000/[34678]??:HP-UX:*:*)
        HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
        case "${UNAME_MACHINE}" in
@@ -641,9 +623,19 @@ EOF
        esac
        if [ ${HP_ARCH} = "hppa2.0w" ]
        then
-           # avoid double evaluation of $set_cc_for_build
-           test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
-           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+           eval $set_cc_for_build
+
+           # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+           # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+           # generating 64-bit code.  GNU and HP use different nomenclature:
+           #
+           # $ CC_FOR_BUILD=cc ./config.guess
+           # => hppa2.0w-hp-hpux11.23
+           # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+           # => hppa64-hp-hpux11.23
+
+           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+               grep __LP64__ >/dev/null
            then
                HP_ARCH="hppa2.0w"
            else
@@ -651,11 +643,11 @@ EOF
            fi
        fi
        echo ${HP_ARCH}-hp-hpux${HPUX_REV}
-       exit ;;
+       exit ;;
     ia64:HP-UX:*:*)
        HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
        echo ia64-hp-hpux${HPUX_REV}
-       exit ;;
+       exit ;;
     3050*:HI-UX:*:*)
        eval $set_cc_for_build
        sed 's/^        //' << EOF >$dummy.c
@@ -683,147 +675,166 @@ EOF
          exit (0);
        }
 EOF
-       $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+       $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+               { echo "$SYSTEM_NAME"; exit; }
        echo unknown-hitachi-hiuxwe2
-       exit ;;
+       exit ;;
     9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
        echo hppa1.1-hp-bsd
-       exit ;;
+       exit ;;
     9000/8??:4.3bsd:*:*)
        echo hppa1.0-hp-bsd
-       exit ;;
+       exit ;;
     *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
        echo hppa1.0-hp-mpeix
-       exit ;;
+       exit ;;
     hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
        echo hppa1.1-hp-osf
-       exit ;;
+       exit ;;
     hp8??:OSF1:*:*)
        echo hppa1.0-hp-osf
-       exit ;;
+       exit ;;
     i*86:OSF1:*:*)
        if [ -x /usr/sbin/sysversion ] ; then
            echo ${UNAME_MACHINE}-unknown-osf1mk
        else
            echo ${UNAME_MACHINE}-unknown-osf1
        fi
-       exit ;;
+       exit ;;
     parisc*:Lites*:*:*)
        echo hppa1.1-hp-lites
-       exit ;;
+       exit ;;
     C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
        echo c1-convex-bsd
-        exit ;;
+        exit ;;
     C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
        if getsysinfo -f scalar_acc
        then echo c32-convex-bsd
        else echo c2-convex-bsd
        fi
-        exit ;;
+        exit ;;
     C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
        echo c34-convex-bsd
-        exit ;;
+        exit ;;
     C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
        echo c38-convex-bsd
-        exit ;;
+        exit ;;
     C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
        echo c4-convex-bsd
-        exit ;;
+        exit ;;
     CRAY*Y-MP:*:*:*)
        echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-       exit ;;
+       exit ;;
     CRAY*[A-Z]90:*:*:*)
        echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
        | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
              -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
              -e 's/\.[^.]*$/.X/'
-       exit ;;
+       exit ;;
     CRAY*TS:*:*:*)
        echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-       exit ;;
+       exit ;;
     CRAY*T3E:*:*:*)
        echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-       exit ;;
+       exit ;;
     CRAY*SV1:*:*:*)
        echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-       exit ;;
+       exit ;;
     *:UNICOS/mp:*:*)
-       echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' 
-       exit ;;
+       echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
        FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
         FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
         FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
         echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-        exit 0 ;;
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+       exit ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
        echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     sparc*:BSD/OS:*:*)
        echo sparc-unknown-bsdi${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:BSD/OS:*:*)
        echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:FreeBSD:*:*)
-       # Determine whether the default compiler uses glibc.
-       eval $set_cc_for_build
-       sed 's/^        //' << EOF >$dummy.c
-       #include <features.h>
-       #if __GLIBC__ >= 2
-       LIBC=gnu
-       #else
-       LIBC=
-       #endif
-EOF
-       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
-       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
-       exit 0 ;;
+       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit ;;
     i*:CYGWIN*:*)
        echo ${UNAME_MACHINE}-pc-cygwin
-       exit ;;
+       exit ;;
     i*:MINGW*:*)
        echo ${UNAME_MACHINE}-pc-mingw32
-       exit 0 ;;
+       exit ;;
+    i*:windows32*:*)
+       # uname -m includes "-pc" on this system.
+       echo ${UNAME_MACHINE}-mingw32
+       exit ;;
     i*:PW*:*)
        echo ${UNAME_MACHINE}-pc-pw32
-       exit ;;
-    x86:Interix*:3*)
-       echo i586-pc-interix3
-       exit ;;
+       exit ;;
+    x86:Interix*:[34]*)
+       echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+       exit ;;
     [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
        echo i${UNAME_MACHINE}-pc-mks
-       exit ;;
+       exit ;;
     i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
        # How do we know it's Interix rather than the generic POSIX subsystem?
        # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
        # UNAME_MACHINE based on the output of uname instead of i386?
        echo i586-pc-interix
-       exit ;;
+       exit ;;
     i*:UWIN*:*)
        echo ${UNAME_MACHINE}-pc-uwin
-       exit 0 ;;
+       exit ;;
+    amd64:CYGWIN*:*:*)
+       echo x86_64-unknown-cygwin
+       exit ;;
     p*:CYGWIN*:*)
        echo powerpcle-unknown-cygwin
-       exit ;;
+       exit ;;
     prep*:SunOS:5.*:*)
        echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit ;;
+       exit ;;
     *:GNU:*:*)
+       # the GNU system
        echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
-       exit 0 ;;
+       exit ;;
+    *:GNU/*:*:*)
+       # other systems with GNU libc and userland
+       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+       exit ;;
     i*86:Minix:*:*)
        echo ${UNAME_MACHINE}-pc-minix
-       exit ;;
+       exit ;;
     arm*:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
-       exit 0 ;;
+       exit ;;
+    cris:Linux:*:*)
+       echo cris-axis-linux-gnu
+       exit ;;
+    crisv32:Linux:*:*)
+       echo crisv32-axis-linux-gnu
+       exit ;;
+    frv:Linux:*:*)
+       echo frv-unknown-linux-gnu
+       exit ;;
     ia64:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
-       exit 0 ;;
+       exit ;;
+    m32r*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
     m68*:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
-       exit ;;
+       exit ;;
     mips:Linux:*:*)
        eval $set_cc_for_build
        sed 's/^        //' << EOF >$dummy.c
@@ -841,7 +852,7 @@ EOF
        #endif
 EOF
        eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
-       test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
        ;;
     mips64:Linux:*:*)
        eval $set_cc_for_build
@@ -860,14 +871,14 @@ EOF
        #endif
 EOF
        eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
-       test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
        ;;
     ppc:Linux:*:*)
        echo powerpc-unknown-linux-gnu
-       exit ;;
+       exit ;;
     ppc64:Linux:*:*)
        echo powerpc64-unknown-linux-gnu
-       exit ;;
+       exit ;;
     alpha:Linux:*:*)
        case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
          EV5)   UNAME_MACHINE=alphaev5 ;;
@@ -881,7 +892,7 @@ EOF
        objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
        if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
        echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
-       exit ;;
+       exit ;;
     parisc:Linux:*:* | hppa:Linux:*:*)
        # Look for CPU level
        case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
@@ -889,22 +900,25 @@ EOF
          PA8*) echo hppa2.0-unknown-linux-gnu ;;
          *)    echo hppa-unknown-linux-gnu ;;
        esac
-       exit ;;
+       exit ;;
     parisc64:Linux:*:* | hppa64:Linux:*:*)
        echo hppa64-unknown-linux-gnu
-       exit ;;
+       exit ;;
     s390:Linux:*:* | s390x:Linux:*:*)
        echo ${UNAME_MACHINE}-ibm-linux
-       exit 0 ;;
+       exit ;;
+    sh64*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
     sh*:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
-       exit ;;
+       exit ;;
     sparc:Linux:*:* | sparc64:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
-       exit ;;
+       exit ;;
     x86_64:Linux:*:*)
        echo x86_64-unknown-linux-gnu
-       exit ;;
+       exit ;;
     i*86:Linux:*:*)
        # The BFD linker knows what the default object file format is, so
        # first see if it will tell us. cd to the root directory to prevent
@@ -922,15 +936,15 @@ EOF
                ;;
          a.out-i386-linux)
                echo "${UNAME_MACHINE}-pc-linux-gnuaout"
-               exit ;;
+               exit ;;
          coff-i386)
                echo "${UNAME_MACHINE}-pc-linux-gnucoff"
-               exit ;;
+               exit ;;
          "")
                # Either a pre-BFD a.out linker (linux-gnuoldld) or
                # one that does not give us useful --help.
                echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
-               exit ;;
+               exit ;;
        esac
        # Determine whether the default compiler is a.out or elf
        eval $set_cc_for_build
@@ -953,17 +967,23 @@ EOF
        LIBC=gnuaout
        #endif
        #endif
+       #ifdef __dietlibc__
+       LIBC=dietlibc
+       #endif
 EOF
        eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
-       test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
-       test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+       test x"${LIBC}" != x && {
+               echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+               exit
+       }
+       test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
        ;;
     i*86:DYNIX/ptx:4*:*)
        # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
        # earlier versions are messed up and put the nodename in both
        # sysname and nodename.
        echo i386-sequent-sysv4
-       exit ;;
+       exit ;;
     i*86:UNIX_SV:4.2MP:2.*)
         # Unixware is an offshoot of SVR4, but it has its own version
         # number series starting with 2...
@@ -971,24 +991,27 @@ EOF
        # I just have to hope.  -- rms.
         # Use sysv4.2uw... so that sysv4* matches it.
        echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
-       exit ;;
+       exit ;;
     i*86:OS/2:*:*)
        # If we were able to find `uname', then EMX Unix compatibility
        # is probably installed.
        echo ${UNAME_MACHINE}-pc-os2-emx
-       exit ;;
+       exit ;;
     i*86:XTS-300:*:STOP)
        echo ${UNAME_MACHINE}-unknown-stop
-       exit ;;
+       exit ;;
     i*86:atheos:*:*)
        echo ${UNAME_MACHINE}-unknown-atheos
-       exit 0 ;;
+       exit ;;
+    i*86:syllable:*:*)
+       echo ${UNAME_MACHINE}-pc-syllable
+       exit ;;
     i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
        echo i386-unknown-lynxos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     i*86:*DOS:*:*)
        echo ${UNAME_MACHINE}-pc-msdosdjgpp
-       exit ;;
+       exit ;;
     i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
        UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
        if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
@@ -996,15 +1019,16 @@ EOF
        else
                echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
        fi
-       exit 0 ;;
-    i*86:*:5:[78]*)
+       exit ;;
+    i*86:*:5:[678]*)
+       # UnixWare 7.x, OpenUNIX and OpenServer 6.
        case `/bin/uname -X | grep "^Machine"` in
            *486*)           UNAME_MACHINE=i486 ;;
            *Pentium)        UNAME_MACHINE=i586 ;;
            *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
        esac
        echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
-       exit ;;
+       exit ;;
     i*86:*:3.2:*)
        if test -f /usr/options/cb.name; then
                UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
@@ -1022,73 +1046,73 @@ EOF
        else
                echo ${UNAME_MACHINE}-pc-sysv32
        fi
-       exit ;;
+       exit ;;
     pc:*:*:*)
        # Left here for compatibility:
         # uname -m prints for DJGPP always 'pc', but it prints nothing about
         # the processor, so we play safe by assuming i386.
        echo i386-pc-msdosdjgpp
-        exit ;;
+        exit ;;
     Intel:Mach:3*:*)
        echo i386-pc-mach3
-       exit ;;
+       exit ;;
     paragon:*:*:*)
        echo i860-intel-osf1
-       exit ;;
+       exit ;;
     i860:*:4.*:*) # i860-SVR4
        if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
          echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
        else # Add other i860-SVR4 vendors below as they are discovered.
          echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
        fi
-       exit ;;
+       exit ;;
     mini*:CTIX:SYS*5:*)
        # "miniframe"
        echo m68010-convergent-sysv
-       exit ;;
+       exit ;;
     mc68k:UNIX:SYSTEM5:3.51m)
        echo m68k-convergent-sysv
-       exit ;;
+       exit ;;
     M680?0:D-NIX:5.3:*)
        echo m68k-diab-dnix
-       exit ;;
-    M68*:*:R3V[567]*:*)
-       test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
-    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0)
+       exit ;;
+    M68*:*:R3V[5678]*:*)
+       test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
        OS_REL=''
        test -r /etc/.relid \
        && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-         && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+         && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
        /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-         && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+         && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
     3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
         /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-          && echo i486-ncr-sysv4 && exit 0 ;;
+          && { echo i486-ncr-sysv4; exit; } ;;
     m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
        echo m68k-unknown-lynxos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     mc68030:UNIX_System_V:4.*:*)
        echo m68k-atari-sysv4
-       exit ;;
+       exit ;;
     TSUNAMI:LynxOS:2.*:*)
        echo sparc-unknown-lynxos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     rs6000:LynxOS:2.*:*)
        echo rs6000-unknown-lynxos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
        echo powerpc-unknown-lynxos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     SM[BE]S:UNIX_SV:*:*)
        echo mips-dde-sysv${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     RM*:ReliantUNIX-*:*:*)
        echo mips-sni-sysv4
-       exit ;;
+       exit ;;
     RM*:SINIX-*:*:*)
        echo mips-sni-sysv4
-       exit ;;
+       exit ;;
     *:SINIX-*:*:*)
        if uname -p 2>/dev/null >/dev/null ; then
                UNAME_MACHINE=`(uname -p) 2>/dev/null`
@@ -1096,68 +1120,73 @@ EOF
        else
                echo ns32k-sni-sysv
        fi
-       exit ;;
+       exit ;;
     PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
                       # says <Richard.M.Bartel@ccMail.Census.GOV>
         echo i586-unisys-sysv4
-        exit ;;
+        exit ;;
     *:UNIX_System_V:4*:FTX*)
        # From Gerald Hewes <hewes@openmarket.com>.
        # How about differentiating between stratus architectures? -djm
        echo hppa1.1-stratus-sysv4
-       exit ;;
+       exit ;;
     *:*:*:FTX*)
        # From seanf@swdc.stratus.com.
        echo i860-stratus-sysv4
-       exit 0 ;;
+       exit ;;
+    i*86:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo ${UNAME_MACHINE}-stratus-vos
+       exit ;;
     *:VOS:*:*)
        # From Paul.Green@stratus.com.
        echo hppa1.1-stratus-vos
-       exit ;;
+       exit ;;
     mc68*:A/UX:*:*)
        echo m68k-apple-aux${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     news*:NEWS-OS:6*:*)
        echo mips-sony-newsos6
-       exit ;;
+       exit ;;
     R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
        if [ -d /usr/nec ]; then
                echo mips-nec-sysv${UNAME_RELEASE}
        else
                echo mips-unknown-sysv${UNAME_RELEASE}
        fi
-        exit ;;
+        exit ;;
     BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
        echo powerpc-be-beos
-       exit ;;
+       exit ;;
     BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
        echo powerpc-apple-beos
-       exit ;;
+       exit ;;
     BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
        echo i586-pc-beos
-       exit ;;
+       exit ;;
     SX-4:SUPER-UX:*:*)
        echo sx4-nec-superux${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     SX-5:SUPER-UX:*:*)
        echo sx5-nec-superux${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     SX-6:SUPER-UX:*:*)
        echo sx6-nec-superux${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     Power*:Rhapsody:*:*)
        echo powerpc-apple-rhapsody${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:Rhapsody:*:*)
        echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:Darwin:*:*)
-       case `uname -p` in
+       UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+       case $UNAME_PROCESSOR in
            *86) UNAME_PROCESSOR=i686 ;;
-           powerpc) UNAME_PROCESSOR=powerpc ;;
+           unknown) UNAME_PROCESSOR=powerpc ;;
        esac
        echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:procnto*:*:* | *:QNX:[0123456789]*:*)
        UNAME_PROCESSOR=`uname -p`
        if test "$UNAME_PROCESSOR" = "x86"; then
@@ -1165,22 +1194,25 @@ EOF
                UNAME_MACHINE=pc
        fi
        echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:QNX:*:4*)
        echo i386-pc-qnx
-       exit 0 ;;
-    NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
+       exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+       echo nse-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
        echo nsr-tandem-nsk${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:NonStop-UX:*:*)
        echo mips-compaq-nonstopux
-       exit ;;
+       exit ;;
     BS2000:POSIX*:*:*)
        echo bs2000-siemens-sysv
-       exit ;;
+       exit ;;
     DS/*:UNIX_System_V:*:*)
        echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:Plan9:*:*)
        # "uname -m" is not consistent, so use $cputype instead. 386
        # is converted to i386 for consistency with other x86
@@ -1191,25 +1223,44 @@ EOF
            UNAME_MACHINE="$cputype"
        fi
        echo ${UNAME_MACHINE}-unknown-plan9
-       exit ;;
+       exit ;;
     *:TOPS-10:*:*)
        echo pdp10-unknown-tops10
-       exit ;;
+       exit ;;
     *:TENEX:*:*)
        echo pdp10-unknown-tenex
-       exit ;;
+       exit ;;
     KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
        echo pdp10-dec-tops20
-       exit ;;
+       exit ;;
     XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
        echo pdp10-xkl-tops20
-       exit ;;
+       exit ;;
     *:TOPS-20:*:*)
        echo pdp10-unknown-tops20
-       exit ;;
+       exit ;;
     *:ITS:*:*)
        echo pdp10-unknown-its
-       exit 0 ;;
+       exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+       exit ;;
+    *:DragonFly:*:*)
+       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit ;;
+    *:*VMS:*:*)
+       UNAME_MACHINE=`(uname -p) 2>/dev/null`
+       case "${UNAME_MACHINE}" in
+           A*) echo alpha-dec-vms ; exit ;;
+           I*) echo ia64-dec-vms ; exit ;;
+           V*) echo vax-dec-vms ; exit ;;
+       esac ;;
+    *:XENIX:*:SysV)
+       echo i386-pc-xenix
+       exit ;;
+    i*86:skyos:*:*)
+       echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+       exit ;;
 esac
 
 #echo '(No uname command or uname output not recognized.)' 1>&2
@@ -1241,7 +1292,7 @@ main ()
 #endif
 
 #if defined (__arm) && defined (__acorn) && defined (__unix)
-  printf ("arm-acorn-riscix"); exit (0);
+  printf ("arm-acorn-riscix\n"); exit (0);
 #endif
 
 #if defined (hp300) && !defined (hpux)
@@ -1330,11 +1381,12 @@ main ()
 }
 EOF
 
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+       { echo "$SYSTEM_NAME"; exit; }
 
 # Apollos put the system type in the environment.
 
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
 
 # Convex versions that predate uname can use getsysinfo(1)
 
@@ -1343,22 +1395,22 @@ then
     case `getsysinfo -f cpu_type` in
     c1*)
        echo c1-convex-bsd
-       exit ;;
+       exit ;;
     c2*)
        if getsysinfo -f scalar_acc
        then echo c32-convex-bsd
        else echo c2-convex-bsd
        fi
-       exit ;;
+       exit ;;
     c34*)
        echo c34-convex-bsd
-       exit ;;
+       exit ;;
     c38*)
        echo c38-convex-bsd
-       exit ;;
+       exit ;;
     c4*)
        echo c4-convex-bsd
-       exit ;;
+       exit ;;
     esac
 fi
 
@@ -1369,7 +1421,9 @@ This script, last modified $timestamp, has failed to recognize
 the operating system you are using. It is advised that you
 download the most up to date version of the config scripts from
 
-    ftp://ftp.gnu.org/pub/gnu/config/
+  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
 
 If the version you run ($0) is already up to date, please
 send the following data and any information you think might be
diff --git a/tools/osx_packaging/ardour2_mac_ui.rc b/tools/osx_packaging/ardour2_mac_ui.rc
new file mode 100644 (file)
index 0000000..fb739a9
--- /dev/null
@@ -0,0 +1,1225 @@
+#
+# This is the GTK style file for Ardour
+#
+#
+
+style "very_small_text"
+{
+       font_name = "sans 9"
+}
+
+style "small_text"
+{
+       font_name = "sans 10"
+}
+
+style "small_bold_text"
+{
+       font_name = "sans bold 10"
+}
+
+style "medium_bold_text"
+{
+       font_name = "sans bold 11"
+}
+
+style "medium_text"
+{
+       font_name = "sans 11"
+}
+
+style "red_medium_text" = "medium_text"
+{      
+       fg[NORMAL] = { 1.0, 0, 0 }
+       fg[ACTIVE] = { 1.0, 0, 0 }
+       fg[SELECTED] = { 1.0, 0, 0 }
+}
+
+
+style "large_text"
+{
+       font_name = "sans 18"
+}
+
+style "larger_bold_text"
+{
+       font_name = "sans bold 14"
+}
+
+style "plugin_name_text"
+{
+       font_name = "sans bold 25"
+       fg[NORMAL] = { 0.80, 0.80, 0.80 }
+}
+
+style "plugin_maker_text"
+{
+       font_name = "sans bold 14"
+       fg[NORMAL] = { 0.80, 0.80, 0.80 }
+}
+
+style "first_action_message" 
+{
+       font_name = "sans medium 34"
+}
+
+style "verbose_canvas_cursor"
+{
+       font_name = "sans bold 24"
+}
+
+style "marker_text" 
+{
+       font_name = "sans 9"
+}
+
+style "time_axis_view_item_name"
+{
+       font_name = "sans medium 10"
+}
+
+style "default_base" = "medium_text"
+{
+  GtkWidget::cursor_color =  {1.0, 1.0, 1.0 }
+  GtkButton::default_border = { 0, 0, 0, 0 }
+  GtkButton::default_outside_border = { 0, 0, 0, 0 }
+  GtkTreeView::vertical-padding = 0
+  GtkTreeView::horizontal-padding = 0
+  
+  fg[NORMAL] = { 0.80, 0.80, 0.80 }    
+  fg[ACTIVE] = { 0.80, 0.80, 0.80 }    
+  fg[PRELIGHT] = { 1.0, 1.0, 1.0 }
+  fg[INSENSITIVE] = { 0.80, 0.80, 0.80 }       
+  fg[SELECTED] = { 0.80, 0.80, 0.80 }  
+  
+  bg[NORMAL] = { 0.40, 0.40, 0.40 }
+  bg[ACTIVE] = { 0.40, 0.40, 0.40 }
+  bg[PRELIGHT] = "#565690"
+  bg[INSENSITIVE] = { 0.10, 0.10, 0.10 }
+  bg[SELECTED] = { 0, 0.40, 0.60 }
+  
+  text[NORMAL] = { 0.80, 0.80, 0.80 }  
+  text[ACTIVE] = { 0.80, 0.80, 0.80 }  
+  text[PRELIGHT] = { 0.80, 0.80, 0.80 }        
+  text[INSENSITIVE] = { 0.80, 0.80, 0.80}      
+  text[SELECTED] = { 1.0, 1.0, 1.0 }
+  
+  base[ACTIVE]     = "#2f272f"
+  base[NORMAL]      =  "#1c1e21"
+  base[PRELIGHT]     = { 0.20, 0.20, 0.20 }
+  base[INSENSITIVE]  = "#4c5159"
+  base[SELECTED]     = { 0.25, 0.25, 0.25 }
+  
+  engine "clearlooks"  {
+    menubarstyle      = 2       # 0 = flat, 1 = sunken, 2 = flat gradient
+    menuitemstyle     = 1       # 0 = flat, 1 = 3d-ish (gradient), 2 = 3d-ish (button)
+    listviewitemstyle = 1       # 0 = flat, 1 = 3d-ish (gradient)
+    progressbarstyle  = 0       # 0 = candy bar, 1 = flat
+  }
+}
+
+style "base_frame"
+{
+       fg[NORMAL] = { 0.80, 0.80, 0.80 }
+       bg[NORMAL] = { 0.40, 0.40, 0.40 }
+}
+
+style "transport_base" = "medium_bold_text"
+{
+  bg[NORMAL] = { 0.10, 0.10, 0.10 }
+  bg[ACTIVE] = { 0, 0, 0 }
+  bg[PRELIGHT] = { 0, 0, 0 }
+  bg[INSENSITIVE] = { 0, 0, 0 }
+  bg[SELECTED] = { 0, 0, 0 }
+}
+
+style "black_mackie_menu_bar" = "medium_bold_text"
+{
+      font_name = "sans bold 12"
+      fg[NORMAL] = { 1.0, 1.0, 1.0 }
+      bg[NORMAL] = { 0, 0, 0 }
+}
+
+style "default_buttons_menus" 
+{
+  font_name = "sans 11"
+  fg[ACTIVE] = { 1.0, 1.0, 1.0 }
+  
+  bg[NORMAL] = { 0.35, 0.35, 0.35 }
+  bg[ACTIVE] = "#565690"
+  bg[PRELIGHT] = { 0.20, 0.20, 0.20 }
+  bg[INSENSITIVE] = { 0.20, 0.20, 0.20 }
+  bg[SELECTED] = { 0.20, 0.20, 0.20 }  
+}
+
+style "very_small_button" = "default_buttons_menus"
+{
+       font_name = "sans 8"
+       ythickness = 0
+       xthickness = 0
+}
+
+style "small_button" = "default_buttons_menus"
+{
+}
+
+style "very_small_red_active_and_selected_button" = "very_small_button"
+{
+       bg[ACTIVE] = { 1.0, 0, 0}
+       bg[SELECTED] = { 1.0, 0, 0}
+}
+
+style "small_red_active_and_selected_button" = "small_button"
+{
+       fg[ACTIVE] = { 0, 0, 0 }
+       bg[ACTIVE] = { 1.0, 0, 0}
+       bg[SELECTED] = { 1.0, 0, 0}
+}
+
+style "track_rec_enable_button" = "small_button"
+{
+       fg[SELECTED] = { 0.0, 0.0, 0.0 }
+       fg[ACTIVE] =   { 0.0, 0.0, 0.0 }
+       fg[PRELIGHT] = { 0.0, 0.0, 0.0 }
+
+       bg[SELECTED] =   { 1.0, 0.0, 0.0 }
+       bg[ACTIVE] =   { 0.91, 0.68, 0.68}
+       bg[PRELIGHT] =   { 1.0, 0.0, 0.0 }
+}
+
+style "mixer_rec_enable_button" = "track_rec_enable_button"
+{
+       font_name = "sans 8"
+       xthickness = 0
+       ythickness = 0
+}
+
+style "solo_button" = "small_button"
+{
+       bg[PRELIGHT] = { 0, 1.0, 0 }
+       bg[ACTIVE] = { 0.66, 0.97, 0.19 }
+
+       fg[PRELIGHT] = { 0, 0, 0 }
+       fg[ACTIVE] = { 0, 0, 0 }
+}
+
+style "mixer_solo_button" = "solo_button"
+{
+       font_name = "sans 8"
+       xthickness = 0
+       ythickness = 0
+
+}
+
+
+style "mute_button" = "small_button"
+{
+       bg[PRELIGHT] = { 1.0, 0.65, 0.13 }
+       bg[ACTIVE] = { 1.0, 0.98, 0.53 }
+       
+       fg[PRELIGHT] = { 0, 0, 0 }
+}
+
+style "mixer_mute_button" = "mute_button"
+{
+       font_name = "sans 8"
+       xthickness = 0
+       ythickness = 0
+}
+
+style "track_loop_button" = "small_button"
+{
+       bg[ACTIVE] = { 1.0, 0.98, 0.53 }
+       bg[PRELIGHT] = { 1.0, 0.98, 0.53 }
+
+}
+
+style "mixer_red_active_button" = "very_small_button"
+{
+       fg[ACTIVE] = { 0, 1.0, 1.0 }
+       bg[ACTIVE] = { 0.7, 0, 0 }
+
+       base[INSENSITIVE] = { 0.21, 0.21, 0.21 }
+       bg[INSENSITIVE] = { 0.21, 0.21, 0.21 }
+}
+
+style "time_button" = "default_buttons_menus"
+{
+       font_name = "sans 10"
+}
+
+style "default_menus" = "default_buttons_menus"
+{
+       font_name = "sans 11"
+}
+
+style "transport_button"
+{
+       font_name = "sans 9"
+       bg[ACTIVE] = { 0.50, 1.0, 0.50 }
+       fg[ACTIVE] = { 0, 0, 0 }
+}
+
+style "transport_rec_button"
+{
+       bg[ACTIVE] = { 1.0, 0, 0 }
+       bg[PRELIGHT] = { 0.91, 0.68, 0.68 }             #blinking rec button color
+}
+
+style "shuttle_control" = "very_small_text"
+{
+       fg[NORMAL] = { 0.85, 0.92, 0.98 }
+       fg[ACTIVE] = { 0.85, 0.92, 0.98 }
+       fg[PRELIGHT] = { 0.85, 0.92, 0.98 }
+       fg[SELECTED] = { 0.85, 0.92, 0.98 }
+       fg[INSENSITIVE] = { 0.85, 0.92, 0.98 }
+
+       bg[NORMAL] = { 0.31, 0.31, 0.31 }
+       bg[PRELIGHT] = { 0.31, 0.31, 0.31 }
+       bg[INSENSITIVE] = { 0.31, 0.31, 0.31 }
+       bg[ACTIVE] = { 0.50, 1.0, 0.50 }
+       bg[SELECTED] = { 1.0, 0.04, 0.04 }
+}
+
+style "ardour_adjusters" = "default_buttons_menus"
+{
+       bg[NORMAL] = { 0.60, 0.60, 0.60 }
+       bg[PRELIGHT] = { 0.80, 0.80, 0.80 }
+       bg[ACTIVE] = { 0.06, 0.06, 0.06 }
+}
+
+style "ardour_progressbars" = "default_buttons_menus"
+{ 
+  bg[NORMAL] = { 0, 0, 0 }
+  bg[PRELIGHT] = { 0.00, 0.36, 0.40 }
+}
+
+style "options_window"  = "default_base"
+{
+       font_name = "sans 11"
+       fg[PRELIGHT] = { 0.80, 0.80, 0.80 }
+}
+
+style "option_entry"  = "default_base"
+{
+       fg[NORMAL] = { 0.50, 1.0, 1.0 }
+       fg[ACTIVE] = { 0.50, 1.0, 1.0 }
+       fg[INSENSITIVE] = { 0.80, 0.80, 0.80 }
+       
+       base[INSENSITIVE] = { 0.12, 0.12, 0.12 }
+       
+       bg[NORMAL] = { 0.40, 0.40, 0.40 }
+       bg[ACTIVE] = { 0.40, 0.40, 0.40 }
+}
+
+style "red_when_active" = "medium_text"
+{
+       fg[NORMAL] = { 0.80, 0.80, 0.80 }
+       bg[NORMAL] = { 0.31, 0.31, 0.31 }
+
+       fg[ACTIVE] = { 0.80, 0.80, 0.80 }
+       bg[ACTIVE] = { 1.0, 0, 0}
+}
+
+style "xrun_warn"  
+{
+       font_name = "sans bold 18"
+
+       fg[NORMAL] = { 1.0, 1.0, 1.0 }
+       fg[ACTIVE] = { 1.0, 1.0, 1.0 }
+       text[NORMAL] = { 1.0, 1.0, 1.0 }
+       text[ACTIVE] = { 1.0, 1.0, 1.0 }
+       base[NORMAL] = { 0.09, 0.48, 0.46 }
+       base[ACTIVE] = { 0.09, 0.48, 0.46 }
+       bg[NORMAL] = { 1.0, 0.48, 0.46 }
+       bg[ACTIVE] = { 0.09, 1.0, 0.46 }
+}
+
+style "menu_bar_base"
+{
+  bg[NORMAL] = { 0, 0, 0 }     
+  bg[ACTIVE] = { 0, 0, 0 }
+  bg[PRELIGHT] = { 0, 0, 0 }
+  bg[INSENSITIVE] = { 0, 0, 0 }
+  bg[SELECTED] = { 0, 0, 0 }
+}
+
+style "fatal_message" = "medium_text"
+{
+   fg[ACTIVE] = { 1.0, 0, 1.0 }
+   fg[NORMAL] = { 0.80, 0.80, 0.80 }
+   bg[ACTIVE] = { 0,0,0 }
+   bg[NORMAL] = { 0,0,0 }
+   base[ACTIVE] = { 0,0,0 }
+   base[NORMAL] = { 0,0,0 }
+}
+
+style "error_message" = "medium_text"
+{
+   fg[ACTIVE] = { 1.0, 0, 0 }
+   fg[NORMAL] = { 0.80, 0.80, 0.80 }
+   bg[ACTIVE] = { 0,0,0 }
+   bg[NORMAL] = { 0,0,0 }
+   base[ACTIVE] = { 0,0,0 }
+   base[NORMAL] = { 0,0,0 }
+}
+
+style "info_message" = "medium_text"
+{
+   fg[ACTIVE] = { 1.0, 0, 0 }
+   fg[NORMAL] = { 0.80, 0.80, 0.80 }
+   bg[ACTIVE] = { 0,0,0 }
+   bg[NORMAL] = { 0,0,0 }
+   base[ACTIVE] = { 0,0,0 }
+   base[NORMAL] = { 0,0,0 }
+}
+
+style "warning_message" = "medium_text"
+{
+   fg[ACTIVE] = { 0.30,0.30, 1.0 }
+   fg[NORMAL] = { 0.80, 0.80, 0.80 }
+   bg[ACTIVE] = { 0, 0, 0 }
+   bg[NORMAL] = { 0, 0, 0 }
+   base[ACTIVE] = { 0, 0, 0 }
+   base[NORMAL] = { 0, 0, 0 }
+}
+
+style "medium_entry" = "medium_text"
+{
+       fg[NORMAL] = { 0.50, 1.0, 1.0 }
+       fg[ACTIVE] = { 0.50, 1.0, 1.0 }
+       fg[SELECTED] = { 0.50, 1.0, 0.50 }
+       
+       bg[NORMAL] = { 0.40, 0.40, 0.40 }
+       
+       base[NORMAL] = { 0, 0, 0 }
+       base[ACTIVE] = { 0, 0, 0 }
+       base[SELECTED] = { 0.5, 0.5, 1.0 }
+}
+
+style "medium_entry_noselection_fg" = "medium_entry"
+{
+       fg[SELECTED] = { 0.50, 1.0, 0.50 }
+}
+
+style "medium_entry_noselection_bg" = "medium_entry"
+{
+       bg[SELECTED] = { 0.50, 1.0, 1.0 }
+}
+
+style "medium_bold_entry"  = "medium_bold_text"
+{
+       fg[NORMAL] = { 0.50, 1.0, 1.0 }
+       fg[ACTIVE] = { 0.50, 1.0, 1.0 }
+       
+       bg[NORMAL] = { 0.40, 0.40, 0.40 }
+       
+       base[NORMAL] = { 0, 0, 0 }
+       base[ACTIVE] = { 0, 0, 0 }
+       base[SELECTED] = { 0, 0, 0 }
+}
+
+
+style "small_entry" = "small_text"
+{
+       fg[NORMAL] = { 0.50, 1.0, 1.0 }
+       fg[ACTIVE] = { 0.50, 1.0, 1.0 }
+       bg[NORMAL] = { 0.0, 0.0, 0.0 }
+       base[NORMAL] = { 0, 0, 0 }
+       base[ACTIVE] = { 0, 0, 0 }
+       base[SELECTED] = { 0, 0, 0 }
+}
+
+style "red_active_small_entry" = "small_entry"
+{
+       fg[ACTIVE] = { 1.0, 0.0, 0.0 }
+       fg[SELECTED] = { 1.0, 0, 0 }
+}
+
+style "small_bold_entry" = "small_bold_text"
+{
+       fg[NORMAL] = { 0.50, 1.0, 1.0 }
+       fg[ACTIVE] = { 0.50, 1.0, 1.0 }
+       
+       bg[NORMAL] = { 0.40, 0.40, 0.40 }
+       
+       base[NORMAL] = { 0, 0, 0 }
+       base[ACTIVE] = { 0, 0, 0 }
+       base[SELECTED] = { 0, 0, 0 }
+}
+
+style "small_red_on_black_entry"  = "small_bold_text"
+{
+       fg[NORMAL] = { 1.0, 0, 0 }
+       fg[ACTIVE] = { 1.0, 0, 0 }
+       base[NORMAL] = { 0.0, 0.0, 0.0 }
+       base[ACTIVE] = { 0.0, 0.0, 0.0 }
+       bg[NORMAL] = { 0.0, 0.0, 0.0 }
+       bg[ACTIVE] = { 0.0, 0.0, 0.0 }
+}
+
+style "big_clock_display" = "medium_entry"
+{
+       font_name = "courier bold 34"
+}
+
+style "transport_clock_display"
+{
+       font_name = "sans bold 14"
+       
+       fg[NORMAL] = { 0.50, 1.0, 0.50 }
+       fg[ACTIVE] = { 1.0, 0, 0.0 }
+       fg[SELECTED] = { 1.0, 0, 0 }
+       fg[PRELIGHT] = { 1.0, 0, 0.0 }
+       fg[INSENSITIVE] = { 1.0, 0, 0.0 }
+       
+       base[NORMAL] = { 0.0, 0.0, 0.0 }
+       base[ACTIVE] = { 0.0, 0.0, 0.0 }
+       bg[NORMAL] = { 0.0, 0.0, 0.0 }
+       bg[ACTIVE] = { 0.0, 0.0, 0.0 }
+}
+
+style "tempo_meter_clock_display"
+{
+       font_name = "sans 9"
+       fg[NORMAL] = { 1.0, 1.0, 1.0 }
+       fg[ACTIVE] = { 1.0, 1.0, 0.0 }
+       fg[SELECTED] = { 1.0, 0, 0 }
+       base[NORMAL] = { 0.0, 0.48, 1.0 }
+       base[ACTIVE] = { 0.09, 0.98, 0.46 }
+       bg[NORMAL] = { 0.0, 0.48, 1.0 }
+       bg[ACTIVE] = { 0.09, 0.98, 0.46 }
+}
+
+style "default_clock_display" = "medium text"
+{
+       font_name = "sans 10"
+       fg[NORMAL] = { 0.50, 1.0, 0.50 }
+       fg[ACTIVE] = { 1.0, 0.0, 0.0 }
+       fg[SELECTED] = { 1.0, 0, 0 }
+       base[NORMAL] = { 0, 0, 0 }
+       base[ACTIVE] = { 0, 0, 0 }
+       bg[NORMAL] = { 0, 0, 0 }
+       bg[ACTIVE] = { 0, 0, 0 }
+}
+
+style "editor_time_ruler" = "small_text"
+{
+       fg[NORMAL] = { 0.80, 0.80, 0.80 }
+       bg[NORMAL] = { 0.09, 0.09, 0.09 }
+}
+
+style "audio_track_base" = "default_base"
+{
+  font_name = "sans 8"
+  fg[NORMAL] = { 0.77, 0.77, 0.72 }    
+  bg[NORMAL] = { 0.18, 0.18, 0.22 }
+  bg[ACTIVE] = { 0.20, 0.20, 0.20 }    
+  bg[PRELIGHT] = { 0.20, 0.20, 0.20 }
+  bg[INSENSITIVE] = { 0.20, 0.20, 0.20 }
+  bg[SELECTED] = { 0.20, 0.20, 0.20 }
+}
+
+style "audio_bus_base"
+{
+  font_name = "sans 8"
+  fg[NORMAL] = { 0.77, 0.77, 0.72 }    
+  fg[NORMAL] = { 0.7, 0.8, 0.2 }       
+  #bg[NORMAL] = {0, 0.36, 0.40 }
+  bg[NORMAL] = "#464666"
+}
+
+style "track_name_display"
+{
+       font_name = "sans medium 11"
+       fg[NORMAL] = { 0.80, 0.80, 0.80 }
+       fg[ACTIVE] = { 0.80, 0.80, 0.80 }
+
+       base[NORMAL] = { 0.06, 0.06, 0.06 }
+       base[ACTIVE] = { 0.26, 0.26, 0.26 }
+       bg[NORMAL] = { 0.26, 0.26, 0.26 }
+       bg[ACTIVE] = { 0.26, 0.26, 0.26 }
+}
+
+style "active_track_name_display"
+{
+       font_name = "sans medium 11"
+       text[NORMAL] = { 0.26, 0.26, 0.26 }
+       base[NORMAL] = { 0.89, 0.89, 0.89 }
+}
+
+style "track_separator"
+{
+       bg[NORMAL] = { 0.40, 0.40, 0.40 }
+}
+
+#
+# Track edit groups. These styles define
+# the colors that the "edit" button will
+# use as a track is moved from
+# track edit group to track edit group.
+# There are 8 edit groups. Edit group 0
+# is used for tracks that are not editable, 
+# so we leave its style to the default.
+#
+
+style "edit_group_0"
+
+{
+       bg[ACTIVE] = { 1.0, 0.65, 0.13 }
+       bg[NORMAL] = { 0.31, 0.31, 0.31 }
+       fg[NORMAL] = { 0.82, 0.91, 0.99 }
+       fg[ACTIVE] = { 0, 0, 0 }
+}
+
+style "edit_group_1" 
+{
+       fg[NORMAL] = { 0, 0, 0 }
+       fg[PRELIGHT] = { 0, 0, 0 }
+       fg[SELECTED] = { 0, 0, 0 }
+       bg[NORMAL] = { 0.93, 0.34, 0.08 }
+       bg[PRELIGHT] = { 0.93, 0.34, 0.08 }
+       bg[SELECTED] = { 0.93, 0.34, 0.08 }
+}
+
+style "edit_group_2" 
+{
+       fg[NORMAL] = { 0, 0, 0 }
+       fg[PRELIGHT] = { 0, 0, 0 }
+       fg[SELECTED] = { 0, 0, 0 }
+       bg[NORMAL] = { 0.93, 0.34, 0.08 }
+       bg[PRELIGHT] = { 0.93, 0.34, 0.08 }
+       bg[SELECTED] = { 0.93, 0.34, 0.08 }
+}
+
+style "edit_group_3" 
+{
+       fg[NORMAL] = { 0, 0, 0 }
+       fg[PRELIGHT] = { 0, 0, 0 }
+       fg[SELECTED] = { 0, 0, 0 }
+       bg[NORMAL] = { 0.93, 0.34, 0.08 }
+       bg[PRELIGHT] = { 0.93, 0.34, 0.08 }
+       bg[SELECTED] = { 0.93, 0.34, 0.08 }
+}
+
+style "region_list_display" = "small_bold_text"
+{
+       fg[NORMAL] = { 0.80, 0.80, 0.80 }
+       fg[ACTIVE] = { 0.80, 0.80, 0.80 }
+       fg[SELECTED] = { 0.50, 1.0, 1.0 }
+       bg[NORMAL] = { 0, 0, 0 }
+       bg[ACTIVE] = { 0, 0, 0 }
+       bg[SELECTED] = { 0, 0, 0 }
+       base[NORMAL] = { 0, 0, 0 }
+       base[ACTIVE] = { 0, 1, 0 }
+       base[INSENSITIVE] = { 0, 0, 0 }
+       base[SELECTED] = { 0.80, 0.80, 0.80 }
+}
+
+style "main_canvas_area"
+{
+       bg[NORMAL] = { 0.38, 0.38, 0.38 }
+       bg[ACTIVE] = { 0.38, 0.38, 0.38 }
+       bg[INSENSITIVE] = { 0.38, 0.38, 0.38 }
+       bg[SELECTED] = { 0.38, 0.38, 0.38 }
+       bg[PRELIGHT] = { 0.38, 0.38, 0.38 }
+}
+
+style "track_controls_inactive"
+{
+       bg[NORMAL] =      { 0.60, 0.60, 0.66 }
+       bg[ACTIVE] =      { 0.60, 0.60, 0.66 }
+       bg[INSENSITIVE] = { 0.60, 0.60, 0.66 }
+       bg[SELECTED] =    { 0.60, 0.60, 0.66 }
+       bg[PRELIGHT] =    { 0.60, 0.60, 0.66 }
+
+       font_name = "sans medium 10"
+       fg[NORMAL] = { 0.7, 0.8, 0.2 }  
+}
+
+style "edit_controls_base_selected"
+{
+       bg[NORMAL] = { 0.56, 0.56, 0.56 }
+       bg[ACTIVE] = { 0.56, 0.56, 0.56 }
+       bg[INSENSITIVE] = { 0.56, 0.56, 0.56 }
+       bg[SELECTED] = { 0.56, 0.56, 0.56 }
+       bg[PRELIGHT] = { 0.56, 0.56, 0.56 }
+}
+
+style "automation_track_controls_base"
+{
+       bg[NORMAL] = { 0.22, 0.22, 0.29 }
+       bg[ACTIVE] = { 0.22, 0.22, 0.29 }
+       bg[INSENSITIVE] = { 0.22, 0.22, 0.29 }
+       bg[SELECTED] = { 0.22, 0.22, 0.29 }
+       bg[PRELIGHT] = { 0.22, 0.22, 0.29 }
+}
+
+# Plugin Editors
+style "plugin_slider" 
+{
+       font_name ="sans bold 10"
+
+       # the slider itself. the inactive part is INSENSITIVE,
+       # the active part is something else.
+
+       fg[NORMAL] = { 0.37, 0.43, 0.52 }
+       fg[ACTIVE] = { 0.37, 0.43, 0.52 }
+       fg[INSENSITIVE] = {0.40, 0.40, 0.40 } # matches default_base
+       fg[SELECTED] = { 0.37, 0.43, 0.52 }
+       fg[PRELIGHT] = { 0.37, 0.43, 0.52 }
+
+       # draws the outer rectangle around the slider
+
+       bg[NORMAL] = { 0.80, 0.80, 0.80 }
+       bg[ACTIVE] = { 0.80, 0.80, 0.80 }
+       bg[INSENSITIVE] = {0.80, 0.80, 0.80 }
+       bg[SELECTED] = { 0.80, 0.80, 0.80 }
+       bg[PRELIGHT] = { 0.80, 0.80, 0.80 }
+
+       # the numeric display
+
+       text[NORMAL] = { 0.80, 0.80, 0.80 }
+       text[ACTIVE] = { 0.80, 0.80, 0.80 }
+       text[INSENSITIVE] = { 0.80, 0.80, 0.80 }
+       text[SELECTED] = { 0.80, 0.80, 0.80 }
+       text[PRELIGHT] = { 0.80, 0.80, 0.80 }
+}
+
+style "track_list_display" = "small_bold_text"
+{
+       text[NORMAL] = { 0.80, 0.80, 0.80 }
+       text[ACTIVE] = { 0.3, 0.3, 0.3 }
+       text[INSENSITIVE] = { 0, 0, 0 }
+       text[SELECTED] = { 0.8, 0.8, 0.8 }
+
+       base[NORMAL] = { 0, 0, 0 }
+       base[ACTIVE] = { 0, 0, 0 }
+       base[INSENSITIVE] = { 0, 0, 0 }
+       base[SELECTED] = { 0, 0, 0 }
+}
+
+style "inspector_track_list_display" = "track_list_display"
+{
+       text[ACTIVE] = { 0.8, 0.8, 0.8 }
+
+       base[NORMAL] = { 0, 0, 0 }
+       base[ACTIVE] = { 0.2, 0.2, 0.2 }
+       base[INSENSITIVE] = { 0, 0, 0 }
+       base[SELECTED] = { 0.3, 0.3, 0.4 }
+}
+
+style "redirect_list_display"
+{
+       GtkTreeView::horizontal-separator = 0
+       GtkTreeView::vertical-separator = 0
+
+       font_name = "sans 10"
+       text[NORMAL] = { 0.80, 0.80, 0.80 }
+       text[ACTIVE] = { 0.5, 0.5, 0.9 }
+       text[INSENSITIVE] = { 0, 0, 0 }
+       text[SELECTED] = { 0.9, 0.3, 0.3 }
+
+       base[NORMAL] = { 0, 0, 0 }
+       base[ACTIVE] = { 0, 0, 0 }
+       base[INSENSITIVE] = { 0, 0, 0 }
+       base[SELECTED] = { 0, 0, 0 }
+
+       # these two are explicitly used by the cell renderer for the
+        # text
+
+       fg[NORMAL] = { 0.5, 0.5, 0.5 }  # used for inactive
+       fg[ACTIVE] = { 0.5, 1.0, 1.0 }  # used for active
+}
+
+style "inspector_redirect_list_display" = "redirect_list_display"
+{
+       base[SELECTED] = { 0.3, 0.3, 0.3 }
+}
+
+# MixerPanZone:
+#
+# the NORMAL fg color is used for the pan puck
+# the ACTIVE fg color is used for the speaker boxes
+
+style "pan_zone" = "default_base"
+{
+       fg[NORMAL] = { 0.34, 0.95, 0.92 }
+       fg[ACTIVE] = { 0.95, 0.48, 0.11 }
+}
+
+style "wall_clock" = "medium_bold_text"
+{
+       fg[NORMAL] = { 1.0, 1.0, 1.0 }
+       bg[NORMAL] = { 0, 0, 0 }
+}
+
+style "paler_red_when_active" = "medium_text"
+{
+       fg[NORMAL] = { 0.80, 0.80, 0.80 }
+       fg[PRELIGHT] = { 0.80, 0.80, 0.80 }
+       bg[NORMAL] = { 0.31, 0.31, 0.31 }
+       bg[PRELIGHT] = { 0.31, 0.31, 0.31 }
+
+       fg[ACTIVE] = { 0.36, 0.46, 0.28 }
+       bg[ACTIVE] = { 1.00, 0.59, 0.59}
+}
+
+style "peak_display_peaked_entry" = "small_text"
+{
+       fg[NORMAL] = { 1.0, 1.0, 1.0 }
+       fg[ACTIVE] = { 1.0, 1.0, 1.0 }
+       fg[SELECTED] = { 1.0, 1.0, 1.0 }
+
+       bg[NORMAL] = {0.9, 0.0, 0.0 }   
+       bg[ACTIVE] = { 0.9, 0.0, 0.0 }  
+       bg[PRELIGHT] = { 0.9, 0.0, 0.0 }        
+       bg[INSENSITIVE] = { 0.9, 0.0, 0.0 }     
+       bg[SELECTED] = { 0.9, 0.0, 0.0 }        
+       base[NORMAL] = { 0.9, 0.0, 0.0 }        
+       base[ACTIVE] = { 0.9, 0.0, 0.0 }        
+       base[PRELIGHT] = { 0.9, 0.0, 0.0 }      
+       base[INSENSITIVE] = { 0.9, 0.0, 0.0 }   
+       base[SELECTED] = { 0.9, 0.0, 0.0 }      
+}
+
+style "selected_strip_frame"
+{
+       fg[NORMAL] = { 0.74, 0.42, 0.47 }
+       bg[NORMAL] = { 0.79, 0.28, 0.18 }
+}
+
+style "flashing_alert" = "very_small_text"
+{
+       fg[NORMAL] = { 0.80, 0.80, 0.80 }
+       bg[NORMAL] = { 0.31, 0.31, 0.31 }
+
+       fg[ACTIVE] = { 0.80, 0.80, 0.80 }
+       bg[ACTIVE] = { 1.0, 0, 0}
+}
+
+style "selected_io_selector_port_list" = "medium_text"
+{
+       fg[NORMAL] = { 0.50, 1.0, 1.0 }
+       fg[SELECTED] = { 0.50, 1.0, 1.0 }
+       base[NORMAL] = { 0, 0, 0 }
+       base[SELECTED] = { 0, 0, 0 }
+}
+
+style "io_selector_port_list" = "medium_text"
+{
+       fg[NORMAL] = {0.80, 0.80, 0.70 }
+       fg[SELECTED] = {0.80, 0.80, 0.70 }
+       base[NORMAL] = { 0.26, 0.26, 0.26 }
+       base[SELECTED] = { 0.26, 0.26, 0.26 }
+}
+
+style "io_selector_notebook" = "default_base"
+{
+       fg[NORMAL] = { 0.50, 1.0, 1.0 }
+        font_name ="sans bold 10"
+}
+
+style "tearoff_arrow" = "medium_bold_entry"
+{
+       fg[NORMAL] = { 0.80, 0.80, 0.80 }
+       fg[PRELIGHT] = { 0.80, 0.80, 0.80 }
+       bg[NORMAL] = { 0.80, 0.80, 0.80 }
+       bg[PRELIGHT] = { 0.80, 0.80, 0.80 }
+}
+
+style "meter_metrics_strip" = "default_base"
+{
+       font_name = "sans 5"
+       fg[NORMAL] = { 1.0, 0.8, 0.2 }  
+}
+
+style "location_row_button" = "default_buttons_menus"
+{
+       font_name = "sans 10"
+}
+
+style "location_rows_clock" = "default_clock_display"
+{
+       font_name = "sans 12"
+}
+
+style "pan_slider" 
+{
+       font_name = "sans 8"
+
+       fg[NORMAL] = { 0.67, 0.23, 0.22 }
+       fg[ACTIVE] = { 0.67, 0.23, 0.22 }
+       fg[INSENSITIVE] = {0.32, 0.39, 0.45 } # matches default_base
+       fg[SELECTED] = { 0.67, 0.23, 0.22 }
+       fg[PRELIGHT] = { 0.67, 0.23, 0.22 }
+
+       bg[NORMAL] = { 0, 0, 0 }
+       bg[ACTIVE] = { 0, 0, 0 }
+       bg[INSENSITIVE] = {0.32, 0.39, 0.45 } # matches default_base
+       bg[SELECTED] = { 0, 0, 0 }
+       bg[PRELIGHT] = { 0, 0, 0 }
+
+       text[NORMAL] = { 0.85, 0.92, 0.98 }
+       text[ACTIVE] = { 0.85, 0.92, 0.98 }
+       text[INSENSITIVE] = { 0.85, 0.92, 0.98 }
+       text[SELECTED] = { 0.85, 0.92, 0.98 }
+       text[PRELIGHT] = { 0.85, 0.92, 0.98 }
+}
+
+style "region_list_whole_file"
+{
+       fg[NORMAL] = { 0.4, 0.4, 0.9 }
+}
+
+style "ardour_button" ="default_buttons_menus"
+{
+       xthickness = 1
+       ythickness = 1
+}
+
+#---------------------------------------------------------------
+widget "*FirstActionMessage" style "first_action_message"
+widget "*VerboseCanvasCursor" style "verbose_canvas_cursor"
+widget "*MarkerText" style "marker_text"
+widget "*TimeAxisViewItemName" style "time_axis_view_item_name"
+#widget "*ExportProgress" style "default_buttons_menus"
+widget "*ExportFileLabel" style "small_bold_text"
+widget "*ExportFormatLabel" style "medium_bold_text"
+widget "*ExportHeader" style "small_bold_text"
+widget "*ExportFileDisplay" style "medium_entry"
+widget "*ExportFormatDisplay" style "medium_entry"
+widget "*ExportCheckbox" style "small_entry"
+widget "*ExportTrackSelector*" style "medium_entry_noselection_bg"
+widget "*EditModeSelector" style "medium_bold_entry"
+widget "*SnapTypeSelector" style "medium_bold_entry"
+widget "*SnapModeSelector" style "medium_bold_entry"
+widget "*ZoomFocusSelector" style "medium_bold_entry"
+widget "*ArdourContextMenu*" style "default_menus"
+widget "*EditGroupTitleButton*" style "default_buttons_menus"
+widget "*MixerGroupTitleButton*" style "default_buttons_menus"
+widget "*ErrorLogCloseButton" style "default_buttons_menus"
+widget "*EditorGTKButton*" style "default_buttons_menus" 
+widget "*ToolbarButton" style "default_buttons_menus"
+widget "*ToolbarButton*" style "default_buttons_menus"
+widget "*CrossfadeEditButton" style "default_buttons_menus"
+widget "*CrossfadeEditButton*" style "default_buttons_menus"
+widget "*TrackHistoryButton*" style "default_buttons_menus"
+widget "*TrackSizeButton*" style "default_buttons_menus"
+widget "*TrackPlaylistButton*" style "default_buttons_menus"
+widget "*TrackAutomationButton*" style "default_buttons_menus"
+widget "*TrackGroupButton*" style "default_buttons_menus"
+widget "*TrackMixButton*" style "default_buttons_menus"
+widget "*TrackVisualButton*" style "default_buttons_menus"
+widget "*TrackRemoveButton*" style "default_buttons_menus"
+widget "*BaseButton" style "default_buttons_menus"
+widget "*TakeButtonLabel" style "default_buttons_menus"
+widget "*MixerWidthButton" style "default_buttons_menus"
+widget "*MixerHideButton" style "default_buttons_menus"
+widget "*MixerSendButton" style "default_buttons_menus"
+widget "*MixerSendButtonLabel" style "default_buttons_menus"
+widget "*MixerSendSwitch" style "default_buttons_menus"
+widget "*MixerInsertButton" style "default_buttons_menus"
+widget "*MixerInsertButtonLabel" style "default_buttons_menus"
+widget "*MixerInsertSwitch" style "default_buttons_menus"
+widget "*MixerMonitorInputButton*" style "very_small_button"
+widget "*MixerMonitorInputButton.*" style "very_small_button"
+widget "*MixerIOButton" style "very_small_button"
+widget "*MixerIOButtonLabel" style "very_small_button"
+widget "*AddRouteDialogSpinner" style "ardour_adjusters"
+widget "*AddRouteDialogRadioButton*" style "options_window"
+widget "*OptionsNotebook" style "options_window"
+widget "*OptionEditorToggleButton*" style "options_window"
+widget "*OptionsLabel" style "options_window"
+widget "*OptionEditorAuditionerLabel" style "options_window"
+widget "*OptionsEntry" style "option_entry"
+widget "*InspectorNotebook" style "options_window"
+widget "*NewSessionDialog" style "options_window"
+widget "*NewSessionDialogButton*" style "options_window"
+widget "*MixerSendSwitch*" style "very_small_red_active_and_selected_button"
+widget "*OptionEditorToggleButton" style "small_red_active_and_selected_button"
+widget "*NewSessionDialogButton" style "small_red_active_and_selected_button"
+widget "*MixerRecordEnableButton" style "mixer_rec_enable_button"
+widget "*MixerRecordEnableButton*" style "mixer_rec_enable_button"
+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 "*EditorTimeButton*" style "time_button"
+widget "*EditorMixerButton*" style "default_buttons_menus"
+widget "*SoloButton*" style "solo_button"
+widget "*SoloButton.*" style "solo_button"
+widget "*SafeSoloButton*" style "solo_button"
+widget "*SafeSoloButton.*" style "solo_button"
+widget "*MixerPhaseInvertButton*" style "very_small_button"
+widget "*MixerPhaseInvertButton.*" style "very_small_button"
+widget "*MixerAutomationRecordingButton*" style "very_small_button"
+widget "*MixerAutomationRecordingButton.*" style "very_small_button"
+widget "*MixerAutomationModeButton*" style "very_small_button"
+widget "*MixerAutomationModeButton.*" style "very_small_button"
+widget "*MixerAutomationPlaybackButton*" style "very_small_button"
+widget "*MixerAutomationPlaybackButton.*" style "very_small_button"
+widget "*MixerMuteButton*" style "mixer_mute_button"
+widget "*MixerMuteButton.*" style "mixer_mute_button"
+widget "*MixerSoloButton*" style "mixer_solo_button"
+widget "*MixerSoloButton.*" style "mixer_solo_button"
+widget "*MixerNameButton" style "very_small_button"
+widget "*MixerNameButtonLabel" style "very_small_button"
+widget "*MixerGroupButton" style "very_small_button"
+widget "*MixerGroupButtonLabel" style "very_small_button"
+widget "*MixerCommentButton" style "very_small_button"
+widget "*MixerCommentButton*" style "very_small_button"
+widget "*EditGroupButton" style "very_small_button"
+widget "*EditGroupButtonLabel" style "very_small_button"
+widget "*TransportButton" style "transport_button"
+widget "*TransportButton*" style "transport_button"
+widget "*ShuttleButton" style "transport_button"
+widget "*ShuttleButton*" style "transport_button"
+widget "*ShuttleDisplay" style "transport_button"
+widget "*ShuttleDisplay*" style "transport_button"
+widget "*ShuttleControl" style "shuttle_control"
+widget "*TransportRecButton" style "transport_rec_button"
+widget "*TransportRecButton*" style "transport_rec_button"
+widget "*RecordingXrunWarningWindow" style "xrun_warn"
+widget "*RecordingXrunWarningWindow*" style "xrun_warn"
+widget "*MainMenuBar" style "menu_bar_base"
+widget "*ErrorMessage" style "error_message"
+widget "*FatalMessage" style "fatal_message"
+widget "*InfoMessage" style "info_message"
+widget "*WarningMessage" style "warning_message"
+widget "*BigClockDisplay" style "big_clock_display"
+widget "*TransportClockDisplay" style "transport_clock_display"
+widget "*SecondaryClockDisplay" style "transport_clock_display"
+widget "*BBTTempoLabel" style "tempo_meter_clock_display"
+widget "*BBTMeterLabel" style "tempo_meter_clock_display"
+widget "*SelectionStartClock" style "default_clock_display"
+widget "*SelectionEndClock" style "default_clock_display"
+widget "*EditCursorClock" style "default_clock_display"
+widget "*PreRollClock" style "default_clock_display"
+widget "*PostRollClock" style "default_clock_display"
+widget "*NudgeClock" style "default_clock_display"
+widget "*ZoomRangeClock" style "default_clock_display"
+widget "*SMPTEOffsetClock" style "default_clock_display"
+widget "*TransportLabel" style "small_bold_text"
+widget "*TakeLabel" style "small_bold_text"
+widget "*LocationLabel" style "small_bold_text"
+widget "*WipeLabel" style "small_bold_text"
+widget "*TakeTagLabel" style "small_bold_text"
+widget "*ToolBarLabel" style "small_bold_text"
+widget "*EditorDisplayLabel" style "small_bold_text"
+widget "*NewSessionLabel" style "large_text"
+widget "*GlobalButtonLabel" style "default_buttons_menus"
+widget "*ClickButton" style "medium_entry"
+widget "*RegionNameDisplay" style "medium_entry"
+widget "*PluginDisplay" style "medium_entry"
+widget "*SelectionDisplay" style "medium_entry"
+widget "*HistorySelector" style "medium_entry"
+widget "*LocationSelector" style "medium_entry"
+widget "*TakeSelector" style "medium_entry"
+widget "*RegionSelector" style "medium_entry"
+widget "*SMPTERuler" style "editor_time_ruler"
+widget "*BBTRuler" style "editor_time_ruler"
+widget "*FramesRuler" style "editor_time_ruler"
+widget "*MinSecRuler" style "editor_time_ruler"
+widget "*BaseFrame" style "base_frame"
+widget "*AudioTrackStripBase" style "audio_track_base"
+widget "*TimeAxisViewControlsBaseUnselected" style "audio_track_base"
+widget "*AudioTrackControlsBaseUnselected" style "audio_track_base"
+widget "*AudioTrackFader" style "audio_track_base"
+widget "*AudioBusStripBase" style "audio_bus_base"
+widget "*BusControlsBaseUnselected" style "audio_bus_base"
+widget "*AudioBusFader" style "audio_bus_base"
+widget "*TrackSeparator" style "track_separator"
+widget "*TrackEditIndicator0*" style "edit_group_0"
+widget "*TrackEditIndicator1*" style "edit_group_1"
+widget "*TrackEditIndicator2*" style "edit_group_2"
+widget "*TrackEditIndicator3*" style "edit_group_3"
+widget "*TrackEditIndicator4*" style "edit_group_3"
+widget "*TrackEditIndicator5*" style "edit_group_3"
+widget "*TrackEditIndicator6*" style "edit_group_3"
+widget "*TrackEditIndicator7*" style "edit_group_3"
+widget "*EditorTrackNameDisplay" style "track_name_display"
+widget "*EditorTrackNameDisplay*" style "track_name_display"
+widget "*EditorActiveTrackNameDisplay" style "active_track_name_display"
+widget "*EditorActiveTrackNameDisplay*" style "active_track_name_display"
+widget "*EditorRegionList" style "region_list_display"
+widget "*CrossfadeEditAuditionButton" style "red_when_active"
+widget "*CrossfadeEditAuditionButton*" style "red_when_active"
+widget "*CrossfadeEditCurveButton" style "red_when_active"
+widget "*CrossfadeEditCurveButton*" style "red_when_active"
+widget "*CrossfadeEditLabel" style "medium_text"
+widget "*CrossfadeEditFrame" style "base_frame"
+widget "*MouseModeButton" style "default_buttons_menus"
+widget "*MouseModeButton*" style "default_buttons_menus"
+widget "*EditorMainCanvas" style "main_canvas_area"
+widget "*AudioTrackControlsBaseInactiveUnselected" style "track_controls_inactive"
+widget "*BusControlsBaseInactiveUnselected" style "track_controls_inactive"
+widget "*AutomationTrackControlsBaseInactiveUnselected" style "track_controls_inactive"
+widget "*AudioTrackControlsBaseInactiveSelected" style "track_controls_inactive"
+widget "*BusControlsBaseInactiveSelected" style "track_controls_inactive"
+widget "*AutomationTrackControlsBaseInactiveSelected" style "track_controls_inactive"
+widget "*AudioTrackStripBaseInactive" style "track_controls_inactive"
+widget "*AudioBusStripBaseInactive" style "track_controls_inactive"
+widget "*AudioTrackControlsBaseSelected" style "edit_controls_base_selected"
+widget "*BusControlsBaseSelected" style "edit_controls_base_selected"
+widget "*AutomationTrackControlsBase" style "automation_track_controls_base"
+widget "*AutomationTrackControlsBaseSelected" style "edit_controls_base_selected"
+widget "*EditorMenuBar*" style "black_mackie_menu_bar"
+widget "*MainMenuBar*" style "black_mackie_menu_bar"
+widget "*ZoomClickBox" style "medium_bold_entry"
+widget "*PluginParameterLabel" style "medium_text"
+widget "*PluginNameInfo" style "plugin_name_text"
+widget "*PluginMakerInfo" style "plugin_maker_text"
+widget "*PluginParameterInfo" style "medium_text"
+widget "*MotionControllerValue" style "medium_entry"
+widget "*ParameterValueDisplay" style "medium_bold_entry"
+widget "*PluginUIClickBox" style "medium_bold_entry"
+widget "*PluginUIClickBox*" style "medium_bold_entry"
+widget "*PluginSlider" style "plugin_slider"
+widget "*TrackListDisplay" style "track_list_display"
+widget "*TrackListDisplay.*" style "small_bold_text"
+widget "*EditGroupList" style "track_list_display"
+widget "*RegionListDisplay" style "small_bold_entry"
+widget "*RegionListDisplay.*" style "small_bold_text"
+widget "*RedirectSelector" style "redirect_list_display"
+widget "*RedirectSelector.*" style "redirect_list_display"
+widget "*MixerTrackCommentArea" style "option_entry"
+widget "*MixerPanZone" style "pan_zone"
+widget "*MixerTrackDisplayList" style "track_list_display"
+widget "*MixerSnapshotDisplayList" style "track_list_display"
+widget "*MixerAuxDisplayList" style "track_list_display"
+widget "*MixerGroupList" style "track_list_display"
+widget "*WallClock" style "wall_clock"
+widget "*CPULoad" style "wall_clock"
+widget "*RegionEditorLabel" style "medium_text"
+widget "*RegionEditorSmallLabel" style "small_text"
+widget "*RegionEditorEntry" style "medium_entry"
+widget "*RegionEditorClock" style "default_clock_display"
+widget "*RegionEditorToggleButton" style "paler_red_when_active"
+widget "*RegionEditorToggleButton*" style "paler_red_when_active"
+widget "*MixerStripSpeedBase" style "small_entry"
+widget "*MixerStripSpeedBase*" style "small_entry"
+widget "*MixerStripSpeedBaseNotOne" style "small_red_on_black_entry"
+widget "*MixerStripSpeedBaseNotOne*" style "small_red_on_black_entry"
+widget "*MixerStripGainDisplay" style "small_entry"
+widget "*MixerStripGainUnitButton" style "very_small_button"
+widget "*MixerStripGainUnitButton*" style "very_small_button"
+widget "*MixerStripMeterPreButton" style "very_small_button"
+widget "*MixerStripMeterPreButton*" style "very_small_button"
+widget "*MixerStripPeakDisplay*" style "red_active_small_entry"
+widget "*MixerStripPeakDisplayPeak*" style "peak_display_peaked_entry"
+widget "*MixerStripSelectedFrame" style "selected_strip_frame"
+widget "*MixerStripFrame" style "base_frame"
+widget "*HWMonitorButton" style "red_when_active"
+widget "*HWMonitorButton*" style "red_when_active"
+widget "*BypassButton" style "red_when_active"
+widget "*BypassButton*" style "red_when_active"
+widget "*TransportSoloAlert" style "flashing_alert"
+widget "*TransportSoloAlert.*" style "flashing_alert"
+widget "*TransportAuditioningAlert" style "flashing_alert"
+widget "*TransportAuditioningAlert.*" style "flashing_alert"
+widget "*FadeCurve" style "medium_bold_entry"
+widget "*FadeCurve*" style "medium_bold_entry"
+widget "*IOSelectorButton" style "default_buttons_menus"
+widget "*IOSelectorButton*" style "default_buttons_menus"
+widget "*IOSelectorList" style "medium_entry_noselection_fg"
+widget "*IOSelectorPortList" style "io_selector_port_list"
+widget "*IOSelectorPortListSelected" style "selected_io_selector_port_list"
+widget "*IOSelectorNotebook" style "io_selector_notebook"
+widget "*IOSelectorNotebookTab" style "io_selector_notebook"
+widget "*IOSelectorFrame" style "base_frame"
+widget "*ConnectionEditorButton" style "default_buttons_menus"
+widget "*ConnectionEditorButton*" style "default_buttons_menus"
+widget "*ConnectionEditorList" style "medium_entry_noselection_fg"
+widget "*ConnectionEditorConnectionList" style "medium_entry"
+widget "*ConnectionEditorPortList" style "io_selector_port_list"
+widget "*ConnectionEditorPortListSelected" style "selected_io_selector_port_list"
+widget "*ConnectionEditorNotebook" style "io_selector_notebook"
+widget "*ConnectionEditorNotebookTab" style "io_selector_notebook"
+widget "*ConnectionEditorFrame" style "base_frame"
+widget "*RouteParamsListDisplay" style "inspector_track_list_display"
+widget "*RouteParamsPreListDisplay" style "inspector_redirect_list_display"
+widget "*RouteParamsPostListDisplay" style "inspector_redirect_list_display"
+widget "*TearOffArrow" style "tearoff_arrow"
+widget "*RouteParamsTitleButton" style "medium_text"
+widget "*RouteParamsTitleLabel" style "medium_text"
+widget "*PluginAutomateRecordButton" style "small_red_active_and_selected_button"
+widget "*PluginAutomateRecordButton*" style "small_red_active_and_selected_button"
+widget "*PluginAutomatePlayButton" style "small_red_active_and_selected_button"
+widget "*PluginAutomatePlayButton*" style "small_red_active_and_selected_button"
+widget "*PluginAutomateButton" style "small_button"
+widget "*PluginAutomateButton*" style "small_button"
+widget "*PluginSaveButton" style "small_button"
+widget "*PluginSaveButton*" style "small_button"
+widget "*PluginLoadButton" style "small_button"
+widget "*PluginLoadButton*" style "small_button"
+widget "*FaderMetricsStrip" style "meter_metrics_strip"
+widget "*MeterMetricsStrip" style "meter_metrics_strip"
+widget "*MetricDialogFrame" style "base_frame"
+widget "*MetricEntry" style "medium_bold_entry"
+widget "*MetricButton" style "default_buttons_menus"
+widget "*MetricButton.*" style "default_buttons_menus"
+widget "*MetricLabel" style "medium_text"
+widget "*TimeStretchButton" style "default_buttons_menus"
+widget "*TimeStretchButton.*" style "default_buttons_menus"
+widget "*TimeStretchProgress" style "default_buttons_menus"
+widget "*ChoiceWindow" style "default_buttons_menus"
+widget "*ChoicePrompt" style "default_buttons_menus"
+widget "*ChoiceButton" style "default_buttons_menus"
+widget "*ChoiceButton*" style "default_buttons_menus"
+widget "*SelectionModeButton" style "default_buttons_menus"
+widget "*SelectionModeButton*" style "default_buttons_menus"
+widget "*TrackLabel" style "medium_text"
+widget "*TrackPlugName" style "medium_text"
+widget "*TrackParameterName" style "small_text"
+widget "*AddRouteDialog*" style "medium_text"
+widget "*AddRouteDialog.GtkLabel" style "medium_text"
+widget "*AddRouteDialogChannelChoice" style "medium_bold_entry"
+widget "*AddRouteDialogSpinner" style "medium_bold_entry"
+widget "*AddRouteDialogSpinner*" style "medium_bold_entry"
+widget "*AddRouteDialogRadioButton" style "red_when_active"
+widget "*AddRouteDialogButton" style "default_buttons_menus"
+widget "*AddRouteDialogNameTemplateEntry" style "medium_bold_entry"
+widget "*NewSessionIOLabel" style "larger_bold_text"
+widget "*NewSessionSR1Label" style "red_medium_text"
+widget "*NewSessionSR2Label" style "medium_text"
+widget "*NewSessionChannelChoice" style "medium_bold_entry"
+widget "*NewSessionMainButton" style "larger_bold_text"
+widget "*NewSessionMainButton*" style "larger_bold_text"
+widget "*NewSessionMainLabel" style "larger_bold_text"
+widget "*LocationEditRowClock" style "location_rows_clock"
+widget "*LocationEditNameLabel" style "medium_text"
+widget "*LocationEditSetButton" style "location_row_button"
+widget "*LocationEditSetButton*" style "location_row_button"
+widget "*LocationEditGoButton" style "location_row_button"
+widget "*LocationEditGoButton*" style "location_row_button"
+widget "*LocationEditCdButton" style "small_red_active_and_selected_button"
+widget "*LocationEditCdButton*" style "small_red_active_and_selected_button"
+widget "*LocationEditHideButton" style "small_red_active_and_selected_button"
+widget "*LocationEditHideButton*" style "small_red_active_and_selected_button"
+widget "*LocationEditNumberLabel" style "small_text"
+widget "*LocationLocEditorFrame" style "base_frame"
+widget "*LocationRangeEditorFrame" style "base_frame"
+widget "*LocationEditNameEntry" style "option_entry"
+widget "*LocationAddLocationButton" style "default_buttons_menus"
+widget "*LocationAddLocationButton*" style "default_buttons_menus"
+widget "*LocationAddRangeButton" style "default_buttons_menus"
+widget "*LocationAddRangeButton*" style "default_buttons_menus"
+widget "*LocationEditRemoveButton" style "location_row_button"
+widget "*LocationEditRemoveButton*" style "location_row_button"
+widget "*PanSlider" style "pan_slider"
+widget "*PanningLinkButton" style "mixer_red_active_button"
+widget "*PanningLinkButton.*" style "mixer_red_active_button"
+widget "*PanningLinkDirectionButton" style "very_small_button"
+widget "*PanningLinkDirectionButton.*" style "very_small_button"
+widget "*ChannelCountSelector" style "medium_bold_entry"
+widget "*ChannelCountSelector.GtkArrow" style "default_buttons_menus"
+widget "*RegionListWholeFile" style "region_list_whole_file"
+
+class "GtkWidget" style "default_base"
+class "GtkScrollbar" style "ardour_adjusters"
+class "GtkLabel" style "default_buttons_menus"
+class "GtkButton" style "ardour_button"
+class "GtkArrow" style "tearoff_arrow"
+class "GtkProgressBar" style "ardour_progressbars"
+
index fead9ba512cc31bc437a5e51197ff34b27ba9ac3..a711a1386dee187e2ff15291905d79e9b1a30413 100644 (file)
@@ -17,8 +17,8 @@ winmain.c
 """
 )
 
-ardour_vst.Append (CCFLAGS="-DVST_SUPPORT", CPPPATH="#libs/fst", LIBPATH='#gtk2_ardour')
-ardour_vst.Append (LINKFLAGS='-L/usr/X11R6/lib -lasound -lardourgtk -lX11 -lpthread') 
+ardour_vst.Append (CCFLAGS="-DVST_SUPPORT", CPPPATH="#libs/fst", LIBPATH='#gtk2_ardour', LIBS="ardourgtk")
+ardour_vst.Append (LINKFLAGS='-L/usr/X11R6/lib -lasound -lX11 -lpthread') 
 ardour_vst["CC"] ="winegcc"
 ardour_vst["LINK"] ="wineg++ -mwindows"
 
@@ -27,7 +27,7 @@ ardour_vst.Merge ([
     libraries['ardour_cp'],
     libraries['gtkmm2ext'],
     libraries['midi++2'],
-    libraries['pbd3'],
+    libraries['pbd'],
     libraries['gtkmm2'],
     libraries['glib2'],
     libraries['libgnomecanvas2'],