virtualize Port object; clean up automation tracks from track deletion
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 16 Oct 2007 21:01:12 +0000 (21:01 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 16 Oct 2007 21:01:12 +0000 (21:01 +0000)
git-svn-id: svn://localhost/ardour2/trunk@2556 d708f5d6-7413-0410-9779-e7cbd77b26cf

25 files changed:
SConstruct
gtk2_ardour/ardour-sae.menus [new file with mode: 0644]
gtk2_ardour/main.cc
gtk2_ardour/mixer_ui.cc
gtk2_ardour/route_time_axis.cc
libs/ardour/SConscript
libs/ardour/ardour/audio_port.h
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/jack_audio_port.h [new file with mode: 0644]
libs/ardour/ardour/jack_midi_port.h [new file with mode: 0644]
libs/ardour/ardour/midi_port.h
libs/ardour/ardour/port.h
libs/ardour/audio_port.cc
libs/ardour/audioengine.cc
libs/ardour/io.cc
libs/ardour/jack_audio_port.cc [new file with mode: 0644]
libs/ardour/jack_midi_port.cc [new file with mode: 0644]
libs/ardour/jack_port.cc [new file with mode: 0644]
libs/ardour/midi_port.cc
libs/ardour/port.cc
libs/ardour/session.cc
libs/pbd/SConscript
libs/pbd/boost-debug/shared_ptr.hpp [new file with mode: 0644]
libs/pbd/pbd/stacktrace.h
libs/pbd/stacktrace.cc

index 5f6bde510312653bb719e346c094ff73b4e35e97..25cd2172228bed7949f826298c3505eb4c1727cb 100644 (file)
@@ -721,6 +721,15 @@ def prep_libcheck(topenv, libinfo):
             
 prep_libcheck(env, env)
 
+#
+# glibc backtrace API, needed everywhere if we want to do shared_ptr<T> debugging
+#
+
+conf = Configure (env)
+if conf.CheckCHeader('execinfo.h'):
+    conf.env.Append(CXXFLAGS="-DHAVE_EXECINFO")
+env = conf.Finish ()
+
 #
 # Check for libusb
 
diff --git a/gtk2_ardour/ardour-sae.menus b/gtk2_ardour/ardour-sae.menus
new file mode 100644 (file)
index 0000000..511ce3a
--- /dev/null
@@ -0,0 +1,320 @@
+<ui>
+
+    <menubar name='Main' action='MainMenu'>
+        <menu name='Session' action='Session'>
+           <menuitem action='New'/>
+           <menuitem action='Open'/>
+           <menuitem action='Recent'/>
+           <menuitem action='Close'/>
+           <separator/>
+           <menuitem action='Save'/>
+           <menuitem action='Snapshot'/>
+           <menuitem action='SaveTemplate'/>
+           <separator/>
+           <menuitem action='AddTrackBus'/>    
+           <separator/>
+           <menu name='Cleanup' action='Cleanup'>
+               <menuitem action='CleanupUnused'/>
+               <menuitem action='FlushWastebasket'/>
+           </menu>
+        </menu>
+       <menu name='Files' action='Files'>
+           <menuitem action='addExistingAudioFiles'/>
+           <separator/>
+           <menuitem action='ExportSession'/>
+           <menuitem action='ExportSelection'/>
+           <menuitem action='ExportRangeMarkers'/>
+       </menu>
+        <menu name='Transport' action='Transport'>
+               <menuitem action='ToggleRoll'/>
+               <menuitem action='ToggleRollForgetCapture'/>
+               <menuitem action='Loop'/>
+               <menuitem action='PlaySelection'/>
+               <menuitem action='set-playhead'/>
+               <menuitem action='Forward'/>
+               <menuitem action='Rewind'/>
+               <menuitem action='GotoZero'/>
+               <menuitem action='GotoStart'/>
+               <menuitem action='GotoEnd'/>
+              <separator/>
+               <menuitem action='Record'/>
+               <separator/> 
+               <menuitem action='TransitionToRoll'/>
+               <menuitem action='TransitionToReverse'/>
+               <separator/> 
+               <menuitem action='jump-forward-to-mark'/>
+               <menuitem action='jump-backward-to-mark'/>
+               <menuitem action='add-location-from-playhead'/>
+               <separator/> 
+               <menuitem action='playhead-to-next-region-start'/>
+               <menuitem action='playhead-to-next-region-end'/>
+               <menuitem action='playhead-to-previous-region-start'/>
+               <menuitem action='playhead-to-previous-region-end'/>
+               <menuitem action='playhead-to-next-region-sync'/>
+               <menuitem action='playhead-to-previous-region-sync'/>
+               <menuitem action='center-playhead'/>
+               <menuitem action='playhead-to-edit'/>
+               <separator/>       
+               <menuitem action='playhead-to-range-start'/>
+               <menuitem action='playhead-to-range-end'/>
+               <menu action='TransportOptions'>
+                    <menuitem action='ToggleTimeMaster'/>
+                    <menuitem action='TogglePunchIn'/>
+                    <menuitem action='TogglePunchOut'/>
+                    <menuitem action='ToggleAutoInput'/>
+                    <menuitem action='ToggleAutoPlay'/>
+                    <menuitem action='ToggleAutoReturn'/>
+                    <menuitem action='ToggleClick'/>
+                    <menuitem action='toggle-follow-playhead'/>
+                    <menuitem action='ToggleVideoSync'/>
+               </menu>
+       </menu>
+       <menu name='Edit' action='Edit'>
+               <menuitem action='undo'/>
+               <menuitem action='redo'/>
+               <menuitem action='editor-cut'/>
+               <menuitem action='editor-delete'/>
+               <menuitem action='editor-copy'/>
+               <menuitem action='editor-paste'/>
+               <menuitem action='set-edit-cursor'/>
+              <menuitem action='remove-last-capture'/>
+               <separator/>       
+               <menu action="EditSelectRangeOptions">
+                   <menuitem action='extend-range-to-start-of-region'/>
+                   <menuitem action='extend-range-to-end-of-region'/>
+                   <menuitem action='start-range'/>
+                   <menuitem action='finish-range'/>
+                   <menuitem action='finish-add-range'/>
+               </menu>
+               <menu action="EditSelectRegionOptions">
+                   <menuitem action='select-all'/>
+                   <menuitem action='select-all-after-edit-cursor'/>
+                   <menuitem action='select-all-before-edit-cursor'/>
+                   <menuitem action='select-all-after-playhead'/>
+                   <menuitem action='select-all-before-playhead'/>
+                   <menuitem action='select-all-between-cursors'/>
+                   <menuitem action='select-all-in-punch-range'/>
+                   <menuitem action='select-all-in-loop-range'/>
+               </menu>
+              <menu action='EditCursorMovementOptions'>
+                   <menuitem action='edit-cursor-to-next-region-start'/>
+                  <menuitem action='edit-cursor-to-next-region-end'/>
+                          <menuitem action='edit-cursor-to-previous-region-start'/>
+                  <menuitem action='edit-cursor-to-previous-region-end'/>
+                  <menuitem action='edit-cursor-to-next-region-sync'/>
+                  <menuitem action='edit-cursor-to-previous-region-sync'/>
+                  <menuitem action='center-edit-cursor'/>
+                  <menuitem action='edit-to-playhead'/>
+                  <menuitem action='edit-cursor-to-range-start'/>
+                  <menuitem action='edit-cursor-to-range-end'/>
+              </menu>
+              <menu name='KeyMouse Actions' action='KeyMouse Actions'>
+                       <menuitem action='audition-at-mouse'/>
+                               <menuitem action='brush-at-mouse'/>
+                               <menuitem action='mute-unmute-region'/>
+                       <separator/>
+                       <menuitem action='set-mouse-mode-object'/>
+                       <menuitem action='set-mouse-mode-range'/>
+                       <menuitem action='set-mouse-mode-gain'/>
+                       <menuitem action='set-mouse-mode-zoom'/>
+                       <menuitem action='set-mouse-mode-timefx'/>
+               </menu>
+                <separator/>       
+                <menuitem action='ToggleOptionsEditor'/>
+        </menu>         
+       <menu name='Regions' action='Regions'>
+                   <menuitem action='crop'/>
+                   <menuitem action='duplicate-region'/>
+                   <menuitem action='insert-region'/>
+                          <menuitem action='normalize-region'/>
+                   <separator/>       
+                  <menuitem action="nudge-forward"/>
+                  <menuitem action="nudge-next-forward"/>
+                  <menuitem action="nudge-backward"/>
+                  <menuitem action="nudge-next-backward"/>
+                  <menuitem action='split-region'/>
+                  <menuitem action='set-region-sync-position'/>
+       </menu>
+        <menu name='View' action = 'View'>
+               <menu name='ZoomFocus' action='ZoomFocus'>
+                   <menuitem action='zoom-focus-left'/>
+                   <menuitem action='zoom-focus-right'/>
+                   <menuitem action='zoom-focus-center'/>
+                   <menuitem action='zoom-focus-playhead'/>
+                   <menuitem action='zoom-focus-edit'/>
+               </menu>
+              <menu name='SnapMode' action='SnapMode'>
+                  <menuitem action='snap-normal'/>
+                  <menuitem action='snap-magnetic'/>
+              </menu>
+               <menu name='SnapTo' action='SnapTo'>
+                  <menuitem action='snap-to-frame'/>
+                  <menuitem action='snap-to-cd-frame'/>
+                  <menuitem action='snap-to-smpte-frame'/>
+                  <menuitem action='snap-to-smpte-seconds'/>
+                  <menuitem action='snap-to-smpte-minutes'/>
+                  <menuitem action='snap-to-seconds'/>
+                  <menuitem action='snap-to-minutes'/>
+                  <menuitem action='snap-to-thirtyseconds'/>
+                  <menuitem action='snap-to-asixteenthbeat'/>
+                  <menuitem action='snap-to-eighths'/>
+                  <menuitem action='snap-to-quarters'/>
+                  <menuitem action='snap-to-thirds'/>
+                  <menuitem action='snap-to-beat'/>
+                  <menuitem action='snap-to-bar'/>
+                  <menuitem action='snap-to-mark'/>
+                  <menuitem action='snap-to-edit-cursor'/>
+                  <menuitem action='snap-to-region-start'/>
+                  <menuitem action='snap-to-region-end'/>
+                  <menuitem action='snap-to-region-sync'/>
+                  <menuitem action='snap-to-region-boundary'/>
+               </menu>
+               <separator/>
+
+               <menuitem action='temporal-zoom-in'/>
+               <menuitem action='temporal-zoom-out'/>
+               <menuitem action='zoom-to-session'/>
+               <menuitem action='scroll-tracks-down'/>
+               <menuitem action='scroll-tracks-up'/>
+               <menuitem action='scroll-tracks-down'/>
+               <menuitem action='step-tracks-up'/>
+               <menuitem action='step-tracks-down'/>
+              <separator/>
+               <menuitem action='scroll-forward'/>
+               <menuitem action='scroll-backward'/>
+              <separator/>
+               <menuitem action='scroll-playhead-forward'/>
+               <menuitem action='scroll-playhead-backward'/>
+              <separator/>
+              <menuitem action='show-editor-mixer'/>
+              <menuitem action='SyncEditorAndMixerTrackOrder'/>
+              <menuitem action='ToggleLogoVisibility'/>
+         </menu>
+        <menu name='JACK' action='JACK'>
+               <menuitem action='JACKDisconnect'/>
+               <menuitem action='JACKReconnect'/>
+               <menu name='Latency' action='Latency'>
+                   <menuitem action='JACKLatency32'/>
+                   <menuitem action='JACKLatency64'/>
+                   <menuitem action='JACKLatency128'/>
+                   <menuitem action='JACKLatency256'/>
+                   <menuitem action='JACKLatency512'/>
+                   <menuitem action='JACKLatency1024'/>
+                   <menuitem action='JACKLatency2048'/>
+                   <menuitem action='JACKLatency4096'/>
+                   <menuitem action='JACKLatency8192'/>
+               </menu>
+        </menu>
+        <menu name='Windows' action = 'Windows'>
+              <menuitem action='ToggleMaximalEditor'/>
+              <separator/>
+               <menuitem action='goto-editor'/>
+               <menuitem action='goto-mixer'/>
+               <menuitem action='ToggleInspector'/>
+               <menuitem action='ToggleLocations'/>
+               <menuitem action='ToggleThemeManager'/>
+               <menuitem action='ToggleBigClock'/>
+              <separator/>
+        </menu>
+        <menu name='Options' action='Options'>
+              <menu action='AudioFileFormat'>
+                   <menu action='AudioFileFormatData'>
+                       <menuitem action='FileDataFormatFloat'/>
+                       <menuitem action='FileDataFormat24bit'/>
+                       <menuitem action='FileDataFormat16bit'/>
+                  </menu>
+                   <menu action='AudioFileFormatHeader'>
+                       <menuitem action='FileHeaderFormatBWF'/>
+                       <menuitem action='FileHeaderFormatWAVE'/>
+                       <menuitem action='FileHeaderFormatWAVE64'/>
+                       <menuitem action='FileHeaderFormatCAF'/>
+                  </menu>
+               </menu>
+               <menu action='Monitoring'>
+                   <menuitem action='UseHardwareMonitoring'/>
+                   <menuitem action='UseSoftwareMonitoring'/>
+                   <menuitem action='UseExternalMonitoring'/>
+               </menu>
+              <menu action='Metering'>
+                   <menu action='MeteringFallOffRate'>
+                       <menuitem action='MeterFalloffOff'/>
+                       <menuitem action='MeterFalloffSlowest'/>
+                       <menuitem action='MeterFalloffSlow'/>
+                       <menuitem action='MeterFalloffMedium'/>
+                       <menuitem action='MeterFalloffFast'/>
+                       <menuitem action='MeterFalloffFaster'/>
+                       <menuitem action='MeterFalloffFastest'/>
+                   </menu>
+                   <menu action='MeteringHoldTime'>
+                       <menuitem action='MeterHoldOff'/>
+                       <menuitem action='MeterHoldShort'/>
+                       <menuitem action='MeterHoldMedium'/>
+                       <menuitem action='MeterHoldLong'/>
+                   </menu>
+               </menu>
+               <menu action='Solo'>
+                   <menuitem action='LatchedSolo'/>
+               </menu>
+         </menu>
+        <menu name='Help' action='Help'>
+            <menuitem action='About'/>
+       </menu>
+     </menubar>
+
+     <popup name='redirectmenu'>
+        <menuitem action='newplugin'/>
+        <menuitem action='newinsert'/>
+        <menuitem action='newsend'/>
+         <separator/>
+        <menuitem action='clear'/>
+         <separator/>
+        <menuitem action='cut'/>
+        <menuitem action='copy'/>
+        <menuitem action='paste'/>
+        <menuitem action='delete'/>
+         <separator/>
+        <menuitem action='rename'/>
+         <separator/>
+        <menuitem action='selectall'/>
+        <menuitem action='deselectall'/>
+         <separator/>
+        <menuitem action='activate'/>
+        <menuitem action='deactivate'/>
+         <separator/>
+        <menuitem action='activate_all'/>
+        <menuitem action='deactivate_all'/>
+         <separator/>
+        <menuitem action='edit'/>
+      </popup>
+
+     <popup name='ShuttleUnitPopup'>
+        <menuitem action='SetShuttleUnitsPercentage'/>
+        <menuitem action='SetShuttleUnitsSemitones'/>
+     </popup>
+
+     <popup name='RegionListMenu'>
+         <menuitem action='rlAudition'/>
+         <menuitem action='rlHide'/>
+         <menuitem action='rlRemove'/>
+         <separator/>
+         <menuitem action='rlShowAll'/>
+         <menuitem action='rlShowAuto'/>
+         <menu name='Sort' action='RegionListSort'>
+               <menuitem action='SortAscending'/>
+               <menuitem action='SortDescending'/>
+                      <separator/>
+               <menuitem action='SortByRegionName'/>
+               <menuitem action='SortByRegionLength'/>
+               <menuitem action='SortByRegionPosition'/>
+               <menuitem action='SortByRegionTimestamp'/>
+               <menuitem action='SortByRegionStartinFile'/>
+               <menuitem action='SortByRegionEndinFile'/>
+               <menuitem action='SortBySourceFileName'/>
+               <menuitem action='SortBySourceFileLength'/>
+               <menuitem action='SortBySourceFileCreationDate'/>
+               <menuitem action='SortBySourceFilesystem'/>
+         </menu>
+         <separator/>
+         <menuitem action='addExternalAudioToRegionList'/>            
+     </popup>
+</ui>
index 5203346d57ba77b9ed08b1b1146d416e1328ea81..32e14420ff519ce8129c6d33d68b326261e85d3e 100644 (file)
@@ -324,3 +324,4 @@ int main (int argc, char *argv[])
 #ifdef VST_SUPPORT
 } // end of extern C block
 #endif
+
index e3f6cae6ac8b4165abb5698c735123997d9f1f9d..d37ab40a3c14cf88c135f810ba23ee04be194e02 100644 (file)
@@ -340,7 +340,7 @@ void
 Mixer_UI::remove_strip (MixerStrip* strip)
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &Mixer_UI::remove_strip), strip));
-       
+
        TreeModel::Children rows = track_model->children();
        TreeModel::Children::iterator ri;
        list<MixerStrip *>::iterator i;
index d2e316f626bf7497ac6b2fe3e90007f7e10f6a90..b5f04f537b2c8928aaee71d30dd1fcf4bb3d25f0 100644 (file)
@@ -223,6 +223,12 @@ RouteTimeAxisView::~RouteTimeAxisView ()
                delete _view;
                _view = 0;
        }
+
+       for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
+               delete i->second;
+       }
+       
+       _automation_tracks.clear ();
 }
 
 void
index 465138d90d2f62a357cd610695c9a6feced11220..556c6c3c9b81868108186624cb44b594bee8c7a0 100644 (file)
@@ -27,47 +27,26 @@ ardour.Append(POTFILE = domain + '.pot')
 ardour.Append(CPPPATH = '#libs/surfaces/control_protocol')
 
 ardour_files=Split("""
-bundle.cc
-chan_count.cc
-diskstream.cc
-directory_names.cc
-filename_extensions.cc
-filesystem_paths.cc
-find_session.cc
-tape_file_matcher.cc
-template_utils.cc
-track.cc
+amp.cc
+audio_buffer.cc
 audio_diskstream.cc
 audio_library.cc
 audio_playlist.cc
+audio_port.cc
 audio_track.cc
 audioengine.cc
-port.cc
-audio_port.cc
-midi_port.cc
-port_set.cc
-buffer.cc
-audio_buffer.cc
-midi_buffer.cc
-buffer_set.cc
-meter.cc
-amp.cc
-panner.cc
-filter.cc
 audiofilesource.cc
 audioregion.cc
 audiosource.cc
-midi_source.cc
-midi_diskstream.cc
-midi_playlist.cc
-midi_track.cc
-midi_region.cc
-midi_model.cc
-note.cc
-smf_source.cc
 auditioner.cc
+automatable.cc
 automation.cc
+automation_control.cc
 automation_event.cc
+buffer.cc
+buffer_set.cc
+bundle.cc
+chan_count.cc
 configuration.cc
 control_protocol_manager.cc
 control_protocol_search_path.cc
@@ -75,34 +54,55 @@ crossfade.cc
 curve.cc
 cycle_timer.cc
 default_click.cc
+directory_names.cc
+diskstream.cc
 enums.cc
+filename_extensions.cc
+filesystem_paths.cc
+filter.cc
+find_session.cc
 gain.cc
 gdither.cc
 globals.cc
 import.cc
-automatable.cc
-automation_control.cc
-processor.cc
-io_processor.cc
-plugin_insert.cc
-port_insert.cc
 io.cc
+io_processor.cc
+jack_port.cc
+jack_audio_port.cc
+jack_midi_port.cc
 jack_slave.cc
 ladspa_plugin.cc
 location.cc
+meter.cc
+midi_buffer.cc
+midi_diskstream.cc
+midi_model.cc
+midi_playlist.cc
+midi_port.cc
+midi_region.cc
+midi_source.cc
+midi_track.cc
+mix.cc
 mtc_slave.cc
 named_selection.cc
+note.cc
+panner.cc
 pcm_utils.cc
 playlist.cc
 playlist_factory.cc
 plugin.cc
+plugin_insert.cc
 plugin_manager.cc
+port.cc
+port_insert.cc
+port_set.cc
+processor.cc
+quantize.cc
 recent_sessions.cc
 region.cc
 region_factory.cc
-reverse.cc
 resampled_source.cc
-quantize.cc
+reverse.cc
 route.cc
 route_group.cc
 send.cc
@@ -122,14 +122,17 @@ session_timefx.cc
 session_transport.cc
 session_utils.cc
 silentfilesource.cc
+smf_source.cc
 sndfile_helpers.cc
 sndfilesource.cc
 source.cc
 source_factory.cc
+tape_file_matcher.cc
+template_utils.cc
 tempo.cc
+track.cc
 utils.cc
 version.cc
-mix.cc
 """)
 
 arch_specific_objects = [ ]
index d480eaf1938a7732279cb0b90bcffc9d96d3e8d1..c6df9e0a2f7674d170f5971036e9ef87620eab7e 100644 (file)
@@ -24,7 +24,6 @@
 #include <sigc++/signal.h>
 #include <pbd/failed_constructor.h>
 #include <ardour/ardour.h>
-#include <jack/jack.h>
 #include <ardour/port.h>
 #include <ardour/audio_buffer.h>
 
@@ -32,19 +31,9 @@ namespace ARDOUR {
 
 class AudioEngine;
 
-class AudioPort : public Port {
+class AudioPort : public virtual Port {
    public:
-       virtual ~AudioPort() { 
-               free (_port);
-       }
-
-       void cycle_start(nframes_t nframes) {
-               _buffer.set_data ((Sample*) jack_port_get_buffer (_port, nframes), nframes);
-       }
-
-       void cycle_end() {}
-
-       DataType type() const { return DataType(DataType::AUDIO); }
+       DataType type() const { return DataType::AUDIO; }
 
        Buffer& get_buffer () {
                return _buffer;
@@ -69,8 +58,8 @@ class AudioPort : public Port {
                reset_overs ();
        }
 
-       float                       peak_db() const { return _peak_db; }
-       jack_default_audio_sample_t peak()    const { return _peak; }
+       float  peak_db() const { return _peak_db; }
+       Sample peak()    const { return _peak; }
 
        uint32_t short_overs () const { return _short_overs; }
        uint32_t long_overs ()  const { return _long_overs; }
@@ -81,21 +70,21 @@ class AudioPort : public Port {
   protected:
        friend class AudioEngine;
 
-       AudioPort (jack_port_t *port);
+       AudioPort ();
        void reset ();
        
        /* engine isn't supposed to access below here */
 
        AudioBuffer _buffer;
 
-       nframes_t               _overlen;
-       jack_default_audio_sample_t  _peak;
-       float                        _peak_db;
-       uint32_t                     _short_overs;
-       uint32_t                     _long_overs;
+       nframes_t _overlen;
+       Sample    _peak;
+       float     _peak_db;
+       uint32_t  _short_overs;
+       uint32_t  _long_overs;
        
-       static nframes_t        _long_over_length;
-       static nframes_t        _short_over_length;
+       static nframes_t _long_over_length;
+       static nframes_t _short_over_length;
 };
  
 } // namespace ARDOUR
index cb5a6d72ceedd6c1a236b655727ddfb8df142365..17ba9f96149a5efbefdba445501622681e410b0a 100644 (file)
@@ -51,7 +51,7 @@ class AudioEngine : public sigc::trackable
        AudioEngine (std::string client_name);
        virtual ~AudioEngine ();
        
-       jack_client_t* jack() const { return _jack; }
+       jack_client_t* jack() const;
        bool connected() const { return _jack != 0; }
 
        bool is_realtime () const;
@@ -219,6 +219,8 @@ class AudioEngine : public sigc::trackable
 
        SerializedRCUManager<Ports> ports;
 
+       Port *register_port (DataType type, const std::string& portname, bool input);
+
        int    process_callback (nframes_t nframes);
        void   remove_all_ports ();
 
diff --git a/libs/ardour/ardour/jack_audio_port.h b/libs/ardour/ardour/jack_audio_port.h
new file mode 100644 (file)
index 0000000..8a636bb
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+    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: port.h 712 2006-07-28 01:08:57Z drobilla $
+*/
+
+#ifndef __ardour_jack_audio_port_h__
+#define __ardour_jack_audio_port_h__
+
+#include <sigc++/signal.h>
+#include <pbd/failed_constructor.h>
+#include <ardour/ardour.h>
+#include <ardour/jack_port.h>
+#include <ardour/audio_port.h>
+
+namespace ARDOUR {
+
+class AudioEngine;
+class JackAudioPort : public AudioPort, public JackPort {
+   public:
+       void cycle_start(nframes_t nframes) {
+               _buffer.set_data ((Sample*) jack_port_get_buffer (_port, nframes), nframes);
+       }
+
+       int reestablish ();
+
+  protected:
+       friend class AudioEngine;
+
+       JackAudioPort (const std::string& name, Flags flags);
+};
+} // namespace ARDOUR
+
+#endif /* __ardour_jack_audio_port_h__ */
diff --git a/libs/ardour/ardour/jack_midi_port.h b/libs/ardour/ardour/jack_midi_port.h
new file mode 100644 (file)
index 0000000..5508ae2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+    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: port.h 712 2006-07-28 01:08:57Z drobilla $
+*/
+
+#ifndef __ardour_jack_midi_port_h__
+#define __ardour_jack_midi_port_h__
+
+#include <sigc++/signal.h>
+#include <pbd/failed_constructor.h>
+#include <ardour/ardour.h>
+#include <jack/jack.h>
+#include <jack/midiport.h>
+#include <ardour/port.h>
+#include <ardour/jack_port.h>
+#include <ardour/midi_port.h>
+#include <ardour/midi_buffer.h>
+
+namespace ARDOUR {
+
+class MidiEngine;
+
+class JackMidiPort : public JackPort, public MidiPort {
+   public:
+       void cycle_start(nframes_t nframes);
+       void cycle_end();
+
+  protected:
+       friend class AudioEngine;
+
+       JackMidiPort (const std::string&, Flags);
+
+       nframes_t _nframes_this_cycle;
+};
+} // namespace ARDOUR
+
+#endif /* __ardour_jack_midi_port_h__ */
index b7730f0d1672238d679948db70e3714105290c7b..48ebf31eef0fa2983c51c2bc1f3be670584f13c3 100644 (file)
@@ -24,8 +24,6 @@
 #include <sigc++/signal.h>
 #include <pbd/failed_constructor.h>
 #include <ardour/ardour.h>
-#include <jack/jack.h>
-#include <jack/midiport.h>
 #include <ardour/port.h>
 #include <ardour/midi_buffer.h>
 
@@ -33,11 +31,11 @@ namespace ARDOUR {
 
 class MidiEngine;
 
-class MidiPort : public Port {
+class MidiPort : public virtual Port {
    public:
        virtual ~MidiPort();
        
-       DataType type() const { return DataType(DataType::MIDI); }
+       DataType type() const { return DataType::MIDI; }
 
        Buffer& get_buffer() {
                return _buffer;
@@ -47,21 +45,17 @@ class MidiPort : public Port {
                return _buffer;
        }
        
-       void cycle_start(nframes_t nframes);
-       void cycle_end();
-
        size_t capacity() { return _buffer.capacity(); }
        size_t size()     { return _buffer.size(); }
 
   protected:
        friend class AudioEngine;
 
-       MidiPort (jack_port_t *port);
+       MidiPort (nframes_t bufsize);
        
        /* engine isn't supposed to access below here */
 
        MidiBuffer     _buffer;
-       nframes_t _nframes_this_cycle;
 };
  
 } // namespace ARDOUR
index cae198758b3bb29916f31e8d2fa3570411c4f1a7..c1e502727f44cc53dc03b25d6fb6d96d95e385f0 100644 (file)
@@ -31,65 +31,39 @@ namespace ARDOUR {
 class AudioEngine;
 class Buffer;
 
-/** Abstract base for all outside ports (eg Jack ports)
+/** Abstract base for ports
  */
-class Port : public sigc::trackable {
+class Port : public virtual sigc::trackable {
    public:
-       virtual ~Port() { 
-               free (_port);
-       }
-
-       virtual DataType type() const = 0;
+       enum Flags {
+               IsInput = JackPortIsInput,
+               IsOutput = JackPortIsOutput,
+               IsPhysical = JackPortIsPhysical,
+               IsTerminal = JackPortIsTerminal,
+               CanMonitor = JackPortCanMonitor
+       };
 
-       virtual void cycle_start(nframes_t nframes) {}
-       virtual void cycle_end() {}
+       virtual ~Port() {}
 
-       virtual Buffer& get_buffer() = 0;
-       
        std::string name() const { 
                return _name;
        }
 
-       std::string short_name() { 
-               return jack_port_short_name (_port);
-       }
-       
-       int set_name (std::string str);
 
-       JackPortFlags flags() const {
+       Flags flags() const {
                return _flags;
        }
 
-       bool is_mine (jack_client_t *client) { 
-               return jack_port_is_mine (client, _port);
-       }
-
-       int connected () const {
-               return jack_port_connected (_port);
-       }
-       
-       bool connected_to (const std::string& portname) const {
-               return jack_port_connected_to (_port, portname.c_str());
-       }
-
-       const char ** get_connections () const {
-               return jack_port_get_connections (_port);
-       }
-
        bool receives_input() const {
-               return _flags & JackPortIsInput;
+               return _flags & IsInput;
        }
 
        bool sends_output () const {
                return _flags & JackPortIsOutput;
        }
-       
-       bool monitoring_input () const {
-               return jack_port_monitoring_input (_port);
-       }
 
        bool can_monitor () const {
-               return _flags & JackPortCanMonitor;
+               return _flags & CanMonitor;
        }
 
        void enable_metering() {
@@ -100,28 +74,23 @@ class Port : public sigc::trackable {
                if (_metering) { _metering--; }
        }
        
-       void ensure_monitor_input (bool yn) {
-
-#ifdef HAVE_JACK_PORT_ENSURE_MONITOR
-               jack_port_ensure_monitor (_port, yn);
-#else
-               jack_port_request_monitor(_port, yn);
-#endif
-
-       }
-
-       /*XXX completely bloody useless imho*/
-       void request_monitor_input (bool yn) {
-               jack_port_request_monitor (_port, yn);
-       }
-
-       nframes_t latency () const {
-               return jack_port_get_latency (_port);
-       }
-
-       void set_latency (nframes_t nframes) {
-               jack_port_set_latency (_port, nframes);
-       }
+       virtual DataType type() const = 0;
+       virtual void cycle_start(nframes_t nframes) {}
+       virtual void cycle_end() {}
+       virtual Buffer& get_buffer() = 0;
+       virtual std::string short_name() = 0;
+       virtual int set_name (std::string str) = 0;
+       virtual bool is_mine (jack_client_t *client) = 0;
+       virtual int reestablish () = 0;
+       virtual int connected () const = 0;
+       virtual bool connected_to (const std::string& portname) const = 0;
+       virtual const char ** get_connections () const = 0;
+       virtual bool monitoring_input () const = 0;
+       virtual void ensure_monitor_input (bool yn) = 0;
+       virtual void request_monitor_input (bool yn) = 0;
+       virtual nframes_t latency () const = 0;
+       virtual nframes_t total_latency () const = 0;
+       virtual void set_latency (nframes_t nframes) = 0;
 
        sigc::signal<void,bool> MonitorInputChanged;
        sigc::signal<void,bool> ClockSyncChanged;
@@ -129,22 +98,19 @@ class Port : public sigc::trackable {
   protected:
        friend class AudioEngine;
 
-       Port (jack_port_t *port);
-       
+       Port ();
+
+       virtual int disconnect () = 0;
+       virtual void recompute_total_latency() const = 0;
        virtual void reset ();
        
        /* engine isn't supposed to access below here */
 
-       /* cache these 3 from JACK so we can access them for reconnecting */
-       JackPortFlags _flags;
-       std::string   _type;
-       std::string   _name;
-
-       jack_port_t*  _port;
-
+       Flags _flags;
+       std::string    _type;
+       std::string    _name;
        unsigned short _metering;
-
-       bool          _last_monitor : 1;
+       bool           _last_monitor;
 };
  
 } // namespace ARDOUR
index ae64995000aa6ac0c8ff5c796b15767ad1e7978b..23c8ab8335cb520d338210eed427e6435e20dcee 100644 (file)
@@ -26,13 +26,10 @@ using namespace std;
 nframes_t AudioPort::_short_over_length = 2;
 nframes_t AudioPort::_long_over_length = 10;
 
-AudioPort::AudioPort(jack_port_t* p)
-       : Port(p)
-       , _buffer(0)
+AudioPort::AudioPort()
+       : _buffer (0)
 {
-       DataType dt(_type);
-       assert(dt == DataType::AUDIO);
-       
+       _type = DataType::AUDIO;
        reset();
 }
 
@@ -40,7 +37,7 @@ void
 AudioPort::reset()
 {
        Port::reset();
-       if (_flags & JackPortIsOutput) {
+       if (_flags & IsOutput) {
                if (_buffer.capacity() > 0) {
                        _buffer.clear();
                }
index 2a4b36f7d8cd9cb8d25e6cf5173deacb2418e14c..63a51b76c488159fd1715953f41d9d0bf8a00a2e 100644 (file)
@@ -31,8 +31,8 @@
 #include <ardour/audioengine.h>
 #include <ardour/buffer.h>
 #include <ardour/port.h>
-#include <ardour/audio_port.h>
-#include <ardour/midi_port.h>
+#include <ardour/jack_audio_port.h>
+#include <ardour/jack_midi_port.h>
 #include <ardour/session.h>
 #include <ardour/cycle_timer.h>
 #include <ardour/utils.h>
@@ -83,6 +83,7 @@ AudioEngine::AudioEngine (string client_name)
 
        start_metering_thread();
 
+       JackPort::set_engine (this);
 }
 
 AudioEngine::~AudioEngine ()
@@ -99,6 +100,12 @@ AudioEngine::~AudioEngine ()
        }
 }
 
+jack_client_t*
+AudioEngine::jack() const
+{
+       return _jack;
+}
+
 void
 _thread_init_callback (void *arg)
 {
@@ -501,89 +508,45 @@ AudioEngine::remove_session ()
 }
 
 Port *
-AudioEngine::register_input_port (DataType type, const string& portname)
+AudioEngine::register_port (DataType type, const string& portname, bool input)
 {
-       if (!_running) {
-               if (!_has_run) {
-                       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(), type.to_jack_type(), JackPortIsInput, 0);
-
-       if (p) {
+       Port* newport = 0;
 
-               Port* newport = 0;
-               
+       try {
                if (type == DataType::AUDIO)
-                       newport = new AudioPort (p);
+                       newport = new JackAudioPort (portname, (input ? Port::IsInput : Port::IsOutput));
                else if (type == DataType::MIDI)
-                       newport = new MidiPort (p);
+                       newport = new JackMidiPort (portname, (input ? Port::IsInput : Port::IsOutput));
                else
                        throw unknown_type();
-
+       
                if (newport != 0) {
                        RCUWriter<Ports> writer (ports);
                        boost::shared_ptr<Ports> ps = writer.get_copy ();
                        ps->insert (ps->begin(), newport);
                        /* writer goes out of scope, forces update */
                }
-
+       
                return newport;
+       }
 
-       } else {
+       catch (...) {
                throw PortRegistrationFailure();
        }
+}
 
-       return 0;
+Port *
+AudioEngine::register_input_port (DataType type, const string& portname)
+{
+       return register_port (type, portname, true);
 }
 
 Port *
 AudioEngine::register_output_port (DataType type, const string& portname)
 {
-       if (!_running) {
-               if (!_has_run) {
-                       fatal << _("register output port called before engine was started") << endmsg;
-                       /*NOTREACHED*/
-               } else {
-                       return 0;
-               }
-       }
-
-       jack_port_t* p = 0;
-       
-       if ((p = jack_port_register (_jack, portname.c_str(),
-                       type.to_jack_type(), JackPortIsOutput, 0)) != 0) {
-               
-               Port* newport = 0;
-               
-               if (type == DataType::AUDIO)
-                       newport = new AudioPort (p);
-               else if (type == DataType::MIDI)
-                       newport = new MidiPort (p);
-               else
-                       throw unknown_type ();
-
-               if (newport != 0) {
-                       RCUWriter<Ports> writer (ports);
-                       boost::shared_ptr<Ports> ps = writer.get_copy ();
-                       ps->insert (ps->begin(), newport);
-                       /* writer goes out of scope, forces update */
-               }
-               
-               return newport;
-               
-       } else {
-               throw PortRegistrationFailure ();
-       }
-
-       return 0;
+       return register_port (type, portname, false);
 }
 
-
 int          
 AudioEngine::unregister_port (Port& port)
 {
@@ -594,29 +557,25 @@ AudioEngine::unregister_port (Port& port)
                return 0;
        }
 
-       int ret = jack_port_unregister (_jack, port._port);
-
-       if (ret == 0) {
-
-               {
-
-                       RCUWriter<Ports> writer (ports);
-                       boost::shared_ptr<Ports> ps = writer.get_copy ();
-
-                       for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) {
-                               if ((*i) == &port) {
-                                       ps->erase (i);
-                                       break;
-                               }
+       {
+               
+               RCUWriter<Ports> writer (ports);
+               boost::shared_ptr<Ports> ps = writer.get_copy ();
+               
+               for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) {
+                       if ((*i) == &port) {
+                               remove_connections_for (port);
+                               cerr << "eraseing " << (*i)->name() << endl;
+                               delete *i;
+                               ps->erase (i);
+                               break;
                        }
-
-                       /* writer goes out of scope, forces update */
                }
-
-               remove_connections_for (port);
+               
+               /* writer goes out of scope, forces update */
        }
 
-       return ret;
+       return 0;
 }
 
 int 
@@ -693,7 +652,7 @@ AudioEngine::disconnect (Port& port)
                }
        }
 
-       int ret = jack_port_disconnect (_jack, port._port);
+       int ret = port.disconnect ();
 
        if (ret == 0) {
                remove_connections_for (port);
@@ -916,22 +875,9 @@ AudioEngine::get_nth_physical (DataType type, uint32_t n, int flag)
 ARDOUR::nframes_t
 AudioEngine::get_port_total_latency (const Port& port)
 {
-       if (!_jack) {
-               fatal << _("get_port_total_latency() called with no JACK client connection") << endmsg;
-               /*NOTREACHED*/
-       }
-
-       if (!_running) {
-               if (!_has_run) {
-                       fatal << _("get_port_total_latency() called before engine was started") << endmsg;
-                       /*NOTREACHED*/
-               } 
-       }
-
-       return jack_port_get_total_latency (_jack, port._port);
+       return port.total_latency ();
 }
 
-
 void
 AudioEngine::update_total_latency (const Port& port)
 {
@@ -947,9 +893,7 @@ AudioEngine::update_total_latency (const Port& port)
                } 
        }
 
-#ifdef HAVE_JACK_RECOMPUTE_LATENCY
-       jack_recompute_total_latency (_jack, port._port);
-#endif
+       port.recompute_total_latency ();
 }
 
 void
@@ -1025,14 +969,6 @@ AudioEngine::remove_all_ports ()
 {
        /* process lock MUST be held */
 
-       if (_jack) {
-               boost::shared_ptr<Ports> p = ports.reader();
-
-               for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-                       jack_port_unregister (_jack, (*i)->_port);
-               }
-       }
-
        {
                RCUWriter<Ports> writer (ports);
                boost::shared_ptr<Ports> ps = writer.get_copy ();
@@ -1152,31 +1088,14 @@ AudioEngine::reconnect_to_jack ()
 
        for (i = p->begin(); i != p->end(); ++i) {
 
-               /* XXX hack hack hack */
-
-               string long_name = (*i)->name();
-               string short_name;
-               
-               short_name = long_name.substr (long_name.find_last_of (':') + 1);
-
-               if (((*i)->_port = jack_port_register (_jack, short_name.c_str(), (*i)->type().to_jack_type(), (*i)->flags(), 0)) == 0) {
-                       error << string_compose (_("could not reregister %1"), (*i)->name()) << endmsg;
+               if ((*i)->reestablish ()) {
                        break;
-               } else {
-               }
-
-               (*i)->reset ();
-
-               if ((*i)->flags() & JackPortIsOutput) {
-                       (*i)->get_buffer().silence (jack_get_buffer_size (_jack), 0);
-               }
+               } 
        }
 
        if (i != p->end()) {
                /* failed */
-               for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-                       jack_port_unregister (_jack, (*i)->_port);
-               }
+               remove_all_ports ();
                return -1;
        } 
 
index bff8c18bc9a374d82f9fcb828c2fd6e1dac6d9a8..0c4ee414963fbb6f72d95a2dff59cf1c1268b2af 100644 (file)
@@ -198,6 +198,8 @@ IO::IO (Session& s, const XMLNode& node, DataType dt)
 
 IO::~IO ()
 {
+       cerr << "Deleting IO called " << _name << endl;
+
        Glib::Mutex::Lock guard (m_meter_signal_lock);
        
        Glib::Mutex::Lock lm (io_lock);
diff --git a/libs/ardour/jack_audio_port.cc b/libs/ardour/jack_audio_port.cc
new file mode 100644 (file)
index 0000000..83a6875
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+    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 <cassert>
+#include <ardour/audioengine.h>
+#include <ardour/jack_audio_port.h>
+
+using namespace ARDOUR;
+
+JackAudioPort::JackAudioPort(const std::string& name, Flags flgs)
+       : JackPort (name, DataType::AUDIO, flgs)
+{
+
+}
+
+int
+JackAudioPort::reestablish ()
+{
+       int ret = JackPort::reestablish ();
+       
+       if (ret == 0 && _flags & IsOutput) {
+               _buffer.silence (jack_get_buffer_size (engine->jack()));
+       }
+
+       return ret;
+}
diff --git a/libs/ardour/jack_midi_port.cc b/libs/ardour/jack_midi_port.cc
new file mode 100644 (file)
index 0000000..90ee933
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+    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 <cassert>
+#include <ardour/jack_midi_port.h>
+
+using namespace ARDOUR;
+JackMidiPort::JackMidiPort (const std::string& name, Flags flgs)
+       : JackPort (name, DataType::MIDI, flgs)
+       , MidiPort (4096) // FIXME FIXME FIXME Jack needs to tell us this
+       , _nframes_this_cycle(0)
+{
+}
+
+void
+JackMidiPort::cycle_start (nframes_t nframes)
+{
+       _buffer.clear();
+       assert(_buffer.size() == 0);
+
+       _nframes_this_cycle = nframes;
+
+       if (_flags & JackPortIsOutput) {
+               _buffer.silence(nframes);
+               assert(_buffer.size() == 0);
+               return;
+       }
+
+       // We're an input - copy Jack events to internal buffer
+       
+       void* jack_buffer = jack_port_get_buffer(_port, nframes);
+       const nframes_t event_count
+               = jack_midi_get_event_count(jack_buffer);
+
+       assert(event_count < _buffer.capacity());
+
+       jack_midi_event_t ev;
+
+       for (nframes_t i=0; i < event_count; ++i) {
+
+               jack_midi_event_get(&ev, jack_buffer, i);
+
+               _buffer.push_back(ev);
+       }
+
+       assert(_buffer.size() == event_count);
+
+       //if (_buffer.size() > 0)
+       //      cerr << "MIDIPort got " << event_count << " events." << endl;
+}
+
+void
+JackMidiPort::cycle_end()
+{
+       if (_flags & JackPortIsInput) {
+               _nframes_this_cycle = 0;
+               return;
+       }
+
+       // We're an output - copy events from internal buffer to Jack buffer
+       
+       void* jack_buffer = jack_port_get_buffer(_port, _nframes_this_cycle);
+
+       //const nframes_t event_count = _buffer.size();
+       //if (event_count > 0)
+       //      cerr << "MIDIPort writing " << event_count << " events." << endl;
+
+       jack_midi_clear_buffer(jack_buffer);
+
+       for (MidiBuffer::iterator i = _buffer.begin(); i != _buffer.end(); ++i) {
+               const MidiEvent& ev = *i;
+               // event times should be frames, relative to cycle start
+               assert(ev.time() >= 0);
+               assert(ev.time() < _nframes_this_cycle);
+               jack_midi_event_write(jack_buffer, (jack_nframes_t)ev.time(), ev.buffer(), ev.size());
+       }
+       
+       _nframes_this_cycle = 0;
+}
diff --git a/libs/ardour/jack_port.cc b/libs/ardour/jack_port.cc
new file mode 100644 (file)
index 0000000..7f56e39
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+    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
+    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 <ardour/jack_port.h>
+#include <ardour/audioengine.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+using namespace std;
+
+AudioEngine* JackPort::engine = 0;
+
+JackPort::JackPort (const std::string& name, DataType type, Flags flgs) 
+       : _port (0)
+{
+       _port = jack_port_register (engine->jack(), name.c_str(), type.to_jack_type(), flgs, 0);
+
+       if (_port == 0) {
+               throw failed_constructor();
+       }
+       
+       _flags = flgs;
+       _type  = type;
+       _name = jack_port_name (_port);
+}
+
+JackPort::~JackPort ()
+{
+       cerr << "deleting jack port " << _name << endl;
+
+       jack_port_unregister (engine->jack(), _port);
+}
+
+int 
+JackPort::set_name (string str)
+{
+       int ret;
+
+       if ((ret = jack_port_set_name (_port, str.c_str())) == 0) {
+               _name = str;
+       }
+       
+       return ret;
+}
+
+int
+JackPort::disconnect ()
+{
+       return jack_port_disconnect (engine->jack(), _port);
+}      
+
+void
+JackPort::set_engine (AudioEngine* e)
+{
+       engine = e;
+}
+
+nframes_t
+JackPort::total_latency () const
+{
+       return jack_port_get_total_latency (engine->jack(), _port);
+}
+
+int
+JackPort::reestablish ()
+{
+       string short_name;
+       
+       short_name = _name.substr (_name.find_last_of (':') + 1);
+
+       _port = jack_port_register (engine->jack(), short_name.c_str(), type().to_jack_type(), _flags, 0);
+
+       if (_port == 0) {
+               error << string_compose (_("could not reregister %1"), _name) << endmsg;
+               return -1;
+       }
+
+       reset ();
+       
+
+       return 0;
+}
+
+void
+JackPort::recompute_total_latency () const
+{
+#ifdef HAVE_JACK_RECOMPUTE_LATENCY
+       jack_recompute_total_latency (engine->jack(), _port);
+#endif
+}
+
index 3f03cfe8802f512fa211f75dd94326e789b22417..df4ab190083d370ade906b8f74721e51a5efed1a 100644 (file)
 using namespace ARDOUR;
 using namespace std;
 
-MidiPort::MidiPort(jack_port_t* p)
-       : Port(p)
-       , _buffer(4096) // FIXME FIXME FIXME Jack needs to tell us this
-       , _nframes_this_cycle(0)
+MidiPort::MidiPort (nframes_t bufsize)
+       : _buffer (bufsize) 
 {
-       DataType dt(_type);
-       assert(dt == DataType::MIDI);
-
+       _type = DataType::MIDI;
        reset();
 
 
 }
 
-
 MidiPort::~MidiPort()
 {
 }
 
-void
-MidiPort::cycle_start (nframes_t nframes)
-{
-       _buffer.clear();
-       assert(_buffer.size() == 0);
-
-       _nframes_this_cycle = nframes;
-
-       if (_flags & JackPortIsOutput) {
-               _buffer.silence(nframes);
-               assert(_buffer.size() == 0);
-               return;
-       }
-
-       // We're an input - copy Jack events to internal buffer
-       
-       void* jack_buffer = jack_port_get_buffer(_port, nframes);
-
-       const nframes_t event_count
-               = jack_midi_get_event_count(jack_buffer);
-
-       assert(event_count < _buffer.capacity());
-
-       jack_midi_event_t ev;
-
-       for (nframes_t i=0; i < event_count; ++i) {
-
-               jack_midi_event_get(&ev, jack_buffer, i);
-
-               _buffer.push_back(ev);
-       }
-
-       assert(_buffer.size() == event_count);
-
-       //if (_buffer.size() > 0)
-       //      cerr << "MIDIPort got " << event_count << " events." << endl;
-}
-
-void
-MidiPort::cycle_end()
-{
-       if (_flags & JackPortIsInput) {
-               _nframes_this_cycle = 0;
-               return;
-       }
-
-       // We're an output - copy events from internal buffer to Jack buffer
-       
-       void* jack_buffer = jack_port_get_buffer(_port, _nframes_this_cycle);
-
-       //const nframes_t event_count = _buffer.size();
-       //if (event_count > 0)
-       //      cerr << "MIDIPort writing " << event_count << " events." << endl;
-
-       jack_midi_clear_buffer(jack_buffer);
-
-       for (MidiBuffer::iterator i = _buffer.begin(); i != _buffer.end(); ++i) {
-               const MidiEvent& ev = *i;
-               // event times should be frames, relative to cycle start
-               assert(ev.time() >= 0);
-               assert(ev.time() < _nframes_this_cycle);
-               jack_midi_event_write(jack_buffer, (jack_nframes_t)ev.time(), ev.buffer(), ev.size());
-       }
-       
-       _nframes_this_cycle = 0;
-}
index d9c93c250b64a8cdee8b9d311bb83dfe933c58d6..bfc1eaf279d1efdadf7288c9a562a7deffd90658 100644 (file)
 using namespace ARDOUR;
 using namespace std;
 
-Port::Port (jack_port_t *p) 
-       : _port (p)
-       , _metering(0)
-       , _last_monitor(false)
+Port::Port ()
+       : _metering (0)
+       , _last_monitor (false)
 {
-       if (_port == 0) {
-               throw failed_constructor();
-       }
-       
-       _flags = JackPortFlags (jack_port_flags (_port));
-       _type  = jack_port_type (_port); 
-       _name = jack_port_name (_port);
-
-       reset ();
 }
 
 void
@@ -43,17 +33,3 @@ Port::reset ()
 {
        _last_monitor = false;
 }
-
-int 
-Port::set_name (string str)
-{
-       int ret;
-
-       if ((ret = jack_port_set_name (_port, str.c_str())) == 0) {
-               _name = str;
-       }
-       
-       return ret;
-}
-
-       
index abd8a0abba9258f972e017b980556a3588951346..1382fa3f0aefe748281396120a4a98b6d981ea45 100644 (file)
@@ -2089,13 +2089,14 @@ Session::remove_route (shared_ptr<Route> route)
 
        find_current_end ();
        
+       // We need to disconnect the routes inputs and outputs 
+
+       route->disconnect_inputs (0);
+       route->disconnect_outputs (0);
+       
        update_latency_compensation (false, false);
        set_dirty();
 
-       // We need to disconnect the routes inputs and outputs 
-       route->disconnect_inputs(NULL);
-       route->disconnect_outputs(NULL);
-       
        /* get rid of it from the dead wood collection in the route list manager */
 
        /* XXX i think this is unsafe as it currently stands, but i am not sure. (pd, october 2nd, 2006) */
@@ -4240,3 +4241,4 @@ Session::foreach_bundle (sigc::slot<void, boost::shared_ptr<Bundle> > sl)
                sl (*i);
        }
 }
+
index d513dfc7625ac298b8dcb34208d2d32de86c7833..feaabd97ff10668b595daff3be0dc1c4f0a5d98a 100644 (file)
@@ -54,8 +54,6 @@ 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'],
diff --git a/libs/pbd/boost-debug/shared_ptr.hpp b/libs/pbd/boost-debug/shared_ptr.hpp
new file mode 100644 (file)
index 0000000..506d11b
--- /dev/null
@@ -0,0 +1,491 @@
+#define DEBUG_SHARED_PTR
+#ifndef DEBUG_SHARED_PTR
+
+#include <boost/shared_ptr.hpp>
+
+#else
+
+#include <pbd/stacktrace.h>
+
+#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
+#define BOOST_SHARED_PTR_HPP_INCLUDED
+
+//
+//  shared_ptr.hpp
+//
+//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov
+//
+//  Distributed under the Boost Software License, Version 1.0. (See
+//  accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt)
+//
+//  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
+//
+
+#include <pbd/stacktrace.h>
+
+#include <boost/config.hpp>   // for broken compiler workarounds
+
+#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
+#include <boost/detail/shared_ptr_nmt.hpp>
+#else
+
+#include <boost/assert.hpp>
+#include <boost/checked_delete.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/detail/shared_count.hpp>
+#include <boost/detail/workaround.hpp>
+
+#include <memory>               // for std::auto_ptr
+#include <algorithm>            // for std::swap
+#include <functional>           // for std::less
+#include <typeinfo>             // for std::bad_cast
+#include <iosfwd>               // for std::basic_ostream
+
+#ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash
+# pragma warning(push)
+# pragma warning(disable:4284) // odd return type for operator->
+#endif
+
+namespace boost
+{
+
+template<class T> class weak_ptr;
+template<class T> class enable_shared_from_this;
+
+namespace detail
+{
+
+struct static_cast_tag {};
+struct const_cast_tag {};
+struct dynamic_cast_tag {};
+struct polymorphic_cast_tag {};
+
+template<class T> struct shared_ptr_traits
+{
+    typedef T & reference;
+};
+
+template<> struct shared_ptr_traits<void>
+{
+    typedef void reference;
+};
+
+#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
+
+template<> struct shared_ptr_traits<void const>
+{
+    typedef void reference;
+};
+
+template<> struct shared_ptr_traits<void volatile>
+{
+    typedef void reference;
+};
+
+template<> struct shared_ptr_traits<void const volatile>
+{
+    typedef void reference;
+};
+
+#endif
+
+// enable_shared_from_this support
+
+template<class T, class Y> void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this<T> const * pe, Y const * px )
+{
+    if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
+}
+
+inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
+{
+}
+
+} // namespace detail
+
+
+//
+//  shared_ptr
+//
+//  An enhanced relative of scoped_ptr with reference counted copy semantics.
+//  The object pointed to is deleted when the last shared_ptr pointing to it
+//  is destroyed or reset.
+//
+
+template<class T> class shared_ptr
+{
+private:
+
+    // Borland 5.5.1 specific workaround
+    typedef shared_ptr<T> this_type;
+
+public:
+
+    typedef T element_type;
+    typedef T value_type;
+    typedef T * pointer;
+    typedef typename detail::shared_ptr_traits<T>::reference reference;
+
+    shared_ptr(): px(0), pn() // never throws in 1.30+
+    {
+    }
+
+    template<class Y>
+    explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
+    {
+        detail::sp_enable_shared_from_this( pn, p, p );
+    }
+
+    //
+    // Requirements: D's copy constructor must not throw
+    //
+    // shared_ptr will release p by calling d(p)
+    //
+
+    template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
+    {
+        detail::sp_enable_shared_from_this( pn, p, p );
+    }
+
+//  generated copy constructor, assignment, destructor are fine...
+
+//  except that Borland C++ has a bug, and g++ with -Wsynth warns
+#if defined(__BORLANDC__) || defined(__GNUC__)
+
+    shared_ptr & operator=(shared_ptr const & r) // never throws
+    {
+        px = r.px;
+        pn = r.pn; // shared_count::op= doesn't throw
+        return *this;
+    }
+
+#endif
+
+    template<class Y>
+    explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
+    {
+        // it is now safe to copy r.px, as pn(r.pn) did not throw
+        px = r.px;
+    }
+
+    template<class Y>
+    shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
+    {
+    }
+
+    template<class Y>
+    shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
+    {
+    }
+
+    template<class Y>
+    shared_ptr(shared_ptr<Y> const & r, detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
+    {
+    }
+
+    template<class Y>
+    shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
+    {
+        if(px == 0) // need to allocate new counter -- the cast failed
+        {
+            pn = detail::shared_count();
+        }
+    }
+
+    template<class Y>
+    shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
+    {
+        if(px == 0)
+        {
+            boost::throw_exception(std::bad_cast());
+        }
+    }
+
+#ifndef BOOST_NO_AUTO_PTR
+
+    template<class Y>
+    explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
+    {
+        Y * tmp = r.get();
+        pn = detail::shared_count(r);
+        detail::sp_enable_shared_from_this( pn, tmp, tmp );
+    }
+
+#endif
+
+#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
+
+    template<class Y>
+    shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
+    {
+        px = r.px;
+        pn = r.pn; // shared_count::op= doesn't throw
+        return *this;
+    }
+
+#endif
+
+#ifndef BOOST_NO_AUTO_PTR
+
+    template<class Y>
+    shared_ptr & operator=(std::auto_ptr<Y> & r)
+    {
+        this_type(r).swap(*this);
+        return *this;
+    }
+
+#endif
+
+    void reset() // never throws in 1.30+
+    {
+        this_type().swap(*this);
+    }
+
+    template<class Y> void reset(Y * p) // Y must be complete
+    {
+        BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
+        this_type(p).swap(*this);
+    }
+
+    template<class Y, class D> void reset(Y * p, D d)
+    {
+        this_type(p, d).swap(*this);
+    }
+
+    reference operator* () const // never throws
+    {
+        BOOST_ASSERT(px != 0);
+        return *px;
+    }
+
+    T * operator-> () const // never throws
+    {
+        BOOST_ASSERT(px != 0);
+        return px;
+    }
+    
+    T * get() const // never throws
+    {
+        return px;
+    }
+
+    // implicit conversion to "bool"
+
+#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
+
+    operator bool () const
+    {
+        return px != 0;
+    }
+
+#elif \
+    ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \
+    ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) )
+
+    typedef T * (this_type::*unspecified_bool_type)() const;
+    
+    operator unspecified_bool_type() const // never throws
+    {
+        return px == 0? 0: &this_type::get;
+    }
+
+#else 
+
+    typedef T * this_type::*unspecified_bool_type;
+
+    operator unspecified_bool_type() const // never throws
+    {
+        return px == 0? 0: &this_type::px;
+    }
+
+#endif
+
+    // operator! is redundant, but some compilers need it
+
+    bool operator! () const // never throws
+    {
+        return px == 0;
+    }
+
+    bool unique() const // never throws
+    {
+        return pn.unique();
+    }
+
+    long use_count() const // never throws
+    {
+        return pn.use_count();
+    }
+
+    void swap(shared_ptr<T> & other) // never throws
+    {
+        std::swap(px, other.px);
+        pn.swap(other.pn);
+    }
+
+    template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
+    {
+        return pn < rhs.pn;
+    }
+
+    void * _internal_get_deleter(std::type_info const & ti) const
+    {
+        return pn.get_deleter(ti);
+    }
+
+// Tasteless as this may seem, making all members public allows member templates
+// to work in the absence of member template friends. (Matthew Langston)
+
+#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+
+private:
+
+    template<class Y> friend class shared_ptr;
+    template<class Y> friend class weak_ptr;
+
+#endif
+
+    T * px;                     // contained pointer
+    detail::shared_count pn;    // reference counter
+    typename PBD::thing_with_backtrace<T> bt; // backtrace
+
+};  // shared_ptr
+
+template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
+{
+    return a.get() == b.get();
+}
+
+template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
+{
+    return a.get() != b.get();
+}
+
+#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
+
+// Resolve the ambiguity between our op!= and the one in rel_ops
+
+template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
+{
+    return a.get() != b.get();
+}
+
+#endif
+
+template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
+{
+    return a._internal_less(b);
+}
+
+template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
+{
+    a.swap(b);
+}
+
+template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
+{
+    return shared_ptr<T>(r, detail::static_cast_tag());
+}
+
+template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
+{
+    return shared_ptr<T>(r, detail::const_cast_tag());
+}
+
+template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
+{
+    return shared_ptr<T>(r, detail::dynamic_cast_tag());
+}
+
+// shared_*_cast names are deprecated. Use *_pointer_cast instead.
+
+template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
+{
+    return shared_ptr<T>(r, detail::static_cast_tag());
+}
+
+template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
+{
+    return shared_ptr<T>(r, detail::dynamic_cast_tag());
+}
+
+template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
+{
+    return shared_ptr<T>(r, detail::polymorphic_cast_tag());
+}
+
+template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
+{
+    BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
+    return shared_static_cast<T>(r);
+}
+
+// get_pointer() enables boost::mem_fn to recognize shared_ptr
+
+template<class T> inline T * get_pointer(shared_ptr<T> const & p)
+{
+    return p.get();
+}
+
+// operator<<
+
+#if defined(__GNUC__) &&  (__GNUC__ < 3)
+
+template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
+{
+    os << p.get();
+    return os;
+}
+
+#else
+
+# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT)
+// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
+using std::basic_ostream;
+template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
+# else
+template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
+# endif 
+{
+    os << p.get();
+    return os;
+}
+
+#endif
+
+// get_deleter (experimental)
+
+#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
+    ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
+    ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
+
+// g++ 2.9x doesn't allow static_cast<X const *>(void *)
+// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
+
+template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
+{
+    void const * q = p._internal_get_deleter(typeid(D));
+    return const_cast<D *>(static_cast<D const *>(q));
+}
+
+#else
+
+template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
+{
+    return static_cast<D *>(p._internal_get_deleter(typeid(D)));
+}
+
+#endif
+
+} // namespace boost
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif    
+
+#endif  // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
+
+#endif  // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
+
+#endif // #ifndef DEBUG_SHARED_PTR
index c6da6ed79dbe69f85ceb73c268510542f449a95c..0a349dcaebbcdb67c4c99abbe3c3e9525eb39d9a 100644 (file)
 #ifndef __libpbd_stacktrace_h__
 #define __libpbd_stacktrace_h__
 
+#include <iostream>
 #include <ostream>
+#include <glibmm/thread.h>
+#include <list>
 
 namespace PBD {
        void stacktrace (std::ostream& out, int levels = 0);
-}
+       void trace_twb();
+
+#ifdef HAVE_EXECINFO
+#include <execinfo.h>
+#include <stdlib.h>
+#endif
+
+template<typename T>
+class thing_with_backtrace 
+{
+  public:
+    thing_with_backtrace () {
+           trace_twb();
+#ifdef HAVE_EXECINFO
+           allocation_backtrace = new void*[50];
+           allocation_backtrace_size = backtrace (allocation_backtrace, 50);
+#else 
+           allocation_backtrace_size = 0;
+#endif
+           Glib::Mutex::Lock lm (all_mutex);
+           all.push_back (this);
+    }
+
+    thing_with_backtrace (const thing_with_backtrace<T>& other) {
+           trace_twb();
+#ifdef HAVE_EXECINFO
+           allocation_backtrace = new void*[50];
+           allocation_backtrace_size = backtrace (allocation_backtrace, 50);
+#else 
+           allocation_backtrace_size = 0;
+#endif
+           Glib::Mutex::Lock lm (all_mutex);
+           all.push_back (this);
+    }
+
+    ~thing_with_backtrace() { 
+           if (allocation_backtrace_size) {
+                   delete [] allocation_backtrace;
+           }
+           Glib::Mutex::Lock lm (all_mutex);
+           all.remove (this);
+    }
+
+    thing_with_backtrace<T>& operator= (const thing_with_backtrace<T>& other) {
+           /* no copyable members */
+           return *this;
+    }
+
+    static void peek_a_boo (std::ostream& stream) {
+#ifdef HAVE_EXECINFO
+           typename std::list<thing_with_backtrace<T>*>::iterator x;
+           for (x = all.begin(); x != all.end(); ++x) {
+                   char **strings;
+                   size_t i;
+                   
+                   strings = backtrace_symbols ((*x)->allocation_backtrace, (*x)->allocation_backtrace_size);
+                   
+                   if (strings) {
+                           stream << "--- ALLOCATED SHARED_PTR @ " << (*x) << std::endl;
+                           for (i = 0; i < (*x)->allocation_backtrace_size && i < 50U; i++) {
+                                   stream << strings[i] << std::endl;
+                           }
+                           free (strings);
+                   }
+           }
+#else
+           stream << "execinfo not defined for this platform" << std::endl;
+#endif
+    }
+
+private:
+    void** allocation_backtrace;
+    int allocation_backtrace_size;
+    static std::list<thing_with_backtrace<T>* > all;
+    static Glib::StaticMutex all_mutex;
+};
+
+template<typename T> std::list<PBD::thing_with_backtrace<T> *> PBD::thing_with_backtrace<T>::all;
+template<typename T> Glib::StaticMutex PBD::thing_with_backtrace<T>::all_mutex = GLIBMM_STATIC_MUTEX_INIT;
+
+} // namespace PBD
+
+
 
 #endif /* __libpbd_stacktrace_h__ */
index 375fc1eecd9de484214976a21f6456da42b77aab..dc9a5e18abca108db3a2c314680cfa7d566b2041 100644 (file)
 #include <pbd/stacktrace.h>
 #include <iostream>
 
+void
+PBD::trace_twb ()
+{
+}
+
 /* Obtain a backtrace and print it to stdout. */
 
 #ifdef HAVE_EXECINFO