Merge libs/ardour and gtk2_ardour with 2.0-ongoing R2837.
authorDavid Robillard <d@drobilla.net>
Thu, 10 Jan 2008 21:20:59 +0000 (21:20 +0000)
committerDavid Robillard <d@drobilla.net>
Thu, 10 Jan 2008 21:20:59 +0000 (21:20 +0000)
git-svn-id: svn://localhost/ardour2/trunk@2883 d708f5d6-7413-0410-9779-e7cbd77b26cf

170 files changed:
SConstruct
gtk2_ardour/SConscript
gtk2_ardour/actions.cc
gtk2_ardour/add_route_dialog.cc
gtk2_ardour/ardev_common.sh.in
gtk2_ardour/ardour-sae-ansi.bindings.in [new file with mode: 0644]
gtk2_ardour/ardour-sae-de.bindings.in [new file with mode: 0644]
gtk2_ardour/ardour-sae.menus
gtk2_ardour/ardour.bindings.in
gtk2_ardour/ardour.menus
gtk2_ardour/ardour2_ui_default.conf
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui2.cc
gtk2_ardour/ardour_ui_dependents.cc
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/ardour_ui_options.cc
gtk2_ardour/au_pluginui.cc [deleted file]
gtk2_ardour/au_pluginui.h
gtk2_ardour/au_pluginui.mm [new file with mode: 0644]
gtk2_ardour/audio_clock.cc
gtk2_ardour/audio_clock.h
gtk2_ardour/audio_region_view.cc
gtk2_ardour/audio_region_view.h
gtk2_ardour/audio_streamview.cc
gtk2_ardour/audio_time_axis.cc
gtk2_ardour/canvas_vars.h
gtk2_ardour/cocoacarbon.mm [new file with mode: 0644]
gtk2_ardour/crossfade_edit.cc
gtk2_ardour/editing_syms.h
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_actions.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_region_list.cc
gtk2_ardour/editor_route_list.cc
gtk2_ardour/editor_rulers.cc
gtk2_ardour/editor_selection.cc
gtk2_ardour/editor_tempodisplay.cc
gtk2_ardour/editor_timefx.cc
gtk2_ardour/evtest.cc [new file with mode: 0644]
gtk2_ardour/export_dialog.cc
gtk2_ardour/gain_meter.cc
gtk2_ardour/gain_meter.h
gtk2_ardour/generic_pluginui.cc [new file with mode: 0644]
gtk2_ardour/icons/sae.png [new file with mode: 0644]
gtk2_ardour/keyboard.cc
gtk2_ardour/keyboard.h
gtk2_ardour/keyeditor.cc
gtk2_ardour/ladspa_pluginui.cc [deleted file]
gtk2_ardour/level_meter.cc
gtk2_ardour/location_ui.cc
gtk2_ardour/location_ui.h
gtk2_ardour/main.cc
gtk2_ardour/marker.cc
gtk2_ardour/marker.h
gtk2_ardour/mixer_strip.cc
gtk2_ardour/mixer_ui.cc
gtk2_ardour/new_session_dialog.cc
gtk2_ardour/new_session_dialog.h
gtk2_ardour/option_editor.cc
gtk2_ardour/opts.cc
gtk2_ardour/opts.h
gtk2_ardour/panner2d.cc
gtk2_ardour/plugin_selector.cc
gtk2_ardour/plugin_selector.h
gtk2_ardour/plugin_ui.cc
gtk2_ardour/plugin_ui.h
gtk2_ardour/po/de_DE.po
gtk2_ardour/processor_box.cc
gtk2_ardour/public_editor.h
gtk2_ardour/region_view.cc
gtk2_ardour/route_params_ui.cc
gtk2_ardour/route_time_axis.cc
gtk2_ardour/route_time_axis.h
gtk2_ardour/route_ui.cc
gtk2_ardour/selectable.h
gtk2_ardour/selection.cc
gtk2_ardour/selection.h
gtk2_ardour/sfdb_ui.cc
gtk2_ardour/streamview.cc
gtk2_ardour/sync-menu.c
gtk2_ardour/tape_region_view.cc
gtk2_ardour/tempo_dialog.cc
gtk2_ardour/tempo_dialog.h
gtk2_ardour/time_axis_view.cc
gtk2_ardour/time_axis_view_item.h
gtk2_ardour/ui_config.cc
gtk2_ardour/utils.cc
gtk2_ardour/vst_pluginui.cc
gtk2_ardour/x11.cc
libs/ardour/SConscript
libs/ardour/ardour/ardour.h
libs/ardour/ardour/audio_buffer.h
libs/ardour/ardour/audio_unit.h
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/audioregion.h
libs/ardour/ardour/audiosource.h
libs/ardour/ardour/configuration_vars.h
libs/ardour/ardour/crossfade.h
libs/ardour/ardour/ladspa_plugin.h
libs/ardour/ardour/location.h
libs/ardour/ardour/pitch.h [new file with mode: 0644]
libs/ardour/ardour/playlist.h
libs/ardour/ardour/plugin.h
libs/ardour/ardour/plugin_manager.h
libs/ardour/ardour/rb_effect.h [new file with mode: 0644]
libs/ardour/ardour/region.h
libs/ardour/ardour/route.h
libs/ardour/ardour/session.h
libs/ardour/ardour/silentfilesource.h
libs/ardour/ardour/slave.h
libs/ardour/ardour/sndfile_helpers.h
libs/ardour/ardour/source.h
libs/ardour/ardour/stretch.h
libs/ardour/ardour/tempo.h
libs/ardour/ardour/types.h
libs/ardour/ardour/vst_plugin.h
libs/ardour/audio_buffer.cc
libs/ardour/audio_diskstream.cc
libs/ardour/audio_playlist.cc
libs/ardour/audio_port.cc
libs/ardour/audio_unit.cc
libs/ardour/audioengine.cc
libs/ardour/audiofilesource.cc
libs/ardour/audioregion.cc
libs/ardour/audiosource.cc
libs/ardour/auditioner.cc
libs/ardour/crossfade.cc
libs/ardour/enums.cc
libs/ardour/import.cc
libs/ardour/io.cc
libs/ardour/jack_audio_port.cc
libs/ardour/jack_midi_port.cc
libs/ardour/ladspa_plugin.cc
libs/ardour/meter.cc
libs/ardour/midi_buffer.cc
libs/ardour/midi_port.cc
libs/ardour/playlist.cc
libs/ardour/plugin.cc
libs/ardour/plugin_insert.cc
libs/ardour/plugin_manager.cc
libs/ardour/rb_effect.cc [new file with mode: 0644]
libs/ardour/region.cc
libs/ardour/route.cc
libs/ardour/session.cc
libs/ardour/session_butler.cc
libs/ardour/session_events.cc
libs/ardour/session_export.cc
libs/ardour/session_process.cc
libs/ardour/session_state.cc
libs/ardour/session_transport.cc
libs/ardour/smf_source.cc
libs/ardour/sndfile_helpers.cc
libs/ardour/source_factory.cc
libs/ardour/st_pitch.cc [new file with mode: 0644]
libs/ardour/st_stretch.cc [new file with mode: 0644]
libs/ardour/stretch.cc [deleted file]
libs/ardour/tempo.cc
libs/ardour/vst_plugin.cc

index 2944040f50a6ed7af770d3a709092f6143cebc2a..a1a3dbbf80a055316090a95885210f864e69b8db 100644 (file)
@@ -16,7 +16,7 @@ import SCons.Node.FS
 SConsignFile()
 EnsureSConsVersion(0, 96)
 
-ardour_version = '3.0'
+ardour_version = '2.1'
 
 subst_dict = { }
 
@@ -28,26 +28,26 @@ opts = Options('scache.conf')
 opts.AddOptions(
     ('ARCH', 'Set architecture-specific compilation flags by hand (all flags as 1 argument)',''),
     BoolOption('AUDIOUNITS', 'Compile with Apple\'s AudioUnit library. (experimental)', 0),
-    BoolOption('CMT', 'Compile with support for CMT Additions', 1),
     BoolOption('COREAUDIO', 'Compile with Apple\'s CoreAudio library', 0),
     BoolOption('GTKOSX', 'Compile for use with GTK-OSX, not GTK-X11', 0),
-    BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 1),
+    BoolOption('NATIVE_OSX_KEYS', 'Build key bindings file that matches OS X conventions', 0),
+    BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 0),
     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('GPROFILE', 'Compile with support for gprofile (Developers only)', 0),
     BoolOption('LIBLO', 'Compile with support for liblo library', 1),
     BoolOption('NLS', 'Set to turn on i18n support', 1),
     PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
     BoolOption('SURFACES', 'Build support for control surfaces', 1),
     BoolOption('SYSLIBS', 'USE AT YOUR OWN RISK: CANCELS ALL SUPPORT FROM ARDOUR AUTHORS: Use existing system versions of various libraries instead of internal ones', 0),
-    BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1),
     BoolOption('UNIVERSAL', 'Compile as universal binary.  Requires that external libraries are already universal.', 0),
     BoolOption('VERSIONED', 'Add revision information to ardour/gtk executable name inside the build directory', 0),
     BoolOption('VST', 'Compile with support for VST', 0),
+    BoolOption('GPROFILE', 'Compile with support for gprofile (Developers only)', 0),
+    BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1)
 )
 
 #----------------------------------------------------------------------
@@ -65,6 +65,7 @@ class LibraryInfo(Environment):
             self.Append (LIBPATH = other.get ('LIBPATH', []))
             self.Append (CPPPATH = other.get('CPPPATH', []))
             self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
+            self.Append (CCFLAGS = other.get('CCFLAGS', []))
        self.Replace(LIBPATH = list(Set(self.get('LIBPATH', []))))
        self.Replace(CPPPATH = list(Set(self.get('CPPPATH',[]))))
         #doing LINKFLAGS breaks -framework
@@ -402,6 +403,29 @@ else:
         os.remove('.personal_use_only')
 
 
+####################
+# push environment
+####################
+
+def pushEnvironment(context):
+    if os.environ.has_key('PATH'):
+       context.Append(PATH = os.environ['PATH'])
+       
+    if os.environ.has_key('PKG_CONFIG_PATH'):
+       context.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
+           
+    if os.environ.has_key('CC'):
+       context['CC'] = os.environ['CC']
+               
+    if os.environ.has_key('CXX'):
+       context['CXX'] = os.environ['CXX']
+
+    if os.environ.has_key('DISTCC_HOSTS'):
+       context['ENV']['DISTCC_HOSTS'] = os.environ['DISTCC_HOSTS']
+       context['ENV']['HOME'] = os.environ['HOME']
+
+pushEnvironment (env)
+
 #######################
 # Dependency Checking #
 #######################
@@ -415,7 +439,7 @@ deps = \
        'samplerate'           : '0.1.0',
        'raptor'               : '1.4.2',
        'lrdf'                 : '0.4.0',
-       'jack'                 : '0.105.0',
+       'jack'                 : '0.101.1',
        'libgnomecanvas-2.0'   : '2.0'
 }
 
@@ -424,16 +448,22 @@ def DependenciesRequiredMessage():
        print 'Please consult http://ardour.org/building for more information'
 
 def CheckPKGConfig(context, version):
-     context.Message( 'Checking for pkg-config version >= %s... ' %version )
-     ret = context.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0]
-     context.Result( ret )
-     return ret
+    context.Message( 'Checking for pkg-config version >= %s... ' %version )
+    ret = context.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0]
+    context.Result( ret )
+    return ret
 
 def CheckPKGVersion(context, name, version):
-     context.Message( 'Checking for %s... ' % name )
-     ret = context.TryAction('pkg-config --atleast-version=%s %s' %(version,name) )[0]
-     context.Result( ret )
-     return ret
+    context.Message( 'Checking for %s... ' % name )
+    ret = context.TryAction('pkg-config --atleast-version=%s %s' %(version,name) )[0]
+    context.Result( ret )
+    return ret
+
+def CheckPKGExists(context, name):
+    context.Message ('Checking for %s...' % name)
+    ret = context.TryAction('pkg-config --exists %s' % name)[0]
+    context.Result (ret)
+    return ret
 
 conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
                                        'CheckPKGVersion' : CheckPKGVersion })
@@ -473,27 +503,30 @@ libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
 libraries['samplerate'] = LibraryInfo()
 libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
 
-libraries['rubberband'] = LibraryInfo()
-#
-# chris cannam's rubberband has not yet been released
-# 
-if os.path.exists ('libs/rubberband'):
-    libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
-                                           LIBPATH='#libs/rubberband/lib',
-                                           CPPPATH='#libs/rubberband/src',
-                                           CXXFLAGS='-DUSE_RUBBERBAND')
+conf = env.Configure (custom_tests = { 'CheckPKGExists' : CheckPKGExists } )
+
+if conf.CheckPKGExists ('fftw3f'):
+    libraries['fftw3f'] = LibraryInfo()
+    libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
+
+if conf.CheckPKGExists ('fftw3'):
+    libraries['fftw3'] = LibraryInfo()
+    libraries['fftw3'].ParseConfig('pkg-config --cflags --libs fftw3')
+
+env = conf.Finish ()
 
 if env['FFT_ANALYSIS']:
-       libraries['fftw3f'] = LibraryInfo()
-       libraries['fftw3f'].ParseConfig('pkg-config --cflags --libs fftw3f')
         #
         # Check for fftw3 header as well as the library
-        conf = Configure (libraries['fftw3f'])
-        if conf.CheckHeader ('fftw3.h') == False:
-                print "FFT Analysis cannot be compiled without the FFTW3 headers, which don't seem to be installed"
-                sys.exit (1)
-        libraries['fftw3f'] = conf.Finish();
+        #
 
+        conf = Configure(libraries['fftw3'])
+
+        if conf.CheckHeader ('fftw3.h') == False:
+            print ('FFT Analysis cannot be compiled without the FFTW3 headers, which do not seem to be installed')
+            sys.exit (1)            
+        conf.Finish()
+        
 libraries['jack'] = LibraryInfo()
 libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
 
@@ -515,12 +548,6 @@ libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
 libraries['pango'] = LibraryInfo()
 libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
 
-libraries['cairo'] = LibraryInfo()
-libraries['cairo'].ParseConfig ('pkg-config --cflags --libs cairo')
-
-libraries['gtk2-unix-print'] = LibraryInfo()
-libraries['gtk2-unix-print'].ParseConfig ('pkg-config --cflags --libs gtk+-unix-print-2.0')
-
 libraries['libgnomecanvas2'] = LibraryInfo()
 libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
 
@@ -541,7 +568,7 @@ libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext
 
 # SCons should really do this for us
 
-conf = Configure (env)
+conf = env.Configure ()
 
 have_cxx = conf.TryAction (Action (str(env['CXX']) + ' --version'))
 if have_cxx[0] != 1:
@@ -559,9 +586,9 @@ env = conf.Finish()
 
 opt_flags = []
 if env['GPROFILE'] == 1:
-    debug_flags = [ '-O0', '-g', '-pg' ]
+    debug_flags = [ '-g', '-pg' ]
 else:
-    debug_flags = [ '-O0', '-g' ]
+    debug_flags = [ '-g' ]
 
 # guess at the platform, used to define compiler flags
 
@@ -728,23 +755,45 @@ if env['LIBLO']:
 
 def prep_libcheck(topenv, libinfo):
     if topenv['DIST_TARGET'] == 'panther' or topenv['DIST_TARGET'] == 'tiger':
-        #
-        # rationale: GTK-Quartz uses jhbuild and installs to /opt/gtk by default.
-        #            All libraries needed should be built against this location
-        if topenv['GTKOSX']:
-            libinfo.Append(CCFLAGS="-I/opt/gtk/include", LINKFLAGS="-L/opt/gtk/lib")
-        libinfo.Append(CCFLAGS="-I/opt/local/include", LINKFLAGS="-L/opt/local/lib")
-            
+       #
+       # rationale: GTK-Quartz uses jhbuild and installs to /opt/gtk by default.
+       #            All libraries needed should be built against this location
+       if topenv['GTKOSX']:
+               libinfo.Append(CPPPATH="/opt/gtk/include", LIBPATH="/opt/gtk/lib")
+               libinfo.Append(CXXFLAGS="-I/opt/gtk/include", LINKFLAGS="-L/opt/gtk/lib")
+       libinfo.Append(CPPPATH="/opt/local/include", LIBPATH="/opt/local/lib")
+       libinfo.Append(CXXFLAGS="-I/opt/local/include", LINKFLAGS="-L/opt/local/lib")
+
 prep_libcheck(env, env)
 
 #
-# glibc backtrace API, needed everywhere if we want to do shared_ptr<T> debugging
+# check for VAMP and rubberband (currently optional)
 #
 
-conf = Configure (env)
-if conf.CheckCHeader('execinfo.h'):
-    conf.env.Append(CXXFLAGS="-DHAVE_EXECINFO")
-env = conf.Finish ()
+libraries['vamp'] = LibraryInfo()
+
+env['RUBBERBAND'] = False
+
+#conf = env.Configure (custom_tests = { 'CheckPKGExists' : CheckPKGExists } )
+#
+#if conf.CheckPKGExists('vamp-sdk'):
+#    have_vamp = True
+#    libraries['vamp'].ParseConfig('pkg-config --cflags --libs vamp-sdk')
+#else:
+#    have_vamp = False
+#
+#libraries['vamp'] = conf.Finish ()
+#
+#if have_vamp:
+#    if os.path.exists ('libs/rubberband/src'):
+#        conf = Configure (libraries['vamp'])
+#        if conf.CheckHeader ('fftw3.h'):
+#            env['RUBBERBAND'] = True
+#            libraries['rubberband'] = LibraryInfo (LIBS='rubberband',
+#                                                   LIBPATH='#libs/rubberband',
+#                                                   CPPPATH='#libs/rubberband',
+#                                                   CCFLAGS='-DUSE_RUBBERBAND')
+#        libraries['vamp'] = conf.Finish ()
 
 #
 # Check for libusb
@@ -771,7 +820,7 @@ libraries['usb'] = conf.Finish ()
 
 libraries['flac'] = LibraryInfo ()
 prep_libcheck(env, libraries['flac'])
-libraries['flac'].Append(CCFLAGS="-I/usr/local/include", LINKFLAGS="-L/usr/local/lib")
+libraries['flac'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
 
 #
 # june 1st 2007: look for a function that is in FLAC 1.1.2 and not in later versions
@@ -780,12 +829,14 @@ libraries['flac'].Append(CCFLAGS="-I/usr/local/include", LINKFLAGS="-L/usr/local
 #
 
 conf = Configure (libraries['flac'])
-if conf.CheckLib ('FLAC', 'FLAC__seekable_stream_decoder_set_read_callback', language='CXX'):
+if conf.CheckLib ('FLAC', 'FLAC__seekable_stream_decoder_init', language='CXX'):
     conf.env.Append(CCFLAGS='-DHAVE_FLAC')
     use_flac = True
 else:
     use_flac = False
+    
 libraries['flac'] = conf.Finish ()
+
 # or if that fails...
 #libraries['flac']    = LibraryInfo (LIBS='FLAC')
 
@@ -793,7 +844,7 @@ libraries['flac'] = conf.Finish ()
 
 libraries['boost'] = LibraryInfo ()
 prep_libcheck(env, libraries['boost'])
-libraries['boost'].Append(CCFLAGS="-I/usr/local/include", LINKFLAGS="-L/usr/local/lib")
+libraries['boost'].Append(CPPPATH="/usr/local/include", LIBPATH="/usr/local/lib")
 conf = Configure (libraries['boost'])
 if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == False:
         print "Boost header files do not appear to be installed."
@@ -834,17 +885,16 @@ else:
 libraries['dmalloc'] = conf.Finish ()
 
 #
-# Audio/MIDI library (needed for MIDI, since audio is all handled via JACK. Note, however, that
-#                     we still need ALSA & CoreAudio to discover audio devices for the engine
-#                     dialog, regardless of what MIDI subsystem is being used)
+# Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
 #
 
 conf = Configure(env)
+    
+# ALSA, for engine dialog
+libraries['asound'] = LibraryInfo ()
 
 if conf.CheckCHeader('alsa/asoundlib.h'):
-    libraries['sysaudio'] = LibraryInfo (LIBS='asound')
-elif conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
-    libraries['sysaudio'] = LibraryInfo (LINKFLAGS= '-framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load')
+    libraries['asound'] = LibraryInfo (LIBS='asound')
 
 if conf.CheckCHeader('jack/midiport.h'):
     libraries['sysmidi'] = LibraryInfo (LIBS='jack')
@@ -863,14 +913,13 @@ elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/Co
     if env['GTKOSX']:
         # We need Carbon as well as the rest
         libraries['sysmidi'] = LibraryInfo (
-               LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -framework Carbon -bind_at_load' )
+               LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -framework Carbon -bind_at_load' )
     else:
         libraries['sysmidi'] = LibraryInfo (
                LINKFLAGS = ' -framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit -framework AudioToolbox -bind_at_load' )
     env['SYSMIDI'] = 'CoreMIDI'
     subst_dict['%MIDITAG%'] = "ardour"
     subst_dict['%MIDITYPE%'] = "coremidi"
-    print "Using CoreMIDI"
 else:
     print "It appears you don't have the required MIDI libraries installed. For Linux this means you are missing the development package for ALSA libraries."
     sys.exit (1)
@@ -883,8 +932,7 @@ if env['SYSLIBS']:
     {
         'sigc++-2.0'           : '2.0',
         'gtkmm-2.4'            : '2.8',
-        'libgnomecanvasmm-2.6' : '2.12.0',
-        'libSoundTouch'        : '1.2.1'
+        'libgnomecanvasmm-2.6' : '2.12.0'
     }
 
     conf = Configure(env, custom_tests = { 'CheckPKGConfig' : CheckPKGConfig,
@@ -912,8 +960,6 @@ if env['SYSLIBS']:
     libraries['atkmm'].ParseConfig ('pkg-config --cflags --libs atkmm-1.6')
     libraries['pangomm'] = LibraryInfo()
     libraries['pangomm'].ParseConfig ('pkg-config --cflags --libs pangomm-1.4')
-    libraries['cairomm'] = LibraryInfo()
-    libraries['cairomm'].ParseConfig ('pkg-config --cflags --libs cairomm-1.0')
     libraries['libgnomecanvasmm'] = LibraryInfo()
     libraries['libgnomecanvasmm'].ParseConfig ('pkg-config --cflags --libs libgnomecanvasmm-2.6')
 
@@ -930,17 +976,16 @@ if env['SYSLIBS']:
 
 #    libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
     libraries['soundtouch'] = LibraryInfo()
-    libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
+    #libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
     # Comment the previous line and uncomment this for Debian:
-    #libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
+    libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
 
     libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
                                             LIBPATH='#libs/appleutility',
                                             CPPPATH='#libs/appleutility')
     
     coredirs = [
-        'templates',
-        'manual'
+        'templates'
     ]
     
     subdirs = [
@@ -972,10 +1017,7 @@ else:
                                     CPPPATH='#libs/sigc++2')
     libraries['glibmm2'] = LibraryInfo(LIBS='glibmm2',
                                     LIBPATH='#libs/glibmm2',
-                                    CPPPATH=['#libs/glibmm2/glib', '#libs/glibmm2'])
-    libraries['cairomm'] = LibraryInfo(LIBS='cairomm',
-                                       LIBPATH="#libs/cairomm",
-                                       CPPPATH='#libs/cairomm')
+                                    CPPPATH='#libs/glibmm2')
     libraries['pangomm'] = LibraryInfo(LIBS='pangomm',
                                     LIBPATH='#libs/gtkmm2/pango',
                                     CPPPATH='#libs/gtkmm2/pango')
@@ -1006,9 +1048,7 @@ else:
                                             CPPPATH='#libs/appleutility')
 
     coredirs = [
-        'libs/soundtouch',
-        'templates',
-        'manual'
+        'templates'
     ]
     
     subdirs = [
@@ -1034,7 +1074,6 @@ else:
        'libs/gtkmm2/atk',
        'libs/gtkmm2/gdk',
        'libs/gtkmm2/gtk',
-        'libs/cairomm',
        'libs/libgnomecanvasmm',
 #      'libs/flowcanvas',
         'libs/gtkmm2ext',
@@ -1075,25 +1114,17 @@ else:
     env['POWERMATE'] = 0
     env['TRANZPORT'] = 0
 
+#
+# timestretch libraries
+#
+
+timefx_subdirs = ['libs/soundtouch']
+#if env['RUBBERBAND']:
+#    timefx_subdirs += ['libs/rubberband']
+    
 opts.Save('scache.conf', env)
 Help(opts.GenerateHelpText(env))
 
-if os.environ.has_key('PATH'):
-    env.Append(PATH = os.environ['PATH'])
-
-if os.environ.has_key('PKG_CONFIG_PATH'):
-    env.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
-
-if os.environ.has_key('CC'):
-    env['CC'] = os.environ['CC']
-
-if os.environ.has_key('CXX'):
-    env['CXX'] = os.environ['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'
 
 if env['DESTDIR'] :
@@ -1112,14 +1143,6 @@ else:
 
 config_prefix = '$DESTDIR' + final_config_prefix
 
-# For colorgcc
-if os.environ.has_key('PATH'):
-       env['PATH'] = os.environ['PATH']
-if os.environ.has_key('TERM'):
-       env['TERM'] = os.environ['TERM']
-if os.environ.has_key('HOME'):
-       env['HOME'] = os.environ['HOME']
-
 #
 # everybody needs this
 #
@@ -1174,8 +1197,8 @@ if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/
     subst_dict['%JACK_INPUT%'] = "coreaudio:Built-in Audio:in"
     subst_dict['%JACK_OUTPUT%'] = "coreaudio:Built-in Audio:out"
 else:
-    subst_dict['%JACK_INPUT%'] = "system:playback_"
-    subst_dict['%JACK_OUTPUT%'] = "system:capture_"
+    subst_dict['%JACK_INPUT%'] = "alsa_pcm:playback_"
+    subst_dict['%JACK_OUTPUT%'] = "alsa_pcm:capture_"
 
 # posix_memalign available
 if not conf.CheckFunc('posix_memalign'):
@@ -1256,7 +1279,7 @@ env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
 for subdir in coredirs:
     SConscript (subdir + '/SConscript')
 
-for sublistdir in [ subdirs, gtk_subdirs, surface_subdirs ]:
+for sublistdir in [ subdirs, timefx_subdirs, gtk_subdirs, surface_subdirs ]:
     for subdir in sublistdir:
         SConscript (subdir + '/SConscript')
 
index 388a4161432fc26ead84798a5d0008d3b83c3778..f3b8788fadf1e8010c64feb7d220e81d593033e4 100644 (file)
@@ -49,12 +49,10 @@ gtkardour.Merge ([
     libraries['gtk2'],
     libraries['xml'],
     libraries['xslt'],
-    libraries['soundtouch'],
-    libraries['rubberband'],
     libraries['samplerate'],
     libraries['jack'],
-    libraries['sysaudio'],
-    libraries['cairomm']
+    libraries['cairomm'],
+    libraries['asound']
 ])
 
 gtkmmtests.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
@@ -78,17 +76,22 @@ if gtkardour['FFT_ANALYSIS']:
        gtkardour.Merge ([libraries['fftw3f']])
        gtkardour.Append(CCFLAGS='-DFFT_ANALYSIS')
 
+if gtkardour['RUBBERBAND']:
+       gtkardour.Merge ([ libraries['rubberband'],  libraries['vamp'], libraries['fftw3f'], libraries['fftw3'] ])
+else:
+       gtkardour.Merge ([ libraries['soundtouch'] ])
+
 skipped_files=Split("""
 connection_editor.cc
 """)
 
 audiounit_files=Split("""
-au_pluginui.cc
+au_pluginui.mm
 """)
 
 gtkosx_files=Split("""
 sync-menu.c
-cocoacarbon.c
+cocoacarbon.mm
 """)
 
 x11_files=Split("""
@@ -165,6 +168,7 @@ export_session_dialog.cc
 export_region_dialog.cc
 export_range_markers_dialog.cc
 gain_meter.cc
+generic_pluginui.cc
 ghostregion.cc
 gtk-custom-hruler.c
 gtk-custom-ruler.c
@@ -172,7 +176,6 @@ io_selector.cc
 port_matrix.cc
 keyboard.cc
 keyeditor.cc
-ladspa_pluginui.cc
 latency_gui.cc
 level_meter.cc
 location_ui.cc
@@ -183,6 +186,7 @@ mixer_ui.cc
 new_session_dialog.cc
 option_editor.cc
 opts.cc
+
 panner.cc
 panner2d.cc
 panner_ui.cc
@@ -230,6 +234,10 @@ icon_files = glob.glob ('icons/*.png')
 
 intl_files = gtkardour_files + glob.glob('*.h')
 
+evtest_files=Split("""
+evtest.cc
+""")
+
 mtest_files=Split("""
 mtest.cc
 """)
@@ -274,21 +282,23 @@ marker_view.cc
 visual_time_axis.cc
 """)
 
-if env['CMT']:
-    extra_sources += cmt_files
-    gtkardour.Append (CCFLAGS="-DWITH_CMT")
+#if env['CMT']:
+#   extra_sources += cmt_files
+#    gtkardour.Append (CCFLAGS="-DWITH_CMT")
 
 if gtkardour['GTKOSX']:
-   extra_sources += gtkosx_files
-   gtkardour.Append (CCFLAGS="-DTOP_MENUBAR -DGTKOSX")
+       extra_sources += gtkosx_files
+       gtkardour.Append (CCFLAGS="-DTOP_MENUBAR -DGTKOSX")
+       gtkardour.Append (LINKFLAGS=" -framework AppKit -framework CoreAudioKit")
+
+       if gtkardour['AUDIOUNITS']:
+               extra_sources += audiounit_files
+               gtkardour.Append(CCFLAGS='-DHAVE_AUDIOUNITS')
+               gtkardour.Merge([libraries['appleutility']])
+
 else:
    extra_sources += x11_files
        
-if gtkardour['AUDIOUNITS']:
-    extra_sources += audiounit_files
-    gtkardour.Append(CCFLAGS='-DHAVE_AUDIOUNITS')
-    gtkardour.Append(LINKFLAGS='-framework Carbon')
-    gtkardour.Merge([libraries['appleutility']])
  
 if env['FFT_ANALYSIS']:
        extra_sources += fft_analysis_files
@@ -307,6 +317,7 @@ executable = 'ardour-' + ardour_version
 ardour = gtkardour.Program(target = executable, source = gtkardour_files + extra_sources)
 ardourlib = gtkardour.SharedLibrary(target = 'ardourgtk', source = gtkardour_files + extra_sources)
 
+evest = gtkmmtests.Program(target = 'evtest', source = evtest_files)
 mtest = gtkardour.Program(target = 'mtest', source = mtest_files)
 itest = gtkardour.Program(target = 'itest', source = itest_files)
 rcu = gtkardour.Program(target = 'rcu', source = rcu_files)
@@ -396,7 +407,30 @@ my_subst_dict = { }
 # null substitution just to avoid ardour.bindings being in svn
 #
 
-ardourbindings = env.SubstInFile ('ardour.bindings', 'ardour.bindings.in', SUBST_DICT = my_subst_dict);
+keybindings_dict = { }
+
+if gtkardour['GTKOSX'] and gtkardour['NATIVE_OSX_KEYS']:
+       #
+       # Command(Mod1), Alt(Mod5), Ctrl, Shift
+       #
+       keybindings_dict['%PRIMARY%'] = 'Mod5'
+       keybindings_dict['%SECONDARY%'] = 'Alt'
+       keybindings_dict['%TERTIARY%'] = 'Shift'
+       keybindings_dict['%LEVEL4%'] = 'Ctrl'
+       keybindings_dict['%WINDOW%'] = 'Mod5'
+else:
+       #
+       # Ctrl, Alt, Shift, Mod3(Meta)
+       #
+       keybindings_dict['%PRIMARY%'] = 'Ctrl'
+       keybindings_dict['%SECONDARY%'] = 'Alt'
+       keybindings_dict['%TERTIARY%'] = 'Shift'
+       keybindings_dict['%LEVEL4%'] = 'Mod2'
+       keybindings_dict['%WINDOW%'] = 'Ctrl'
+
+ardourbindings = env.SubstInFile ('ardour.bindings', 'ardour.bindings.in', SUBST_DICT = keybindings_dict);
+ardoursaeDEbindings = env.SubstInFile ('ardour-sae-de.bindings', 'ardour-sae-de.bindings.in', SUBST_DICT = keybindings_dict);
+ardoursaeANSIbindings = env.SubstInFile ('ardour-sae-ansi.bindings', 'ardour-sae-ansi.bindings.in', SUBST_DICT = keybindings_dict);
 
 my_subst_dict['%INSTALL_PREFIX%'] = final_prefix
 my_subst_dict['%LIBDIR%'] = env['LIBDIR']
@@ -409,6 +443,8 @@ ardourdev = env.SubstInFile ('ardev_common.sh','ardev_common.sh.in', SUBST_DICT
 env.AddPostAction (ardourdev, Chmod ('$TARGET', 0755))
 
 Default(ardourbindings)
+Default(ardoursaeDEbindings)
+Default(ardoursaeANSIbindings)
 Default(ardourdev)
 Default(ardoursh)
 Default(ardour_dark_theme)
@@ -441,7 +477,8 @@ env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), ardour_
 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour.menus'))
 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour-sae.menus'))
 env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour.bindings'))
-env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour2_ui_default.conf'))
+env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour-sae-ansi.bindings'))
+env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour-sae-de.bindings'))
 # data files
 env.Alias('install', env.Install(os.path.join(install_prefix, 'share', 'ardour2'), 'splash.png'))
 env.Alias('install', env.Install(os.path.join(install_prefix, 'share', 'ardour2', 'pixmaps'), pixmap_files))
@@ -457,9 +494,11 @@ env.Alias ('tarball', env.Distribute (env['DISTTREE'],
                                        'ardev_common.sh.in',
                                        'ardev', 'ardbg',
                                         'ardour2_ui_dark.rc.in', 'ardour2_ui_light.rc.in', 'splash.png',
-                                        'ardour.menus',
-                                        'ardour-sae.menus',
-                                       'ardour.bindings.in', 'ardour2_ui_default.conf',
+                                        'ardour.menus', 'ardour-sae.menus', 
+                                       'ardour.bindings.in', 
+                                       'ardour-sae-ansi.bindings.in', 
+                                       'ardour-sae-de.bindings.in', 
+                                       'ardour2_ui_default.conf',
                                        'editor_xpms'
                                         ] +
                                       gtkardour_files +
index 023520c17e9c4ec3e3efc434985fce947d55a3ef..1484c01454309bdfb9724461b432c42f87a9a70c 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <vector>
 #include <string>
+#include <list>
 
 #include <gtk/gtkaccelmap.h>
 #include <gtk/gtkuimanager.h>
@@ -150,6 +151,14 @@ ActionManager::lookup_entry (const ustring accel_path, Gtk::AccelKey& key)
        return known;
 }
 
+struct SortActionsByLabel {
+    bool operator() (Glib::RefPtr<Gtk::Action> a, Glib::RefPtr<Gtk::Action> b) {
+           ustring astr = a->get_accel_path();
+           ustring bstr = b->get_accel_path();
+           return astr < bstr;
+    }
+};
+
 void
 ActionManager::get_all_actions (vector<string>& names, vector<string>& paths, vector<string>& keys, vector<AccelKey>& bindings)
 {
@@ -162,18 +171,29 @@ ActionManager::get_all_actions (vector<string>& names, vector<string>& paths, ve
        GList* acts;
 
        for (node = list; node; node = g_list_next (node)) {
-
+               
                GtkActionGroup* group = (GtkActionGroup*) node->data;
+               
+               /* first pass: collect them all */
+               
+               typedef std::list<Glib::RefPtr<Gtk::Action> > action_list;
+               action_list the_acts;
 
                for (acts = gtk_action_group_list_actions (group); acts; acts = g_list_next (acts)) {
-
                        GtkAction* action = (GtkAction*) acts->data;
+                       the_acts.push_back (Glib::wrap (action, true));
+               }
+               
+               /* now sort by label */
+               
+               SortActionsByLabel cmp;
+               the_acts.sort (cmp);
 
-                       Glib::RefPtr<Action> act = Glib::wrap (action, true);
+               for (action_list::iterator a = the_acts.begin(); a != the_acts.end(); ++a) {
+
+                       string accel_path = (*a)->get_accel_path ();
+                       ustring label = (*a)->property_label();
 
-                       string accel_path = act->get_accel_path ();
-                       ustring label = act->property_label();
-                       
                        names.push_back (label);
                        paths.push_back (accel_path);
                        
index 45fe7456f3f98f18d225811f7fbbcb52a32a9f35..dbf95037e8d4829622de5246553e96c4ed99c660 100644 (file)
@@ -25,6 +25,7 @@
 #include <pbd/error.h>
 #include <pbd/convert.h>
 #include <gtkmm2ext/utils.h>
+#include <ardour/profile.h>
 
 #include "utils.h"
 #include "add_route_dialog.h"
@@ -67,10 +68,27 @@ AddRouteDialog::AddRouteDialog ()
 {
        if (channel_combo_strings.empty()) {
                channel_combo_strings = I18N (channel_setup_names);
+
+               if (ARDOUR::Profile->get_sae()) {
+                       /* remove all but the first two (Mono & Stereo) */
+
+                       while (track_mode_strings.size() > 2) {
+                               track_mode_strings.pop_back();
+                       }
+               }
+
        }
 
        if (track_mode_strings.empty()) {
                track_mode_strings = I18N (track_mode_names);
+
+               if (ARDOUR::Profile->get_sae()) {
+                       /* remove all but the first track mode (Normal) */
+
+                       while (track_mode_strings.size() > 1) {
+                               track_mode_strings.pop_back();
+                       }
+               }
        }
 
        set_name ("AddRouteDialog");
@@ -121,7 +139,9 @@ AddRouteDialog::AddRouteDialog ()
        ccframe.set_shadow_type (SHADOW_IN);
 
        dvbox->pack_start (channel_combo, true, false, 5);
-       dvbox->pack_start (track_mode_combo, true, false, 5);
+       if (!ARDOUR::Profile->get_sae()) {
+               dvbox->pack_start (track_mode_combo, true, false, 5);
+       }
        dhbox->pack_start (*dvbox, true, false, 5);
 
        ccframe.add (*dhbox);
@@ -198,6 +218,10 @@ AddRouteDialog::count ()
 ARDOUR::TrackMode
 AddRouteDialog::mode ()
 {
+       if (ARDOUR::Profile->get_sae()) {
+               return ARDOUR::Normal;
+       }
+
        Glib::ustring str = track_mode_combo.get_active_text();
        if (str == _("Normal")) {
                return ARDOUR::Normal;
index e8746e9fedf2cdedd1dcc0bd74c64a716dfc023e..8165b22bc4fdb067dc5b0f247d3dbaf8555cbef2 100644 (file)
@@ -7,10 +7,10 @@ export GTK_PATH=libs/clearlooks
 
 export ARDOUR_SURFACES_PATH=libs/surfaces/frontier:libs/surfaces/generic_midi:libs/surfaces/mackie:libs/surfaces/tranzport
 
-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:libs/cairomm:$LD_LIBRARY_PATH
+export LD_LIBRARY_PATH=libs/surfaces/control_protocol:libs/ardour:libs/midi++2:libs/pbd:libs/rubberband: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
+export DYLD_FALLBACK_LIBRARY_PATH=$LD_LIBRARY_PATH
 # For the internal clearlooks engine
 export GTK_PATH=$PWD/libs/clearlooks:~/.ardour2
 
diff --git a/gtk2_ardour/ardour-sae-ansi.bindings.in b/gtk2_ardour/ardour-sae-ansi.bindings.in
new file mode 100644 (file)
index 0000000..523878b
--- /dev/null
@@ -0,0 +1,346 @@
+; ardour GtkAccelMap rc-file         -*- scheme -*-
+; this file is an automated accelerator map dump
+;
+; (gtk_accel_path "<Actions>/RegionList/RegionListSort" "")
+(gtk_accel_path "<Actions>/Common/Quit" "<%PRIMARY%>q")
+(gtk_accel_path "<Actions>/Common/Save" "<%PRIMARY%>s")
+; (gtk_accel_path "<Actions>/Editor/Pullup" "")
+; (gtk_accel_path "<Actions>/Editor/zoom-to-session" "")
+; (gtk_accel_path "<Actions>/JACK/JACKReconnect" "")
+; (gtk_accel_path "<Actions>/Editor/Autoconnect" "")
+; (gtk_accel_path "<Actions>/Editor/Edit" "")
+(gtk_accel_path "<Actions>/Editor/cycle-edit-point" "grave")
+(gtk_accel_path "<Actions>/Editor/cycle-edit-point-with-marker" "<%SECONDARY%>grave")
+(gtk_accel_path "<Actions>/Editor/toggle-edit-mode" "1")
+(gtk_accel_path "<Actions>/Editor/cycle-snap-mode" "2")
+(gtk_accel_path "<Actions>/Editor/cycle-snap-choice" "3")
+; (gtk_accel_path "<Actions>/redirectmenu/copy" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffFaster" "")
+(gtk_accel_path "<Actions>/Transport/ToggleRollForgetCapture" "<%PRIMARY%>space")
+(gtk_accel_path "<Actions>/Transport/record-roll" "<%TERTIARY%>space")
+(gtk_accel_path "<Actions>/Transport/Record" "<%TERTIARY%>r")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionLength" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffSlowest" "")
+; (gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-sync" "")
+; (gtk_accel_path "<Actions>/redirectmenu/deactivate_all" "")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionPosition" "")
+; (gtk_accel_path "<Actions>/Editor/ZoomFocus" "")
+(gtk_accel_path "<Actions>/Editor/addExistingAudioFiles" "<%SECONDARY%>i")
+; (gtk_accel_path "<Actions>/options/MeterFalloffSlow" "")
+; (gtk_accel_path "<Actions>/RegionList/rlHide" "")
+; (gtk_accel_path "<Actions>/Main/Metering" "")
+(gtk_accel_path "<Actions>/Editor/playhead-to-next-region-boundary" "rightarrow")
+(gtk_accel_path "<Actions>/Editor/selected-marker-to-next-region-boundary" "<%PRIMARY%><%TERTIARY%>rightarrow")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-playhead" "")
+; (gtk_accel_path "<Actions>/Editor/center-edit-cursor" "")
+; (gtk_accel_path "<Actions>/Editor/Monitoring" "")
+; (gtk_accel_path "<Actions>/redirectmenu/deactivate" "")
+; (gtk_accel_path "<Actions>/options/LatchedRecordEnable" "")
+; (gtk_accel_path "<Actions>/Transport/TogglePunchIn" "")
+; (gtk_accel_path "<Actions>/ShuttleActions/SetShuttleUnitsPercentage" "")
+; (gtk_accel_path "<Actions>/Main/Close" "")
+; (gtk_accel_path "<Actions>/Main/New" "")
+(gtk_accel_path "<Actions>/Editor/nudge-next-backward" "<%PRIMARY%>KP_Subtract")
+; (gtk_accel_path "<Actions>/Editor/EditSelectRangeOptions" "")
+; (gtk_accel_path "<Actions>/Transport/ToggleTimeMaster" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-thirds" "")
+(gtk_accel_path "<Actions>/Editor/align-regions-start-relative" "<%TERTIARY%>a")
+; (gtk_accel_path "<Actions>/Main/Export" "")
+(gtk_accel_path "<Actions>/Editor/jump-forward-to-mark" "<%PRIMARY%>KP_Right")
+; (gtk_accel_path "<Actions>/Editor/Smpte30" "")
+; (gtk_accel_path "<Actions>/Editor/playhead-to-range-start" "")
+; (gtk_accel_path "<Actions>/Editor/Subframes" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte2997drop" "")
+(gtk_accel_path "<Actions>/Main/AddTrackBus" "<%PRIMARY%><%SECONDARY%>n")
+(gtk_accel_path "<Actions>/Editor/align-regions-end" "<%LEVEL4%>a")
+; (gtk_accel_path "<Actions>/JACK/JACKDisconnect" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffFast" "")
+; (gtk_accel_path "<Actions>/options/FileDataFormatFloat" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-region-end" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-next-region-sync" "semicolon")
+; (gtk_accel_path "<Actions>/options/StopRecordingOnXrun" "")
+; (gtk_accel_path "<Actions>/RegionList/SortDescending" "")
+; (gtk_accel_path "<Actions>/options/DoNotRunPluginsWhileRecording" "")
+; (gtk_accel_path "<Actions>/Editor/PullupNone" "")
+(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-range" "r")
+(gtk_accel_path "<Actions>/Editor/jump-backward-to-mark" "<%PRIMARY%>KP_Left")
+; (gtk_accel_path "<Actions>/Main/AudioFileFormatData" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffFastest" "")
+(gtk_accel_path "<Actions>/Editor/play-selected-regions" "w")
+(gtk_accel_path "<Actions>/Editor/play-edit-range" "<%SECONDARY%>w")
+(gtk_accel_path "<Actions>/Transport/Forward" "<%PRIMARY%>rightarrow")
+; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-seconds" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-frame" "")
+; (gtk_accel_path "<Actions>/Main/ExportSelection" "")
+; (gtk_accel_path "<Actions>/options/StopPluginsWithTransport" "")
+(gtk_accel_path "<Actions>/Editor/editor-paste" "<%PRIMARY%>v")
+(gtk_accel_path "<Actions>/Editor/scroll-tracks-down" "Page_Down")
+(gtk_accel_path "<Actions>/Editor/select-next-route" "downarrow")
+(gtk_accel_path "<Actions>/Editor/select-prev-route" "uparrow")
+; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-minutes" "")
+; (gtk_accel_path "<Actions>/Main/FlushWastebasket" "")
+(gtk_accel_path "<Actions>/Editor/normalize-region" "n")
+(gtk_accel_path "<Actions>/Editor/nudge-forward" "h")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionEndinFile" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleMeasureVisibility" "")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-center" "")
+(gtk_accel_path "<Actions>/Editor/nudge-backward" "g")
+; (gtk_accel_path "<Actions>/options/LatchedSolo" "")
+; (gtk_accel_path "<Actions>/options/MeterHoldOff" "")
+; (gtk_accel_path "<Actions>/options/OutputAutoConnectMaster" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency64" "")
+(gtk_accel_path "<Actions>/Editor/undo" "<%PRIMARY%>z")
+(gtk_accel_path "<Actions>/Editor/insert-region" "i")
+; (gtk_accel_path "<Actions>/Editor/center-playhead" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-region-start" "")
+; (gtk_accel_path "<Actions>/Editor/View" "")
+; (gtk_accel_path "<Actions>/Editor/Layering" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency4096" "")
+(gtk_accel_path "<Actions>/Editor/scroll-tracks-up" "Page_Up")
+(gtk_accel_path "<Actions>/Editor/set-edit-point" "g")
+; (gtk_accel_path "<Actions>/Editor/Smpte30drop" "")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-edit" "")
+(gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-boundary" "leftarrow")
+(gtk_accel_path "<Actions>/Editor/selected-marker-to-previous-region-boundary" "<%PRIMARY%><%TERTIARY%>leftarrow")
+; (gtk_accel_path "<Actions>/Editor/EditCursorMovementOptions" "")
+; (gtk_accel_path "<Actions>/redirectmenu/activate_all" "")
+; (gtk_accel_path "<Actions>/redirectmenu/paste" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte25" "")
+; (gtk_accel_path "<Actions>/options/RegionEquivalentsOverlap" "")
+; (gtk_accel_path "<Actions>/Main/MeteringFallOffRate" "")
+; (gtk_accel_path "<Actions>/options/UseHardwareMonitoring" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte24" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-mark" "")
+; (gtk_accel_path "<Actions>/Editor/CrossfadesShort" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte5994" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency8192" "")
+; (gtk_accel_path "<Actions>/Editor/toggle-xfades-visible" "")
+(gtk_accel_path "<Actions>/Editor/extend-range-to-end-of-region" "rightanglebracket")
+(gtk_accel_path "<Actions>/Editor/start-range" "F1")
+; (gtk_accel_path "<Actions>/ShuttleActions/SetShuttleUnitsSemitones" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency128" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-beat" "")
+; (gtk_accel_path "<Actions>/Editor/RegionEditOps" "")
+; (gtk_accel_path "<Actions>/Editor/snap-magnetic" "")
+; (gtk_accel_path "<Actions>/Editor/playhead-to-range-end" "")
+(gtk_accel_path "<Actions>/Editor/scroll-playhead-forward" "<%TERTIARY%>rightarrow")
+(gtk_accel_path "<Actions>/Editor/align-regions-sync-relative" "<%SECONDARY%>less")
+(gtk_accel_path "<Actions>/Editor/align-regions-sync" "less")
+; (gtk_accel_path "<Actions>/Editor/EditSelectRegionOptions" "")
+(gtk_accel_path "<Actions>/Editor/crop" "c")
+; (gtk_accel_path "<Actions>/redirectmenu/newsend" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceSubMenu" "")
+; (gtk_accel_path "<Actions>/Editor/MeterFalloff" "")
+; (gtk_accel_path "<Actions>/RegionList/rlRemove" "")
+(gtk_accel_path "<Actions>/Transport/GotoStart" "Home")
+(gtk_accel_path "<Actions>/Editor/select-all-before-edit-cursor" "<%TERTIARY%>Home")
+(gtk_accel_path "<Actions>/Editor/scroll-playhead-backward" "<%TERTIARY%>leftarrow")
+(gtk_accel_path "<Actions>/Editor/split-region" "z")
+; (gtk_accel_path "<Actions>/Transport/ToggleAutoInput" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-thirtyseconds" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-minutes" "")
+; (gtk_accel_path "<Actions>/Main/Windows" "")
+; (gtk_accel_path "<Actions>/Main/CleanupUnused" "")
+; (gtk_accel_path "<Actions>/redirectmenu/deselectall" "")
+; (gtk_accel_path "<Actions>/options/SoloViaBus" "")
+; (gtk_accel_path "<Actions>/RegionList/rlAudition" "")
+(gtk_accel_path "<Actions>/Editor/set-region-sync-position" "u")
+; (gtk_accel_path "<Actions>/Editor/PullupPlus4Plus1" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-region-boundary" "")
+; (gtk_accel_path "<Actions>/JACK/JACK" "")
+(gtk_accel_path "<Actions>/Editor/editor-cut" "<%PRIMARY%>x")
+(gtk_accel_path "<Actions>/Editor/editor-separate" "F4")
+; (gtk_accel_path "<Actions>/RegionList/SortAscending" "")
+; (gtk_accel_path "<Actions>/Main/Help" "")
+; (gtk_accel_path "<Actions>/options/UseExternalMonitoring" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte23976" "")
+(gtk_accel_path "<Actions>/Common/goto-editor" "<%WINDOW%>e")
+(gtk_accel_path "<Actions>/Editor/select-all" "F14")
+(gtk_accel_path "<Actions>/Editor/invert-selection" "F15")
+(gtk_accel_path "<Actions>/Editor/nudge-next-forward" "<%PRIMARY%>KP_Add")
+; (gtk_accel_path "<Actions>/options/ShowSoloMutes" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-eighths" "")
+(gtk_accel_path "<Actions>/Editor/select-all-after-playhead" "<%TERTIARY%><%PRIMARY%>p")
+(gtk_accel_path "<Actions>/Common/ToggleMaximalEditor" "F11")
+; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileLength" "")
+; (gtk_accel_path "<Actions>/Editor/Timecode" "")
+; (gtk_accel_path "<Actions>/Transport/PlaySelection" "")
+; (gtk_accel_path "<Actions>/Editor/PullupMinus4Minus1" "")
+(gtk_accel_path "<Actions>/Editor/select-all-after-edit-cursor" "<%TERTIARY%><%PRIMARY%>e")
+; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileName" "")
+(gtk_accel_path "<Actions>/Editor/finish-range" "F2")
+(gtk_accel_path "<Actions>/Editor/select-range-between-cursors" "F16")
+(gtk_accel_path "<Actions>/Transport/Loop" "l")
+; (gtk_accel_path "<Actions>/Editor/CrossfadesFull" "")
+(gtk_accel_path "<Actions>/Editor/finish-add-range" "<%TERTIARY%><%PRIMARY%>KP_Up")
+; (gtk_accel_path "<Actions>/options/SendMTC" "")
+; (gtk_accel_path "<Actions>/Transport/TogglePunchOut" "")
+(gtk_accel_path "<Actions>/Editor/select-all-in-loop-range" "<%PRIMARY%>l")
+(gtk_accel_path "<Actions>/Editor/show-editor-mixer" "<%TERTIARY%>e")
+; (gtk_accel_path "<Actions>/options/SoloInPlace" "")
+; (gtk_accel_path "<Actions>/Main/Options" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffMedium" "")
+(gtk_accel_path "<Actions>/Editor/toggle-follow-playhead" "f")
+; (gtk_accel_path "<Actions>/Main/SaveTemplate" "")
+(gtk_accel_path "<Actions>/Transport/TransitionToRoll" "<%PRIMARY%>uparrow")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionStartinFile" "")
+; (gtk_accel_path "<Actions>/options/GainReduceFastTransport" "")
+; (gtk_accel_path "<Actions>/Common/ToggleInspector" "")
+; (gtk_accel_path "<Actions>/Transport/ToggleAutoPlay" "")
+; (gtk_accel_path "<Actions>/Editor/playhead-to-next-region-sync" "")
+(gtk_accel_path "<Actions>/Editor/edit-to-playhead" "<%SECONDARY%>Return")
+; (gtk_accel_path "<Actions>/Editor/LayerMoveAddHigher" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte60" "")
+; (gtk_accel_path "<Actions>/Main/Open" "")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-left" "")
+; (gtk_accel_path "<Actions>/Main/TransportOptions" "")
+; (gtk_accel_path "<Actions>/Main/ControlSurfaces" "")
+; (gtk_accel_path "<Actions>/options/FileHeaderFormatBWF" "")
+; (gtk_accel_path "<Actions>/Transport/ToggleAutoReturn" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte2997" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleWaveformVisibility" "")
+(gtk_accel_path "<Actions>/Editor/redo" "<%PRIMARY%>r")
+; (gtk_accel_path "<Actions>/Main/ExportSession" "")
+; (gtk_accel_path "<Actions>/options/InputAutoConnectPhysical" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-edit-cursor" "")
+(gtk_accel_path "<Actions>/Editor/temporal-zoom-in" "t")
+; (gtk_accel_path "<Actions>/JACK/Latency" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-end" "<%TERTIARY%>F2")
+; (gtk_accel_path "<Actions>/redirectmenu/rename" "")
+; (gtk_accel_path "<Actions>/RegionList/rlShowAuto" "")
+(gtk_accel_path "<Actions>/Editor/select-all-before-playhead" "<%PRIMARY%>p")
+; (gtk_accel_path "<Actions>/Main/Session" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-start" "<%TERTIARY%>F1")
+; (gtk_accel_path "<Actions>/Main/AudioFileFormat" "")
+; (gtk_accel_path "<Actions>/Transport/Transport" "")
+(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-timefx" "t")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionName" "")
+; (gtk_accel_path "<Actions>/Main/KeyMouse Actions" "")
+(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-gain" "g")
+; (gtk_accel_path "<Actions>/Snap/snap-to-frame" "")
+; (gtk_accel_path "<Actions>/Editor/SnapTo" "")
+(gtk_accel_path "<Actions>/Transport/TransitionToReverse" "<%PRIMARY%>downarrow")
+; (gtk_accel_path "<Actions>/Editor/Crossfades" "")
+; (gtk_accel_path "<Actions>/Editor/PullupPlus4" "")
+; (gtk_accel_path "<Actions>/Main/MeteringHoldTime" "")
+; (gtk_accel_path "<Actions>/Editor/PullupPlus1" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte24976" "")
+; (gtk_accel_path "<Actions>/options/FileDataFormat24bit" "")
+; (gtk_accel_path "<Actions>/Editor/SnapMode" "")
+(gtk_accel_path "<Actions>/Common/ToggleOptionsEditor" "<%WINDOW%>o")
+; (gtk_accel_path "<Actions>/Editor/PullupMinus4" "")
+(gtk_accel_path "<Actions>/Common/goto-mixer" "<%WINDOW%>m")
+; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileCreationDate" "")
+; (gtk_accel_path "<Actions>/redirectmenu/activate" "")
+(gtk_accel_path "<Actions>/Editor/extend-range-to-start-of-region" "leftanglebracket")
+; (gtk_accel_path "<Actions>/Editor/PullupMinus1" "")
+; (gtk_accel_path "<Actions>/Editor/snap-normal" "")
+(gtk_accel_path "<Actions>/Common/ToggleBigClock" "<%WINDOW%>b")
+(gtk_accel_path "<Actions>/Common/ToggleKeyEditor" "<%WINDOW%>k")
+; (gtk_accel_path "<Actions>/Snap/snap-to-asixteenthbeat" "")
+(gtk_accel_path "<Actions>/Editor/select-all-in-punch-range" "<%PRIMARY%>d")
+; (gtk_accel_path "<Actions>/redirectmenu/edit" "")
+(gtk_accel_path "<Actions>/Editor/duplicate-region" "d")
+(gtk_accel_path "<Actions>/Editor/multi-duplicate-region" "<%SECONDARY%>d")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency2048" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleWaveformsWhileRecording" "")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-right" "")
+(gtk_accel_path "<Actions>/Editor/remove-last-capture" "<%PRIMARY%>Delete")
+; (gtk_accel_path "<Actions>/options/FileHeaderFormatWAVE" "")
+(gtk_accel_path "<Actions>/Transport/GotoZero" "KP_0")
+(gtk_accel_path "<Actions>/Editor/select-all-after-edit-cursor" "<%TERTIARY%>End")
+; (gtk_accel_path "<Actions>/redirectmenu/cut" "")
+; (gtk_accel_path "<Actions>/redirectmenu/newinsert" "")
+; (gtk_accel_path "<Actions>/options/UseMMC" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffOff" "")
+;(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-object" "o")
+; (gtk_accel_path "<Actions>/Editor/PullupMinus4Plus1" "")
+; (gtk_accel_path "<Actions>/Editor/MeterHold" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-cd-frame" "")
+; (gtk_accel_path "<Actions>/options/StopTransportAtEndOfSession" "")
+; (gtk_accel_path "<Actions>/Main/Cleanup" "")
+; (gtk_accel_path "<Actions>/Main/Snapshot" "")
+; (gtk_accel_path "<Actions>/Transport/ToggleVideoSync" "")
+(gtk_accel_path "<Actions>/Transport/ToggleRoll" "space")
+; (gtk_accel_path "<Actions>/RegionList/SortBySourceFilesystem" "")
+(gtk_accel_path "<Actions>/Common/ToggleColorManager" "<%WINDOW%>c")
+; (gtk_accel_path "<Actions>/Common/About" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency32" "")
+(gtk_accel_path "<Actions>/Editor/playhead-to-edit" "Return")
+; (gtk_accel_path "<Actions>/options/FileHeaderFormatWAVE64" "")
+(gtk_accel_path "<Actions>/Editor/brush-at-mouse" "F3")
+; (gtk_accel_path "<Actions>/RegionList/rlShowAll" "")
+(gtk_accel_path "<Actions>/Transport/Rewind" "<%PRIMARY%>leftarrow")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionTimestamp" "")
+; (gtk_accel_path "<Actions>/options/VerifyRemoveLastCapture" "")
+; (gtk_accel_path "<Actions>/options/OutputAutoConnectPhysical" "")
+; (gtk_accel_path "<Actions>/options/SendMMC" "")
+; (gtk_accel_path "<Actions>/Editor/toggle-auto-xfades" "")
+; (gtk_accel_path "<Actions>/Main/AudioFileFormatHeader" "")
+; (gtk_accel_path "<Actions>/options/MeterHoldShort" "")
+; (gtk_accel_path "<Actions>/options/MeterHoldMedium" "")
+(gtk_accel_path "<Actions>/Editor/select-all-before-edit-cursor" "<%PRIMARY%>e")
+; (gtk_accel_path "<Actions>/Editor/Subframes80" "")
+; (gtk_accel_path "<Actions>/options/FileHeaderFormatCAF" "")
+(gtk_accel_path "<Actions>/Common/ToggleLocations" "<%WINDOW%>l")
+; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurface" "")
+(gtk_accel_path "<Actions>/Editor/editor-delete" "BackSpace")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency256" "")
+(gtk_accel_path "<Actions>/Editor/select-all-between-cursors" "F16")
+; (gtk_accel_path "<Actions>/Editor/LayerAddHigher" "")
+; (gtk_accel_path "<Actions>/Editor/Solo" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency1024" "")
+; (gtk_accel_path "<Actions>/Main/ExportRangeMarkers" "")
+(gtk_accel_path "<Actions>/Editor/set-playhead" "p")
+; (gtk_accel_path "<Actions>/Editor/toggle-xfades-active" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-bar" "")
+; (gtk_accel_path "<Actions>/Editor/LayerLaterHigher" "")
+; (gtk_accel_path "<Actions>/redirectmenu/selectall" "")
+(gtk_accel_path "<Actions>/Editor/editor-copy" "<%PRIMARY%>c")
+; (gtk_accel_path "<Actions>/Snap/snap-to-quarters" "")
+(gtk_accel_path "<Actions>/Editor/temporal-zoom-out" "r")
+; (gtk_accel_path "<Actions>/options/UseSoftwareMonitoring" "")
+; (gtk_accel_path "<Actions>/Editor/Subframes100" "")
+(gtk_accel_path "<Actions>/Editor/mute-unmute-region" "<%SECONDARY%>m")
+(gtk_accel_path "<Actions>/Editor/add-location-from-playhead" "m")
+; (gtk_accel_path "<Actions>/options/OutputAutoConnectManual" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-region-sync" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-previous-region-sync" "apostrophe")
+; (gtk_accel_path "<Actions>/redirectmenu/clear" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceFeedback" "")
+; (gtk_accel_path "<Actions>/Editor/PullupPlus4Minus1" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency512" "")
+; (gtk_accel_path "<Actions>/Main/Recent" "")
+; (gtk_accel_path "<Actions>/redirectmenu/newplugin" "")
+; (gtk_accel_path "<Actions>/options/InputAutoConnectManual" "")
+; (gtk_accel_path "<Actions>/options/MeterHoldLong" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-seconds" "")
+(gtk_accel_path "<Actions>/Editor/set-fade-in-length" "q")
+(gtk_accel_path "<Actions>/Editor/toggle-fade-in-active" "<%SECONDARY%>q")
+(gtk_accel_path "<Actions>/Editor/set-fade-out-length" "e")
+(gtk_accel_path "<Actions>/Editor/toggle-fade-out-active" "<%SECONDARY%>e")
+(gtk_accel_path "<Actions>/Editor/trim-from-start" "<%TERTIARY%>braceleft")
+(gtk_accel_path "<Actions>/Editor/trim-to-end" "<%TERTIARY%>braceright")
+(gtk_accel_path "<Actions>/Editor/trim-front" "a")
+(gtk_accel_path "<Actions>/Editor/trim-back" "s")
+(gtk_accel_path "<Actions>/Editor/goto-mark-1" "KP_1")
+(gtk_accel_path "<Actions>/Editor/goto-mark-2" "KP_2")
+(gtk_accel_path "<Actions>/Editor/goto-mark-3" "KP_3")
+(gtk_accel_path "<Actions>/Editor/goto-mark-4" "KP_4")
+(gtk_accel_path "<Actions>/Editor/goto-mark-5" "KP_5")
+(gtk_accel_path "<Actions>/Editor/goto-mark-6" "KP_6")
+(gtk_accel_path "<Actions>/Editor/goto-mark-7" "KP_7")
+(gtk_accel_path "<Actions>/Editor/goto-mark-8" "KP_8")
+(gtk_accel_path "<Actions>/Editor/goto-mark-9" "KP_9")
+(gtk_accel_path "<Actions>/Transport/ToggleClick" "5")
+(gtk_accel_path "<Actions>/Transport/ToggleAutoReturn" "4")
+(gtk_accel_path "<Actions>/Transport/focus-on-clock" "KP_Divide")
+(gtk_accel_path "<Actions>/Editor/set-loop-from-edit-range" "bracketright")
+(gtk_accel_path "<Actions>/Editor/set-punch-from-edit-range" "bracketleft")
+(gtk_accel_path "<Actions>/Editor/set-loop-from-region" "<%PRIMARY%><%SECONDARY%>bracketright")
+(gtk_accel_path "<Actions>/Editor/loop-region" "<%PRIMARY%>bracketright")
+(gtk_accel_path "<Actions>/Editor/toggle-zoom" "o")
+(gtk_accel_path "<Actions>/Editor/zoom-to-region" "y")
+(gtk_accel_path "<Actions>/Editor/pitch-shift-region" "F5")
+(gtk_accel_path "<Actions>/Editor/play-from-edit-point-and-return" "<%LEVEL4%>space")
+
diff --git a/gtk2_ardour/ardour-sae-de.bindings.in b/gtk2_ardour/ardour-sae-de.bindings.in
new file mode 100644 (file)
index 0000000..7feaed2
--- /dev/null
@@ -0,0 +1,346 @@
+; ardour GtkAccelMap rc-file         -*- scheme -*-
+; this file is an automated accelerator map dump
+;
+; (gtk_accel_path "<Actions>/RegionList/RegionListSort" "")
+(gtk_accel_path "<Actions>/Common/Quit" "<%PRIMARY%>q")
+(gtk_accel_path "<Actions>/Common/Save" "<%PRIMARY%>s")
+; (gtk_accel_path "<Actions>/Editor/Pullup" "")
+(gtk_accel_path "<Actions>/Editor/zoom-to-session" "<%SECONDARY%>z")
+; (gtk_accel_path "<Actions>/JACK/JACKReconnect" "")
+; (gtk_accel_path "<Actions>/Editor/Autoconnect" "")
+; (gtk_accel_path "<Actions>/Editor/Edit" "")
+(gtk_accel_path "<Actions>/Editor/cycle-edit-point" "asciicircum")
+(gtk_accel_path "<Actions>/Editor/cycle-edit-point-with-marker" "<%SECONDARY%>asciicircum")
+(gtk_accel_path "<Actions>/Editor/toggle-edit-mode" "1")
+(gtk_accel_path "<Actions>/Editor/cycle-snap-mode" "2")
+(gtk_accel_path "<Actions>/Editor/cycle-snap-choice" "3")
+; (gtk_accel_path "<Actions>/redirectmenu/copy" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffFaster" "")
+(gtk_accel_path "<Actions>/Transport/ToggleRollForgetCapture" "<%PRIMARY%>space")
+(gtk_accel_path "<Actions>/Transport/record-roll" "<%TERTIARY%>space")
+(gtk_accel_path "<Actions>/Transport/Record" "<%TERTIARY%>r")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionLength" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffSlowest" "")
+; (gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-sync" "")
+; (gtk_accel_path "<Actions>/redirectmenu/deactivate_all" "")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionPosition" "")
+; (gtk_accel_path "<Actions>/Editor/ZoomFocus" "")
+(gtk_accel_path "<Actions>/Editor/addExistingAudioFiles" "<%PRIMARY%>i")
+; (gtk_accel_path "<Actions>/options/MeterFalloffSlow" "")
+; (gtk_accel_path "<Actions>/RegionList/rlHide" "")
+; (gtk_accel_path "<Actions>/Main/Metering" "")
+(gtk_accel_path "<Actions>/Editor/playhead-to-next-region-boundary" "rightarrow")
+(gtk_accel_path "<Actions>/Editor/selected-marker-to-next-region-boundary" "<%PRIMARY%><%TERTIARY%>rightarrow")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-playhead" "")
+; (gtk_accel_path "<Actions>/Editor/center-edit-cursor" "")
+; (gtk_accel_path "<Actions>/Editor/Monitoring" "")
+; (gtk_accel_path "<Actions>/redirectmenu/deactivate" "")
+; (gtk_accel_path "<Actions>/options/LatchedRecordEnable" "")
+; (gtk_accel_path "<Actions>/Transport/TogglePunchIn" "")
+; (gtk_accel_path "<Actions>/ShuttleActions/SetShuttleUnitsPercentage" "")
+(gtk_accel_path "<Actions>/Main/Close" "<%PRIMARY%>w")
+(gtk_accel_path "<Actions>/Main/New" "<%PRIMARY%>n")
+(gtk_accel_path "<Actions>/Editor/nudge-next-backward" "<%PRIMARY%>KP_Subtract")
+; (gtk_accel_path "<Actions>/Editor/EditSelectRangeOptions" "")
+; (gtk_accel_path "<Actions>/Transport/ToggleTimeMaster" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-thirds" "")
+(gtk_accel_path "<Actions>/Editor/align-regions-start-relative" "<%LEVEL4%>less")
+(gtk_accel_path "<Actions>/Editor/align-regions-start" "<%LEVEL4%><%SECONDARY%>less")
+; (gtk_accel_path "<Actions>/Main/Export" "<%PRIMARY%>e")
+(gtk_accel_path "<Actions>/Editor/jump-forward-to-mark" "<%PRIMARY%>KP_6")
+; (gtk_accel_path "<Actions>/Editor/Smpte30" "")
+; (gtk_accel_path "<Actions>/Editor/playhead-to-range-start" "")
+; (gtk_accel_path "<Actions>/Editor/Subframes" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte2997drop" "")
+(gtk_accel_path "<Actions>/Main/AddTrackBus" "<%PRIMARY%><%TERTIARY%>n")
+(gtk_accel_path "<Actions>/Editor/align-regions-end" "<%PRIMARY%><%SECONDARY%>less")
+(gtk_accel_path "<Actions>/Editor/align-regions-end-relative" "<%PRIMARY%>less")
+; (gtk_accel_path "<Actions>/JACK/JACKDisconnect" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffFast" "")
+; (gtk_accel_path "<Actions>/options/FileDataFormatFloat" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-region-end" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-next-region-sync" "semicolon")
+; (gtk_accel_path "<Actions>/options/StopRecordingOnXrun" "")
+; (gtk_accel_path "<Actions>/RegionList/SortDescending" "")
+; (gtk_accel_path "<Actions>/options/DoNotRunPluginsWhileRecording" "")
+; (gtk_accel_path "<Actions>/Editor/PullupNone" "")
+(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-range" "r")
+(gtk_accel_path "<Actions>/Editor/jump-backward-to-mark" "<%PRIMARY%>KP_4")
+; (gtk_accel_path "<Actions>/Main/AudioFileFormatData" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffFastest" "")
+(gtk_accel_path "<Actions>/Editor/audition-at-mouse" "w")
+(gtk_accel_path "<Actions>/Transport/Forward" "<%PRIMARY%>rightarrow")
+; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-seconds" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-frame" "")
+; (gtk_accel_path "<Actions>/Main/ExportSelection" "")
+; (gtk_accel_path "<Actions>/options/StopPluginsWithTransport" "")
+(gtk_accel_path "<Actions>/Editor/editor-paste" "<%PRIMARY%>v")
+(gtk_accel_path "<Actions>/Editor/scroll-tracks-down" "Page_Down")
+(gtk_accel_path "<Actions>/Editor/select-next-route" "downarrow")
+(gtk_accel_path "<Actions>/Editor/select-prev-route" "uparrow")
+; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-minutes" "")
+; (gtk_accel_path "<Actions>/Main/FlushWastebasket" "")
+(gtk_accel_path "<Actions>/Editor/normalize-region" "n")
+(gtk_accel_path "<Actions>/Editor/nudge-forward" "h")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionEndinFile" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleMeasureVisibility" "")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-center" "")
+(gtk_accel_path "<Actions>/Editor/nudge-backward" "g")
+; (gtk_accel_path "<Actions>/options/LatchedSolo" "")
+; (gtk_accel_path "<Actions>/options/MeterHoldOff" "")
+; (gtk_accel_path "<Actions>/options/OutputAutoConnectMaster" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency64" "")
+(gtk_accel_path "<Actions>/Editor/undo" "<%PRIMARY%>z")
+(gtk_accel_path "<Actions>/Editor/insert-region" "i")
+; (gtk_accel_path "<Actions>/Editor/center-playhead" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-region-start" "")
+; (gtk_accel_path "<Actions>/Editor/View" "")
+; (gtk_accel_path "<Actions>/Editor/Layering" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency4096" "")
+(gtk_accel_path "<Actions>/Editor/scroll-tracks-up" "Page_Up")
+(gtk_accel_path "<Actions>/Editor/set-edit-point" "g")
+; (gtk_accel_path "<Actions>/Editor/Smpte30drop" "")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-edit" "")
+(gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-boundary" "leftarrow")
+(gtk_accel_path "<Actions>/Editor/selected-marker-to-previous-region-boundary" "<%PRIMARY%><%TERTIARY%>leftarrow")
+; (gtk_accel_path "<Actions>/Editor/EditCursorMovementOptions" "")
+; (gtk_accel_path "<Actions>/redirectmenu/activate_all" "")
+; (gtk_accel_path "<Actions>/redirectmenu/paste" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte25" "")
+; (gtk_accel_path "<Actions>/options/RegionEquivalentsOverlap" "")
+; (gtk_accel_path "<Actions>/Main/MeteringFallOffRate" "")
+; (gtk_accel_path "<Actions>/options/UseHardwareMonitoring" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte24" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-mark" "")
+; (gtk_accel_path "<Actions>/Editor/CrossfadesShort" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte5994" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency8192" "")
+; (gtk_accel_path "<Actions>/Editor/toggle-xfades-visible" "")
+(gtk_accel_path "<Actions>/Editor/extend-range-to-end-of-region" "rightanglebracket")
+(gtk_accel_path "<Actions>/Editor/start-range" "F1")
+; (gtk_accel_path "<Actions>/ShuttleActions/SetShuttleUnitsSemitones" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency128" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-beat" "")
+; (gtk_accel_path "<Actions>/Editor/RegionEditOps" "")
+; (gtk_accel_path "<Actions>/Editor/snap-magnetic" "")
+; (gtk_accel_path "<Actions>/Editor/playhead-to-range-end" "")
+(gtk_accel_path "<Actions>/Editor/scroll-playhead-forward" "<%TERTIARY%>rightarrow")
+(gtk_accel_path "<Actions>/Editor/align-regions-sync-relative" "less")
+(gtk_accel_path "<Actions>/Editor/align-regions-sync" "<%SECONDARY%>less")
+; (gtk_accel_path "<Actions>/Editor/EditSelectRegionOptions" "")
+(gtk_accel_path "<Actions>/Editor/crop" "c")
+; (gtk_accel_path "<Actions>/redirectmenu/newsend" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceSubMenu" "")
+; (gtk_accel_path "<Actions>/Editor/MeterFalloff" "")
+; (gtk_accel_path "<Actions>/RegionList/rlRemove" "")
+(gtk_accel_path "<Actions>/Transport/GotoStart" "Home")
+(gtk_accel_path "<Actions>/Editor/select-all-before-edit-cursor" "<%TERTIARY%>Home")
+(gtk_accel_path "<Actions>/Editor/scroll-playhead-backward" "<%TERTIARY%>leftarrow")
+(gtk_accel_path "<Actions>/Editor/split-region" "y")
+; (gtk_accel_path "<Actions>/Transport/ToggleAutoInput" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-thirtyseconds" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-minutes" "")
+; (gtk_accel_path "<Actions>/Main/Windows" "")
+; (gtk_accel_path "<Actions>/Main/CleanupUnused" "")
+; (gtk_accel_path "<Actions>/redirectmenu/deselectall" "<%PRIMARY%><%TERTIARY%>a")
+; (gtk_accel_path "<Actions>/options/SoloViaBus" "")
+; (gtk_accel_path "<Actions>/RegionList/rlAudition" "")
+(gtk_accel_path "<Actions>/Editor/set-region-sync-position" "u")
+; (gtk_accel_path "<Actions>/Editor/PullupPlus4Plus1" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-region-boundary" "")
+; (gtk_accel_path "<Actions>/JACK/JACK" "")
+(gtk_accel_path "<Actions>/Editor/editor-cut" "<%PRIMARY%>x")
+(gtk_accel_path "<Actions>/Editor/editor-separate" "x")
+; (gtk_accel_path "<Actions>/RegionList/SortAscending" "")
+; (gtk_accel_path "<Actions>/Main/Help" "")
+; (gtk_accel_path "<Actions>/options/UseExternalMonitoring" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte23976" "")
+(gtk_accel_path "<Actions>/Common/goto-editor" "<%PRIMARY%>e")
+(gtk_accel_path "<Actions>/Editor/select-all" "<%PRIMARY%>a")
+(gtk_accel_path "<Actions>/Editor/invert-selection" "<%TERTIARY%>i")
+(gtk_accel_path "<Actions>/Editor/nudge-next-forward" "<%PRIMARY%>KP_Add")
+; (gtk_accel_path "<Actions>/options/ShowSoloMutes" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-eighths" "")
+(gtk_accel_path "<Actions>/Editor/select-all-after-playhead" "<%TERTIARY%><%PRIMARY%>End")
+(gtk_accel_path "<Actions>/Common/ToggleMaximalEditor" "F11")
+; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileLength" "")
+; (gtk_accel_path "<Actions>/Editor/Timecode" "")
+; (gtk_accel_path "<Actions>/Transport/PlaySelection" "")
+; (gtk_accel_path "<Actions>/Editor/PullupMinus4Minus1" "")
+(gtk_accel_path "<Actions>/Editor/select-all-after-edit-cursor" "<%TERTIARY%><%PRIMARY%>e")
+; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileName" "")
+(gtk_accel_path "<Actions>/Editor/finish-range" "F2")
+(gtk_accel_path "<Actions>/Editor/select-range-between-cursors" "F16")
+(gtk_accel_path "<Actions>/Transport/Loop" "l")
+; (gtk_accel_path "<Actions>/Editor/CrossfadesFull" "")
+(gtk_accel_path "<Actions>/Editor/finish-add-range" "<%TERTIARY%><%PRIMARY%>KP_Up")
+; (gtk_accel_path "<Actions>/options/SendMTC" "")
+; (gtk_accel_path "<Actions>/Transport/TogglePunchOut" "")
+(gtk_accel_path "<Actions>/Editor/select-all-in-loop-range" "<%TERTIARY%>l")
+(gtk_accel_path "<Actions>/Editor/show-editor-mixer" "<%TERTIARY%>e")
+; (gtk_accel_path "<Actions>/options/SoloInPlace" "")
+; (gtk_accel_path "<Actions>/Main/Options" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffMedium" "")
+(gtk_accel_path "<Actions>/Editor/toggle-follow-playhead" "f")
+; (gtk_accel_path "<Actions>/Main/SaveTemplate" "")
+(gtk_accel_path "<Actions>/Transport/TransitionToRoll" "<%PRIMARY%>uparrow")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionStartinFile" "")
+; (gtk_accel_path "<Actions>/options/GainReduceFastTransport" "")
+; (gtk_accel_path "<Actions>/Common/ToggleInspector" "")
+; (gtk_accel_path "<Actions>/Transport/ToggleAutoPlay" "")
+; (gtk_accel_path "<Actions>/Editor/playhead-to-next-region-sync" "")
+(gtk_accel_path "<Actions>/Editor/edit-to-playhead" "<%SECONDARY%>Return")
+; (gtk_accel_path "<Actions>/Editor/LayerMoveAddHigher" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte60" "")
+(gtk_accel_path "<Actions>/Main/Open" "<%PRIMARY%>o")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-left" "")
+; (gtk_accel_path "<Actions>/Main/TransportOptions" "")
+; (gtk_accel_path "<Actions>/Main/ControlSurfaces" "")
+; (gtk_accel_path "<Actions>/options/FileHeaderFormatBWF" "")
+; (gtk_accel_path "<Actions>/Transport/ToggleAutoReturn" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte2997" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleWaveformVisibility" "")
+(gtk_accel_path "<Actions>/Editor/redo" "<%PRIMARY%>r")
+(gtk_accel_path "<Actions>/Main/ExportSession" "<%PRIMARY%>e")
+; (gtk_accel_path "<Actions>/options/InputAutoConnectPhysical" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-edit-cursor" "")
+(gtk_accel_path "<Actions>/Editor/temporal-zoom-in" "t")
+; (gtk_accel_path "<Actions>/JACK/Latency" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-end" "<%TERTIARY%>F2")
+; (gtk_accel_path "<Actions>/redirectmenu/rename" "")
+; (gtk_accel_path "<Actions>/RegionList/rlShowAuto" "")
+(gtk_accel_path "<Actions>/Editor/select-all-before-playhead" "<%TERTIARY%>Home")
+; (gtk_accel_path "<Actions>/Main/Session" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-start" "<%TERTIARY%>F1")
+; (gtk_accel_path "<Actions>/Main/AudioFileFormat" "")
+; (gtk_accel_path "<Actions>/Transport/Transport" "")
+; (gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-timefx" "t")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionName" "")
+; (gtk_accel_path "<Actions>/Main/KeyMouse Actions" "")
+(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-gain" "g")
+; (gtk_accel_path "<Actions>/Snap/snap-to-frame" "")
+; (gtk_accel_path "<Actions>/Editor/SnapTo" "")
+(gtk_accel_path "<Actions>/Transport/TransitionToReverse" "<%PRIMARY%>downarrow")
+; (gtk_accel_path "<Actions>/Editor/Crossfades" "")
+; (gtk_accel_path "<Actions>/Editor/PullupPlus4" "")
+; (gtk_accel_path "<Actions>/Main/MeteringHoldTime" "")
+; (gtk_accel_path "<Actions>/Editor/PullupPlus1" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte24976" "")
+; (gtk_accel_path "<Actions>/options/FileDataFormat24bit" "")
+; (gtk_accel_path "<Actions>/Editor/SnapMode" "")
+(gtk_accel_path "<Actions>/Common/ToggleOptionsEditor" "<%PRIMARY%>o")
+; (gtk_accel_path "<Actions>/Editor/PullupMinus4" "")
+(gtk_accel_path "<Actions>/Common/goto-mixer" "<%PRIMARY%>m")
+; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileCreationDate" "")
+; (gtk_accel_path "<Actions>/redirectmenu/activate" "")
+(gtk_accel_path "<Actions>/Editor/extend-range-to-start-of-region" "leftanglebracket")
+; (gtk_accel_path "<Actions>/Editor/PullupMinus1" "")
+; (gtk_accel_path "<Actions>/Editor/snap-normal" "")
+(gtk_accel_path "<Actions>/Common/ToggleBigClock" "<%PRIMARY%>b")
+(gtk_accel_path "<Actions>/Common/ToggleKeyEditor" "<%PRIMARY%>k")
+; (gtk_accel_path "<Actions>/Snap/snap-to-asixteenthbeat" "")
+(gtk_accel_path "<Actions>/Editor/select-all-in-punch-range" "<%TERTIARY%>p")
+; (gtk_accel_path "<Actions>/redirectmenu/edit" "")
+(gtk_accel_path "<Actions>/Editor/duplicate-region" "d")
+(gtk_accel_path "<Actions>/Editor/multi-duplicate-region" "<%SECONDARY%>d")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency2048" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleWaveformsWhileRecording" "")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-right" "")
+(gtk_accel_path "<Actions>/Editor/remove-last-capture" "<%PRIMARY%>Delete")
+; (gtk_accel_path "<Actions>/options/FileHeaderFormatWAVE" "")
+(gtk_accel_path "<Actions>/Transport/GotoZero" "KP_Insert")
+(gtk_accel_path "<Actions>/Editor/select-all-after-edit-cursor" "<%TERTIARY%>End")
+; (gtk_accel_path "<Actions>/redirectmenu/cut" "")
+; (gtk_accel_path "<Actions>/redirectmenu/newinsert" "")
+; (gtk_accel_path "<Actions>/options/UseMMC" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffOff" "")
+;(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-object" "o")
+; (gtk_accel_path "<Actions>/Editor/PullupMinus4Plus1" "")
+; (gtk_accel_path "<Actions>/Editor/MeterHold" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-cd-frame" "")
+; (gtk_accel_path "<Actions>/options/StopTransportAtEndOfSession" "")
+; (gtk_accel_path "<Actions>/Main/Cleanup" "")
+(gtk_accel_path "<Actions>/Main/Snapshot" "<%PRIMARY%><%TERTIARY%>s")
+; (gtk_accel_path "<Actions>/Transport/ToggleVideoSync" "")
+(gtk_accel_path "<Actions>/Transport/ToggleRoll" "space")
+; (gtk_accel_path "<Actions>/RegionList/SortBySourceFilesystem" "")
+(gtk_accel_path "<Actions>/Common/ToggleColorManager" "<%PRIMARY%>c")
+; (gtk_accel_path "<Actions>/Common/About" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency32" "")
+(gtk_accel_path "<Actions>/Editor/playhead-to-edit" "Return")
+; (gtk_accel_path "<Actions>/options/FileHeaderFormatWAVE64" "")
+(gtk_accel_path "<Actions>/Editor/brush-at-mouse" "F3")
+; (gtk_accel_path "<Actions>/RegionList/rlShowAll" "")
+(gtk_accel_path "<Actions>/Transport/Rewind" "<%PRIMARY%>leftarrow")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionTimestamp" "")
+; (gtk_accel_path "<Actions>/options/VerifyRemoveLastCapture" "")
+; (gtk_accel_path "<Actions>/options/OutputAutoConnectPhysical" "")
+; (gtk_accel_path "<Actions>/options/SendMMC" "")
+; (gtk_accel_path "<Actions>/Editor/toggle-auto-xfades" "")
+; (gtk_accel_path "<Actions>/Main/AudioFileFormatHeader" "")
+; (gtk_accel_path "<Actions>/options/MeterHoldShort" "")
+; (gtk_accel_path "<Actions>/options/MeterHoldMedium" "")
+(gtk_accel_path "<Actions>/Editor/select-all-before-edit-cursor" "<%PRIMARY%>e")
+; (gtk_accel_path "<Actions>/Editor/Subframes80" "")
+; (gtk_accel_path "<Actions>/options/FileHeaderFormatCAF" "")
+(gtk_accel_path "<Actions>/Common/ToggleLocations" "<%PRIMARY%>l")
+; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurface" "")
+(gtk_accel_path "<Actions>/Editor/editor-delete" "BackSpace")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency256" "")
+(gtk_accel_path "<Actions>/Editor/select-all-between-cursors" "F16")
+; (gtk_accel_path "<Actions>/Editor/LayerAddHigher" "")
+; (gtk_accel_path "<Actions>/Editor/Solo" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency1024" "")
+; (gtk_accel_path "<Actions>/Main/ExportRangeMarkers" "")
+(gtk_accel_path "<Actions>/Editor/set-playhead" "p")
+; (gtk_accel_path "<Actions>/Editor/toggle-xfades-active" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-bar" "")
+; (gtk_accel_path "<Actions>/Editor/LayerLaterHigher" "")
+; (gtk_accel_path "<Actions>/redirectmenu/selectall" "")
+(gtk_accel_path "<Actions>/Editor/editor-copy" "<%PRIMARY%>c")
+; (gtk_accel_path "<Actions>/Snap/snap-to-quarters" "")
+(gtk_accel_path "<Actions>/Editor/temporal-zoom-out" "r")
+; (gtk_accel_path "<Actions>/options/UseSoftwareMonitoring" "")
+; (gtk_accel_path "<Actions>/Editor/Subframes100" "")
+(gtk_accel_path "<Actions>/Editor/mute-unmute-region" "<%SECONDARY%>m")
+(gtk_accel_path "<Actions>/Editor/add-location-from-playhead" "m")
+; (gtk_accel_path "<Actions>/options/OutputAutoConnectManual" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-region-sync" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-previous-region-sync" "apostrophe")
+; (gtk_accel_path "<Actions>/redirectmenu/clear" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceFeedback" "")
+; (gtk_accel_path "<Actions>/Editor/PullupPlus4Minus1" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency512" "")
+(gtk_accel_path "<Actions>/Main/Recent" "<%PRIMARY%><%TERTIARY%>o")
+; (gtk_accel_path "<Actions>/redirectmenu/newplugin" "")
+; (gtk_accel_path "<Actions>/options/InputAutoConnectManual" "")
+; (gtk_accel_path "<Actions>/options/MeterHoldLong" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-seconds" "")
+(gtk_accel_path "<Actions>/Editor/set-fade-in-length" "q")
+(gtk_accel_path "<Actions>/Editor/toggle-fade-in-active" "<%SECONDARY%>q")
+(gtk_accel_path "<Actions>/Editor/set-fade-out-length" "e")
+(gtk_accel_path "<Actions>/Editor/toggle-fade-out-active" "<%SECONDARY%>e")
+(gtk_accel_path "<Actions>/Editor/trim-from-start" "<%TERTIARY%>braceleft")
+(gtk_accel_path "<Actions>/Editor/trim-to-end" "<%TERTIARY%>braceright")
+(gtk_accel_path "<Actions>/Editor/trim-front" "a")
+(gtk_accel_path "<Actions>/Editor/trim-back" "s")
+(gtk_accel_path "<Actions>/Editor/goto-mark-1" "KP_1")
+(gtk_accel_path "<Actions>/Editor/goto-mark-2" "KP_2")
+(gtk_accel_path "<Actions>/Editor/goto-mark-3" "KP_3")
+(gtk_accel_path "<Actions>/Editor/goto-mark-4" "KP_4")
+(gtk_accel_path "<Actions>/Editor/goto-mark-5" "KP_5")
+(gtk_accel_path "<Actions>/Editor/goto-mark-6" "KP_6")
+(gtk_accel_path "<Actions>/Editor/goto-mark-7" "KP_7")
+(gtk_accel_path "<Actions>/Editor/goto-mark-8" "KP_8")
+(gtk_accel_path "<Actions>/Editor/goto-mark-9" "KP_9")
+(gtk_accel_path "<Actions>/Transport/ToggleClick" "5")
+(gtk_accel_path "<Actions>/Transport/ToggleAutoReturn" "4")
+(gtk_accel_path "<Actions>/Transport/focus-on-clock" "KP_Divide")
+(gtk_accel_path "<Actions>/Editor/set-loop-from-edit-range" "bracketright")
+(gtk_accel_path "<Actions>/Editor/set-punch-from-edit-range" "bracketleft")
+(gtk_accel_path "<Actions>/Editor/set-loop-from-region" "<%PRIMARY%><%SECONDARY%>bracketright")
+(gtk_accel_path "<Actions>/Editor/loop-region" "<%PRIMARY%>bracketright")
+(gtk_accel_path "<Actions>/Editor/toggle-zoom" "<%TERTIARY%>z")
+(gtk_accel_path "<Actions>/Editor/zoom-to-region" "z")
+
+
index e132329dbcd19fca7d834215bc7ab90970cd0826..a1818a99658d267d711ee61ac20ce8c6211fd220 100644 (file)
@@ -6,30 +6,36 @@
            <menuitem action='Open'/>
            <menuitem action='Recent'/>
            <menuitem action='Close'/>
+           <menuitem action='Quit'/>
            <separator/>
            <menuitem action='Save'/>
            <menuitem action='Snapshot'/>
            <menuitem action='SaveTemplate'/>
            <separator/>
            <menuitem action='AddTrackBus'/>    
+
+          <menu name='Files' action='Files'>
+              <menuitem action='addExistingAudioFiles'/>
+              <separator/>
+             <menuitem action='ExportSession'/>
+          </menu>
+
            <separator/>
            <menu name='Cleanup' action='Cleanup'>
                <menuitem action='CleanupUnused'/>
                <menuitem action='FlushWastebasket'/>
            </menu>
+           <menuitem action='ToggleOptionsEditor'/>
+           <menuitem action='About'/>
         </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='play-from-edit-point-and-return'/>
+               <menuitem action='play-edit-range'/>
+               <menuitem action='record-roll'/>
                <menuitem action='ToggleRollForgetCapture'/>
                <menuitem action='Loop'/>
-               <menuitem action='PlaySelection'/>
+               <menuitem action='loop-region'/>
                <menuitem action='set-playhead'/>
                <menuitem action='Forward'/>
                <menuitem action='Rewind'/>
                <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-boundary'/>
+               <menuitem action='playhead-to-previous-region-boundary'/>
                <menuitem action='playhead-to-next-region-sync'/>
                <menuitem action='playhead-to-previous-region-sync'/>
                <menuitem action='center-playhead'/>
+              <separator/>
                <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>
+               <menuitem action='focus-on-clock'/>
+              <separator/>
+              <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'/>
+              <separator/>
+              <menuitem action='set-loop-from-edit-range'/>
+              <menuitem action='set-loop-from-region'/>
+              <menuitem action='set-punch-from-edit-range'/>
+              <menu action='LocateToMarker'>
+                    <menuitem action='goto-mark-1'/>
+                    <menuitem action='goto-mark-2'/>
+                    <menuitem action='goto-mark-3'/>
+                    <menuitem action='goto-mark-4'/>
+                    <menuitem action='goto-mark-5'/>
+                    <menuitem action='goto-mark-6'/>
+                    <menuitem action='goto-mark-7'/>
+                    <menuitem action='goto-mark-8'/>
+                    <menuitem action='goto-mark-9'/>
+               </menu>
        </menu>
        <menu name='Edit' action='Edit'>
                <menuitem action='undo'/>
                <menuitem action='editor-copy'/>
                <menuitem action='editor-paste'/>
                <menuitem action='set-edit-point'/>
+               <menuitem action='editor-separate'/>
+               <separator/>       
               <menuitem action='remove-last-capture'/>
                <separator/>       
+               <menuitem action='select-all'/>
+               <menuitem action='deselect-all'/>
+               <menuitem action='invert-selection'/>
+               <menuitem action='select-all-after-edit-cursor'/>
+               <menuitem action='select-all-before-edit-cursor'/>
+               <menuitem action='select-all-between-cursors'/>
+               <menuitem action='select-all-within-cursors'/>
+               <menuitem action='select-all-in-punch-range'/>
+               <menuitem action='select-all-in-loop-range'/>
+              <separator/>
+               <menuitem action='select-next-route'/>
+               <menuitem action='select-prev-route'/>
+              <separator/>
               <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='selected-marker-to-next-region-boundary'/>
+                  <menuitem action='selected-marker-to-previous-region-boundary'/>
                   <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='play-selected-regions'/>
                                <menuitem action='brush-at-mouse'/>
                                <menuitem action='mute-unmute-region'/>
                        <separator/>
                        <menuitem action='set-mouse-mode-gain'/>
                        <menuitem action='set-mouse-mode-zoom'/>
                        <menuitem action='set-mouse-mode-timefx'/>
+                       <separator/>
+                       <menuitem action='cycle-edit-point'/>
+                       <menuitem action='cycle-edit-point-with-marker'/>
+                       <menuitem action='toggle-edit-mode'/>
                </menu>
-                <separator/>       
-                <menuitem action='ToggleOptionsEditor'/>
         </menu>         
-       <menu name='Select' action='Select'>
-                   <menuitem action='select-range-between-cursors'/>
-                   <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'/>
-                  <separator/>
-                   <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-within-cursors'/>
-                   <menuitem action='select-all-in-punch-range'/>
-                   <menuitem action='select-all-in-loop-range'/>
-       </menu>
        <menu name='Regions' action='Regions'>
                    <menuitem action='crop'/>
                    <menuitem action='duplicate-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'/>
                    <separator/>       
                   <menuitem action='align-regions-sync-relative'/>
                    <separator/>       
                   <menuitem action='set-fade-in-length'/>
+                  <menuitem action='toggle-fade-in-active'/>
                   <menuitem action='set-fade-out-length'/>
+                  <menuitem action='toggle-fade-out-active'/>
                    <separator/>       
-                  <menuitem action='trim-from-start'/>
-                  <menuitem action='trim-to-end'/>
+                  <menuitem action='trim-front'/>
+                  <menuitem action='trim-back'/>
                   <menuitem action='trim-region-to-loop'/>
                   <menuitem action='trim-region-to-punch'/>
+                   <separator/>       
+                  <menuitem action='pitch-shift-region'/>
        </menu>
         <menu name='View' action = 'View'>
+              <menuitem action='ToggleMaximalEditor'/>
+              <separator/>
                <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'/>
                    <menuitem action='zoom-focus-mouse'/>
                </menu>
               <menu name='SnapMode' action='SnapMode'>
+                  <menuitem action='snap-off'/>
                   <menuitem action='snap-normal'/>
                   <menuitem action='snap-magnetic'/>
+                  <separator/>
+                  <menuitem action='cycle-snap-mode'/>
               </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-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'/>
+                  <menuitem action='cycle-snap-choice'/>
                </menu>
                <separator/>
-
                <menuitem action='temporal-zoom-in'/>
                <menuitem action='temporal-zoom-out'/>
                <menuitem action='zoom-to-session'/>
+               <menuitem action='zoom-to-region'/>
+               <menuitem action='toggle-zoom'/>
                <menuitem action='scroll-tracks-down'/>
                <menuitem action='scroll-tracks-up'/>
                <menuitem action='scroll-tracks-down'/>
               <separator/>
               <menuitem action='show-editor-mixer'/>
               <menuitem action='SyncEditorAndMixerTrackOrder'/>
+               <menuitem action='ToggleMeasureVisibility'/>
               <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='ToggleKeyEditor'/>
                <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>
+               <menuitem action='LatchedSolo'/>
+               <menuitem action='link-region-and-track-selection'/>
          </menu>
-        <menu name='Help' action='Help'>
-            <menuitem action='About'/>
-       </menu>
      </menubar>
 
      <popup name='redirectmenu'>
index 2e9b4af1e94f516fa9071a23cd36efd6b2ff9617..fb26ff1b56414a4f9066d3416f22e450e2391ae3 100644 (file)
@@ -2,29 +2,31 @@
 ; this file is an automated accelerator map dump
 ;
 ; (gtk_accel_path "<Actions>/RegionList/RegionListSort" "")
-(gtk_accel_path "<Actions>/Common/Quit" "<Control>q")
-(gtk_accel_path "<Actions>/Common/Save" "<Control>s")
+(gtk_accel_path "<Actions>/Common/Quit" "<%PRIMARY%>q")
+(gtk_accel_path "<Actions>/Common/Save" "<%PRIMARY%>s")
 ; (gtk_accel_path "<Actions>/Editor/Pullup" "")
 ; (gtk_accel_path "<Actions>/Editor/zoom-to-session" "")
 ; (gtk_accel_path "<Actions>/JACK/JACKReconnect" "")
 ; (gtk_accel_path "<Actions>/Editor/Autoconnect" "")
 ; (gtk_accel_path "<Actions>/Editor/Edit" "")
-(gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-end" "<Control>comma")
+(gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-boundary" "comma")
+(gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-sync" "<%PRIMARY%>comma")
 ; (gtk_accel_path "<Actions>/processormenu/copy" "")
 ; (gtk_accel_path "<Actions>/options/MeterFalloffFaster" "")
-(gtk_accel_path "<Actions>/Transport/ToggleRollForgetCapture" "<Control>space")
-(gtk_accel_path "<Actions>/Transport/Record" "<Shift>r")
+(gtk_accel_path "<Actions>/Transport/ToggleRollForgetCapture" "<%PRIMARY%>space")
+(gtk_accel_path "<Actions>/Transport/Record" "<%TERTIARY%>r")
 ; (gtk_accel_path "<Actions>/RegionList/SortByRegionLength" "")
 ; (gtk_accel_path "<Actions>/options/MeterFalloffSlowest" "")
 ; (gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-sync" "")
 ; (gtk_accel_path "<Actions>/processormenu/deactivate_all" "")
 ; (gtk_accel_path "<Actions>/RegionList/SortByRegionPosition" "")
 ; (gtk_accel_path "<Actions>/Editor/ZoomFocus" "")
+(gtk_accel_path "<Actions>/Editor/addExistingAudioFiles" "<%SECONDARY%>i")
 ; (gtk_accel_path "<Actions>/options/MeterFalloffSlow" "")
 (gtk_accel_path "<Actions>/options/ABAllPlugins" "<Control><Alt>p")
 ; (gtk_accel_path "<Actions>/RegionList/rlHide" "")
 ; (gtk_accel_path "<Actions>/Main/Metering" "")
-(gtk_accel_path "<Actions>/Editor/playhead-to-next-region-end" "<Control>period")
+(gtk_accel_path "<Actions>/Editor/playhead-to-next-region-sync" "<%PRIMARY%>period")
 ; (gtk_accel_path "<Actions>/Zoom/zoom-focus-playhead" "")
 ; (gtk_accel_path "<Actions>/Editor/center-edit-cursor" "")
 ; (gtk_accel_path "<Actions>/Editor/Monitoring" "")
 (gtk_accel_path "<Actions>/Editor/edit-cursor-to-previous-region-start" "bracketleft")
 ; (gtk_accel_path "<Actions>/Main/Close" "")
 ; (gtk_accel_path "<Actions>/Main/New" "")
-(gtk_accel_path "<Actions>/Editor/nudge-next-backward" "<Control>KP_Subtract")
+(gtk_accel_path "<Actions>/Editor/nudge-next-backward" "<%PRIMARY%>KP_Subtract")
 ; (gtk_accel_path "<Actions>/Editor/EditSelectRangeOptions" "")
 ; (gtk_accel_path "<Actions>/Transport/ToggleTimeMaster" "")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-thirds" "")
-(gtk_accel_path "<Actions>/Editor/align-regions-start-relative" "<Shift>a")
+(gtk_accel_path "<Actions>/Editor/align-regions-start-relative" "<%TERTIARY%>a")
 ; (gtk_accel_path "<Actions>/Main/Export" "")
-(gtk_accel_path "<Actions>/Editor/jump-forward-to-mark" "<Control>KP_Right")
+(gtk_accel_path "<Actions>/Editor/jump-forward-to-mark" "<%PRIMARY%>KP_Right")
 ; (gtk_accel_path "<Actions>/Editor/Smpte30" "")
 ; (gtk_accel_path "<Actions>/Editor/playhead-to-range-start" "")
 ; (gtk_accel_path "<Actions>/Editor/Subframes" "")
 ; (gtk_accel_path "<Actions>/Editor/Smpte2997drop" "")
 ; (gtk_accel_path "<Actions>/Main/AddTrackBus" "")
-(gtk_accel_path "<Actions>/Editor/align-regions-end" "<Control><Mod2>a")
+(gtk_accel_path "<Actions>/Editor/align-regions-end" "<%PRIMARY%><%LEVEL4%>a")
 ; (gtk_accel_path "<Actions>/JACK/JACKDisconnect" "")
 ; (gtk_accel_path "<Actions>/options/MeterFalloffFast" "")
 ; (gtk_accel_path "<Actions>/options/FileDataFormatFloat" "")
 ; (gtk_accel_path "<Actions>/options/DoNotRunPluginsWhileRecording" "")
 ; (gtk_accel_path "<Actions>/Editor/PullupNone" "")
 (gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-range" "r")
-(gtk_accel_path "<Actions>/Editor/jump-backward-to-mark" "<Control>KP_Left")
+(gtk_accel_path "<Actions>/Editor/jump-backward-to-mark" "<%PRIMARY%>KP_Left")
 ; (gtk_accel_path "<Actions>/Main/AudioFileFormatData" "")
 ; (gtk_accel_path "<Actions>/options/MeterFalloffFastest" "")
 ; (gtk_accel_path "<Actions>/Editor/audition-at-mouse" "")
-(gtk_accel_path "<Actions>/Transport/Forward" "<Control>rightarrow")
+(gtk_accel_path "<Actions>/Transport/Forward" "<%PRIMARY%>rightarrow")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-seconds" "")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-frame" "")
 ; (gtk_accel_path "<Actions>/Main/ExportSelection" "")
 ; (gtk_accel_path "<Actions>/options/StopPluginsWithTransport" "")
-(gtk_accel_path "<Actions>/Editor/editor-paste" "<Control>v")
+(gtk_accel_path "<Actions>/Editor/editor-paste" "<%PRIMARY%>v")
 (gtk_accel_path "<Actions>/Editor/scroll-tracks-down" "Page_Down")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-minutes" "")
 ; (gtk_accel_path "<Actions>/Main/FlushWastebasket" "")
 ; (gtk_accel_path "<Actions>/options/MeterHoldOff" "")
 ; (gtk_accel_path "<Actions>/options/OutputAutoConnectMaster" "")
 ; (gtk_accel_path "<Actions>/JACK/JACKLatency64" "")
-(gtk_accel_path "<Actions>/Editor/undo" "<Control>z")
+(gtk_accel_path "<Actions>/Editor/undo" "<%PRIMARY%>z")
 (gtk_accel_path "<Actions>/Editor/insert-region" "i")
 ; (gtk_accel_path "<Actions>/Editor/center-playhead" "")
-(gtk_accel_path "<Actions>/Editor/edit-cursor-to-next-region-start" "bracketright")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-region-start" "")
 ; (gtk_accel_path "<Actions>/Editor/View" "")
 ; (gtk_accel_path "<Actions>/Editor/Layering" "")
@@ -94,7 +95,6 @@
 (gtk_accel_path "<Actions>/Editor/set-edit-point" "e")
 ; (gtk_accel_path "<Actions>/Editor/Smpte30drop" "")
 ; (gtk_accel_path "<Actions>/Zoom/zoom-focus-edit" "")
-(gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-start" "comma")
 ; (gtk_accel_path "<Actions>/Editor/EditCursorMovementOptions" "")
 ; (gtk_accel_path "<Actions>/processormenu/activate_all" "")
 ; (gtk_accel_path "<Actions>/Editor/addExternalAudioAsTapeTrack" "")
 ; (gtk_accel_path "<Actions>/Editor/toggle-xfades-visible" "")
 (gtk_accel_path "<Actions>/Editor/extend-range-to-end-of-region" "rightanglebracket")
 (gtk_accel_path "<Actions>/Editor/scroll-backward" "leftarrow")
-(gtk_accel_path "<Actions>/Editor/start-range" "F1")
+(gtk_accel_path "<Actions>/Editor/start-range" "<%PRIMARY%>KP_Down")
 ; (gtk_accel_path "<Actions>/ShuttleActions/SetShuttleUnitsSemitones" "")
 ; (gtk_accel_path "<Actions>/JACK/JACKLatency128" "")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-beat" "")
 ; (gtk_accel_path "<Actions>/Editor/RegionEditOps" "")
 ; (gtk_accel_path "<Actions>/Editor/snap-magnetic" "")
 ; (gtk_accel_path "<Actions>/Editor/playhead-to-range-end" "")
-(gtk_accel_path "<Actions>/Editor/scroll-playhead-forward" "<Shift>rightarrow")
+(gtk_accel_path "<Actions>/Editor/scroll-playhead-forward" "<%TERTIARY%>rightarrow")
 (gtk_accel_path "<Actions>/Editor/align-regions-sync-relative" "a")
 ; (gtk_accel_path "<Actions>/Editor/EditSelectRegionOptions" "")
 (gtk_accel_path "<Actions>/Editor/crop" "c")
 ; (gtk_accel_path "<Actions>/Editor/MeterFalloff" "")
 ; (gtk_accel_path "<Actions>/RegionList/rlRemove" "")
 (gtk_accel_path "<Actions>/Transport/GotoStart" "Home")
-(gtk_accel_path "<Actions>/Editor/scroll-playhead-backward" "<Shift>leftarrow")
+(gtk_accel_path "<Actions>/Editor/scroll-playhead-backward" "<%TERTIARY%>leftarrow")
 (gtk_accel_path "<Actions>/Editor/split-region" "s")
 ; (gtk_accel_path "<Actions>/Transport/ToggleAutoInput" "")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-thirtyseconds" "")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-minutes" "")
-(gtk_accel_path "<Actions>/Editor/align-regions-sync" "<Mod2>a")
+(gtk_accel_path "<Actions>/Editor/align-regions-sync" "<%LEVEL4%>a")
 ; (gtk_accel_path "<Actions>/Main/Windows" "")
 ; (gtk_accel_path "<Actions>/Main/CleanupUnused" "")
 ; (gtk_accel_path "<Actions>/processormenu/deselectall" "")
 ; (gtk_accel_path "<Actions>/options/SoloViaBus" "")
-(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-zoom" "z")
+(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-zoom" "<Shift>z")
 ; (gtk_accel_path "<Actions>/RegionList/rlAudition" "")
 (gtk_accel_path "<Actions>/Editor/set-region-sync-position" "v")
 ; (gtk_accel_path "<Actions>/Editor/PullupPlus4Plus1" "")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-region-boundary" "")
 ; (gtk_accel_path "<Actions>/JACK/JACK" "")
-(gtk_accel_path "<Actions>/Editor/editor-cut" "<Control>x")
+(gtk_accel_path "<Actions>/Editor/editor-cut" "<%PRIMARY%>x")
 ; (gtk_accel_path "<Actions>/RegionList/SortAscending" "")
 ; (gtk_accel_path "<Actions>/Main/Help" "")
 ; (gtk_accel_path "<Actions>/options/UseExternalMonitoring" "")
 ; (gtk_accel_path "<Actions>/Editor/Smpte23976" "")
-(gtk_accel_path "<Actions>/Common/goto-editor" "<Alt>e")
-(gtk_accel_path "<Actions>/Editor/select-all" "<Control>a")
-(gtk_accel_path "<Actions>/Editor/nudge-next-forward" "<Control>KP_Add")
+(gtk_accel_path "<Actions>/Common/goto-editor" "<%WINDOW%>e")
+(gtk_accel_path "<Actions>/Editor/select-all" "<%PRIMARY%>a")
+(gtk_accel_path "<Actions>/Editor/nudge-next-forward" "<%PRIMARY%>KP_Add")
 ; (gtk_accel_path "<Actions>/options/ShowSoloMutes" "")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-eighths" "")
-(gtk_accel_path "<Actions>/Editor/select-all-after-playhead" "<Shift><Control>p")
+(gtk_accel_path "<Actions>/Editor/select-all-after-playhead" "<%TERTIARY%><%PRIMARY%>p")
 (gtk_accel_path "<Actions>/Common/ToggleMaximalEditor" "F11")
 ; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileLength" "")
 ; (gtk_accel_path "<Actions>/Editor/Timecode" "")
 ; (gtk_accel_path "<Actions>/Transport/PlaySelection" "")
 ; (gtk_accel_path "<Actions>/Editor/PullupMinus4Minus1" "")
-(gtk_accel_path "<Actions>/Editor/select-all-after-edit-cursor" "<Shift><Control>e")
+(gtk_accel_path "<Actions>/Editor/select-all-after-edit-cursor" "<%TERTIARY%><%PRIMARY%>e")
 ; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileName" "")
-(gtk_accel_path "<Actions>/Editor/finish-range" "F2")
-(gtk_accel_path "<Actions>/Editor/select-range-between-cursors" "F3")
+(gtk_accel_path "<Actions>/Editor/finish-range" "<%PRIMARY%>KP_Up")
 (gtk_accel_path "<Actions>/Transport/Loop" "l")
 ; (gtk_accel_path "<Actions>/Editor/CrossfadesFull" "")
-(gtk_accel_path "<Actions>/Editor/finish-add-range" "<Shift><Control>KP_Up")
+(gtk_accel_path "<Actions>/Editor/finish-add-range" "<%TERTIARY%><%PRIMARY%>KP_Up")
 ; (gtk_accel_path "<Actions>/Transport/ToggleClick" "")
 ; (gtk_accel_path "<Actions>/options/SendMTC" "")
 ; (gtk_accel_path "<Actions>/Transport/TogglePunchOut" "")
-(gtk_accel_path "<Actions>/Editor/select-all-in-loop-range" "<Control>l")
-(gtk_accel_path "<Actions>/Editor/show-editor-mixer" "<Shift>e")
+(gtk_accel_path "<Actions>/Editor/select-all-in-loop-range" "<%PRIMARY%>l")
+(gtk_accel_path "<Actions>/Editor/show-editor-mixer" "<%TERTIARY%>e")
 (gtk_accel_path "<Actions>/Editor/show-editor-list" "<Shift>l")
 ; (gtk_accel_path "<Actions>/options/SoloInPlace" "")
 ; (gtk_accel_path "<Actions>/Main/Options" "")
 ; (gtk_accel_path "<Actions>/options/MeterFalloffMedium" "")
 (gtk_accel_path "<Actions>/Editor/toggle-follow-playhead" "f")
 ; (gtk_accel_path "<Actions>/Main/SaveTemplate" "")
-(gtk_accel_path "<Actions>/Transport/TransitionToRoll" "<Control>uparrow")
+(gtk_accel_path "<Actions>/Transport/TransitionToRoll" "<%PRIMARY%>uparrow")
 ; (gtk_accel_path "<Actions>/RegionList/SortByRegionStartinFile" "")
 ; (gtk_accel_path "<Actions>/options/GainReduceFastTransport" "")
 ; (gtk_accel_path "<Actions>/Common/ToggleInspector" "")
 ; (gtk_accel_path "<Actions>/Transport/ToggleAutoPlay" "")
 ; (gtk_accel_path "<Actions>/Editor/playhead-to-next-region-sync" "")
-(gtk_accel_path "<Actions>/Editor/edit-to-playhead" "<Alt>Return")
+(gtk_accel_path "<Actions>/Editor/edit-to-playhead" "<%SECONDARY%>Return")
 ; (gtk_accel_path "<Actions>/Editor/LayerMoveAddHigher" "")
 ; (gtk_accel_path "<Actions>/Editor/Smpte60" "")
 ; (gtk_accel_path "<Actions>/Main/Open" "")
 ; (gtk_accel_path "<Actions>/Transport/ToggleAutoReturn" "")
 ; (gtk_accel_path "<Actions>/Editor/Smpte2997" "")
 ; (gtk_accel_path "<Actions>/Editor/ToggleWaveformVisibility" "")
-(gtk_accel_path "<Actions>/Editor/redo" "<Control>r")
+(gtk_accel_path "<Actions>/Editor/redo" "<%PRIMARY%>r")
 ; (gtk_accel_path "<Actions>/Editor/addExternalAudioAsRegion" "")
 ; (gtk_accel_path "<Actions>/Main/ExportSession" "")
 ; (gtk_accel_path "<Actions>/options/InputAutoConnectPhysical" "")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-edit-cursor" "")
 (gtk_accel_path "<Actions>/Editor/temporal-zoom-in" "minus")
 ; (gtk_accel_path "<Actions>/JACK/Latency" "")
-(gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-end" "<Shift>F2")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-end" "F2")
 ; (gtk_accel_path "<Actions>/processormenu/rename" "")
 ; (gtk_accel_path "<Actions>/RegionList/rlShowAuto" "")
-(gtk_accel_path "<Actions>/Editor/select-all-before-playhead" "<Control>p")
+(gtk_accel_path "<Actions>/Editor/select-all-before-playhead" "<%PRIMARY%>p")
 ; (gtk_accel_path "<Actions>/Editor/addExistingAudioFiles" "")
 ; (gtk_accel_path "<Actions>/Main/Session" "")
-(gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-start" "<Shift>F1")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-start" "F1")
 ; (gtk_accel_path "<Actions>/Main/AudioFileFormat" "")
 ; (gtk_accel_path "<Actions>/Transport/Transport" "")
 (gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-timefx" "t")
 (gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-gain" "g")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-frame" "")
 ; (gtk_accel_path "<Actions>/Editor/SnapTo" "")
-(gtk_accel_path "<Actions>/Transport/TransitionToReverse" "<Control>downarrow")
+(gtk_accel_path "<Actions>/Transport/TransitionToReverse" "<%PRIMARY%>downarrow")
 ; (gtk_accel_path "<Actions>/Editor/Crossfades" "")
 ; (gtk_accel_path "<Actions>/Editor/PullupPlus4" "")
 (gtk_accel_path "<Actions>/Editor/add-location-from-playhead" "KP_Enter")
-(gtk_accel_path "<Actions>/Editor/edit-cursor-to-previous-region-end" "<Control>bracketleft")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-previous-region-end" "<%PRIMARY%>bracketleft")
 ; (gtk_accel_path "<Actions>/Main/MeteringHoldTime" "")
 ; (gtk_accel_path "<Actions>/Editor/PullupPlus1" "")
 ; (gtk_accel_path "<Actions>/Editor/Smpte24976" "")
 ; (gtk_accel_path "<Actions>/options/FileDataFormat24bit" "")
 ; (gtk_accel_path "<Actions>/Editor/SnapMode" "")
-(gtk_accel_path "<Actions>/Common/ToggleOptionsEditor" "<Control>o")
+(gtk_accel_path "<Actions>/Common/ToggleOptionsEditor" "<%WINDOW%>o")
 ; (gtk_accel_path "<Actions>/Editor/PullupMinus4" "")
-(gtk_accel_path "<Actions>/Common/goto-mixer" "<Alt>m")
+(gtk_accel_path "<Actions>/Common/goto-mixer" "<%WINDOW%>m")
 ; (gtk_accel_path "<Actions>/Editor/addExternalAudioToTrack" "")
 ; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileCreationDate" "")
 ; (gtk_accel_path "<Actions>/processormenu/activate" "")
 (gtk_accel_path "<Actions>/Editor/extend-range-to-start-of-region" "leftanglebracket")
 ; (gtk_accel_path "<Actions>/Editor/PullupMinus1" "")
 ; (gtk_accel_path "<Actions>/Editor/snap-normal" "")
-; (gtk_accel_path "<Actions>/Editor/addExternalAudioAsTrack" "")
-(gtk_accel_path "<Actions>/Common/ToggleBigClock" "<Alt>b")
+(gtk_accel_path "<Actions>/Common/ToggleBigClock" "<%WINDOW%>b")
+(gtk_accel_path "<Actions>/Common/ToggleKeyEditor" "<%WINDOW%>k")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-asixteenthbeat" "")
-(gtk_accel_path "<Actions>/Editor/select-all-in-punch-range" "<Control>d")
+(gtk_accel_path "<Actions>/Editor/select-all-in-punch-range" "<%PRIMARY%>d")
 ; (gtk_accel_path "<Actions>/processormenu/edit" "")
 (gtk_accel_path "<Actions>/Editor/duplicate-region" "d")
 ; (gtk_accel_path "<Actions>/JACK/JACKLatency2048" "")
 ; (gtk_accel_path "<Actions>/Editor/ToggleWaveformsWhileRecording" "")
 ; (gtk_accel_path "<Actions>/Zoom/zoom-focus-right" "")
-(gtk_accel_path "<Actions>/Editor/remove-last-capture" "<Control>Delete")
+(gtk_accel_path "<Actions>/Editor/remove-last-capture" "<%PRIMARY%>Delete")
 ; (gtk_accel_path "<Actions>/options/FileHeaderFormatWAVE" "")
-(gtk_accel_path "<Actions>/Transport/GotoZero" "KP_Insert")
+(gtk_accel_path "<Actions>/Transport/GotoZero" "KP_0")
 (gtk_accel_path "<Actions>/Transport/GotoEnd" "End")
 ; (gtk_accel_path "<Actions>/processormenu/cut" "")
 ; (gtk_accel_path "<Actions>/processormenu/newinsert" "")
 ; (gtk_accel_path "<Actions>/Transport/ToggleVideoSync" "")
 (gtk_accel_path "<Actions>/Transport/ToggleRoll" "space")
 ; (gtk_accel_path "<Actions>/RegionList/SortBySourceFilesystem" "")
-(gtk_accel_path "<Actions>/Common/ToggleColorManager" "<Alt>c")
+(gtk_accel_path "<Actions>/Common/ToggleColorManager" "<%WINDOW%>c")
 ; (gtk_accel_path "<Actions>/Common/About" "")
 ; (gtk_accel_path "<Actions>/JACK/JACKLatency32" "")
 (gtk_accel_path "<Actions>/Editor/playhead-to-edit" "Return")
 ; (gtk_accel_path "<Actions>/options/FileHeaderFormatWAVE64" "")
-(gtk_accel_path "<Actions>/Editor/brush-at-mouse" "<Control>b")
+(gtk_accel_path "<Actions>/Editor/brush-at-mouse" "<%PRIMARY%>b")
 ; (gtk_accel_path "<Actions>/RegionList/rlShowAll" "")
-(gtk_accel_path "<Actions>/Transport/Rewind" "<Control>leftarrow")
+(gtk_accel_path "<Actions>/Transport/Rewind" "<%PRIMARY%>leftarrow")
 ; (gtk_accel_path "<Actions>/RegionList/SortByRegionTimestamp" "")
 ; (gtk_accel_path "<Actions>/options/VerifyRemoveLastCapture" "")
 ; (gtk_accel_path "<Actions>/options/OutputAutoConnectPhysical" "")
 (gtk_accel_path "<Actions>/Editor/step-tracks-up" "uparrow")
-(gtk_accel_path "<Actions>/Editor/playhead-to-next-region-start" "period")
+(gtk_accel_path "<Actions>/Editor/playhead-to-next-region-boundary" "period")
 ; (gtk_accel_path "<Actions>/options/SendMMC" "")
 ; (gtk_accel_path "<Actions>/Editor/toggle-auto-xfades" "")
 ; (gtk_accel_path "<Actions>/Main/AudioFileFormatHeader" "")
 ; (gtk_accel_path "<Actions>/options/MeterHoldShort" "")
 ; (gtk_accel_path "<Actions>/options/MeterHoldMedium" "")
-(gtk_accel_path "<Actions>/Editor/select-all-before-edit-cursor" "<Control>e")
+(gtk_accel_path "<Actions>/Editor/select-all-before-edit-cursor" "<%PRIMARY%>e")
 ; (gtk_accel_path "<Actions>/Editor/Subframes80" "")
 ; (gtk_accel_path "<Actions>/options/FileHeaderFormatCAF" "")
-(gtk_accel_path "<Actions>/Common/ToggleLocations" "<Alt>l")
+(gtk_accel_path "<Actions>/Common/ToggleLocations" "<%WINDOW%>l")
 ; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurface" "")
 (gtk_accel_path "<Actions>/Editor/editor-delete" "Delete")
 ; (gtk_accel_path "<Actions>/JACK/JACKLatency256" "")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-bar" "")
 ; (gtk_accel_path "<Actions>/Editor/LayerLaterHigher" "")
 ; (gtk_accel_path "<Actions>/processormenu/selectall" "")
-(gtk_accel_path "<Actions>/Editor/editor-copy" "<Control>c")
+(gtk_accel_path "<Actions>/Editor/editor-copy" "<%PRIMARY%>c")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-quarters" "")
 (gtk_accel_path "<Actions>/Editor/temporal-zoom-out" "equal")
 ; (gtk_accel_path "<Actions>/options/UseSoftwareMonitoring" "")
 ; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceFeedback" "")
 ; (gtk_accel_path "<Actions>/Editor/PullupPlus4Minus1" "")
 ; (gtk_accel_path "<Actions>/JACK/JACKLatency512" "")
-(gtk_accel_path "<Actions>/Editor/edit-cursor-to-next-region-end" "<Control>bracketright")
 ; (gtk_accel_path "<Actions>/Main/Recent" "")
 ; (gtk_accel_path "<Actions>/processormenu/newplugin" "")
 ; (gtk_accel_path "<Actions>/options/InputAutoConnectManual" "")
 ; (gtk_accel_path "<Actions>/options/MeterHoldLong" "")
 ; (gtk_accel_path "<Actions>/Snap/snap-to-seconds" "")
+(gtk_accel_path "<Actions>/Editor/cycle-edit-point" "grave")
+(gtk_accel_path "<Actions>/Editor/toggle-edit-mode" "1")
+(gtk_accel_path "<Actions>/Editor/cycle-snap-mode" "2")
+(gtk_accel_path "<Actions>/Editor/cycle-snap-choice" "3")
 (gtk_accel_path "<Actions>/Editor/set-fade-in-length" "slash")
 (gtk_accel_path "<Actions>/Editor/set-fade-out-length" "backslash")
-(gtk_accel_path "<Actions>/Editor/trim-from-start" "<Shift>braceleft")
-(gtk_accel_path "<Actions>/Editor/trim-to-end" "<Shift>braceright")
+(gtk_accel_path "<Actions>/Editor/trim-from-start" "<%TERTIARY%>braceleft")
+(gtk_accel_path "<Actions>/Editor/trim-to-end" "<%TERTIARY%>braceright")
+;(gtk_accel_path "<Actions>/Editor/trim-front" "a")
+;(gtk_accel_path "<Actions>/Editor/trim-back" "s")
+(gtk_accel_path "<Actions>/Editor/goto-mark-1" "KP_1")
+(gtk_accel_path "<Actions>/Editor/goto-mark-2" "KP_2")
+(gtk_accel_path "<Actions>/Editor/goto-mark-3" "KP_3")
+(gtk_accel_path "<Actions>/Editor/goto-mark-4" "KP_4")
+(gtk_accel_path "<Actions>/Editor/goto-mark-5" "KP_5")
+(gtk_accel_path "<Actions>/Editor/goto-mark-6" "KP_6")
+(gtk_accel_path "<Actions>/Editor/goto-mark-7" "KP_7")
+(gtk_accel_path "<Actions>/Editor/goto-mark-8" "KP_8")
+(gtk_accel_path "<Actions>/Editor/goto-mark-9" "KP_9")
+(gtk_accel_path "<Actions>/Transport/ToggleClick" "5")
+(gtk_accel_path "<Actions>/Transport/ToggleAutoReturn" "4")
+(gtk_accel_path "<Actions>/Transport/focus-on-clock" "KP_Divide")
+(gtk_accel_path "<Actions>/Editor/set-loop-from-edit-range" "bracketright")
+(gtk_accel_path "<Actions>/Editor/set-punch-from-edit-range" "bracketleft")
+(gtk_accel_path "<Actions>/Editor/set-loop-from-region" "<%PRIMARY%><%SECONDARY%>bracketright")
+(gtk_accel_path "<Actions>/Editor/toggle-zoom" "<%TERTIARY%>z")
+(gtk_accel_path "<Actions>/Editor/zoom-to-region" "z")
index 6bcc0d7898ef9139611f8429c344e42bba008fd2..11e75137dd7dbffd9e87bdbffdae8b0ee7a52c4d 100644 (file)
         </menu>
         <menu name='Transport' action='Transport'>
                <menuitem action='ToggleRoll'/>
+               <menuitem action='play-from-edit-point-and-return'/>
+               <menuitem action='play-edit-range'/>
+               <menuitem action='record-roll'/>
                <menuitem action='ToggleRollForgetCapture'/>
                <menuitem action='Loop'/>
+               <menuitem action='loop-region'/>
                <menuitem action='PlaySelection'/>
+               <menuitem action='play-edit-range'/>
                <menuitem action='Forward'/>
                <menuitem action='Rewind'/>
                <menuitem action='GotoZero'/>
                <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-boundary'/>
+               <menuitem action='playhead-to-previous-region-boundary'/>
                <menuitem action='playhead-to-next-region-sync'/>
                <menuitem action='playhead-to-previous-region-sync'/>
                <menuitem action='center-playhead'/>
                <separator/>       
                <menuitem action='playhead-to-range-start'/>
                <menuitem action='playhead-to-range-end'/>
+               <menuitem action='focus-on-clock'/>
+               <separator/>
+                       <menuitem action='goto-mark-1'/>
+                       <menuitem action='goto-mark-2'/>
+                       <menuitem action='goto-mark-3'/>
+                       <menuitem action='goto-mark-4'/>
+                       <menuitem action='goto-mark-5'/>
+                       <menuitem action='goto-mark-6'/>
+                       <menuitem action='goto-mark-7'/>
+                       <menuitem action='goto-mark-8'/>
+                       <menuitem action='goto-mark-9'/>
                <menu action='TransportOptions'>
                     <menuitem action='ToggleTimeMaster'/>
                     <menuitem action='TogglePunchIn'/>
@@ -70,6 +84,9 @@
                     <menuitem action='toggle-follow-playhead'/>
                     <menuitem action='ToggleVideoSync'/>
                </menu>
+              <menuitem action='set-loop-from-edit-range'/>
+              <menuitem action='set-loop-from-region'/>
+              <menuitem action='set-punch-from-edit-range'/>
        </menu>
        <menu name='Edit' action='Edit'>
                <menuitem action='undo'/>
                <menuitem action='editor-delete'/>
                <menuitem action='editor-copy'/>
                <menuitem action='editor-paste'/>
+               <separator/>       
+               <menuitem action='editor-separate'/>
+               <menuitem action='editor-crop'/>
+               <menuitem action='split-region'/>
+               <separator/>       
               <menuitem action='remove-last-capture'/>
                <separator/>       
               <menu action='EditCursorMovementOptions'>
                   <menuitem action='edit-cursor-to-range-end'/>
               </menu>
               <menu name='KeyMouse Actions' action='KeyMouse Actions'>
-                       <menuitem action='audition-at-mouse'/>
+                       <menuitem action='play-selected-regions'/>
                                <menuitem action='brush-at-mouse'/>
                                <menuitem action='set-edit-point'/>
                                <menuitem action='mute-unmute-region'/>
                        <menuitem action='set-playhead'/>
-                       <menuitem action='split-region'/>
                        <menuitem action='set-region-sync-position'/>
                        <separator/>
                        <menuitem action='set-mouse-mode-object'/>
                        <menuitem action='set-mouse-mode-gain'/>
                        <menuitem action='set-mouse-mode-zoom'/>
                        <menuitem action='set-mouse-mode-timefx'/>
+                       <separator/>
+                       <menuitem action='cycle-edit-point'/>
+                       <menuitem action='cycle-edit-point-with-marker'/>
+                       <menuitem action='toggle-edit-mode'/>
           </menu>
         </menu>         
        <menu name='Select' action='Select'>
                    <menuitem action='finish-add-range'/>
                   <separator/>
                    <menuitem action='select-all'/>
+                   <menuitem action='deselect-all'/>
+                  <menuitem action='invert-selection'/>
                    <menuitem action='select-all-after-edit-cursor'/>
                    <menuitem action='select-all-before-edit-cursor'/>
                    <menuitem action='select-all-after-playhead'/>
                    <menuitem action='select-all-within-cursors'/>
                    <menuitem action='select-all-in-punch-range'/>
                    <menuitem action='select-all-in-loop-range'/>
+                  <separator/>
+                   <menuitem action='select-next-route'/>
+                   <menuitem action='select-prev-route'/>
        </menu>
        <menu name='Regions' action='Regions'>
                    <menuitem action='crop'/>
                    <menuitem action='duplicate-region'/>
+                   <menuitem action='multi-duplicate-region'/>
                    <menuitem action='insert-region'/>
                           <menuitem action='normalize-region'/>
                    <separator/>       
                    <separator/>       
                   <menuitem action='set-fade-in-length'/>
                   <menuitem action='set-fade-out-length'/>
+                  <menuitem action='toggle-fade-in-active'/>
+                  <menuitem action='toggle-fade-out-active'/>
                    <separator/>       
+                  <menuitem action='trim-back'/>
+                  <menuitem action='trim-front'/>
                   <menuitem action='trim-from-start'/>
                   <menuitem action='trim-to-end'/>
                   <menuitem action='trim-region-to-loop'/>
                   <menuitem action='trim-region-to-punch'/>
+                  <separator/>
+                  <menuitem action='pitch-shift-region'/>
        </menu>
         <menu name='View' action = 'View'>
                <menu name='ZoomFocus' action='ZoomFocus'>
                    <menuitem action='zoom-focus-mouse'/>
                </menu>
               <menu name='SnapMode' action='SnapMode'>
+                  <menuitem action='snap-off'/>
                   <menuitem action='snap-normal'/>
                   <menuitem action='snap-magnetic'/>
+                  <separator/>
+                  <menuitem action='cycle-snap-mode'/>
+                  <menuitem action='cycle-snap-choice'/>
               </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-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='temporal-zoom-in'/>
                <menuitem action='temporal-zoom-out'/>
                <menuitem action='zoom-to-session'/>
+               <menuitem action='zoom-to-region'/>
+               <menuitem action='toggle-zoom'/>
                <menuitem action='scroll-tracks-down'/>
                <menuitem action='scroll-tracks-up'/>
                <menuitem action='scroll-tracks-down'/>
               <menuitem action='SecondaryClockDeltaEditCursor'/>
                        <menuitem action='ShowTrackMeters'/>
               <menuitem action='OnlyCopyImportedFiles'/>
+              <menuitem action='ShowTrackMeters'/>
+               <menuitem action='link-region-and-track-selection'/>
               <separator/>
          </menu>
         <menu name='Help' action='Help'>
index 108782953b15dc19bc08e4f374df4555977344fa..80f53f7181bfabc9a4264b59092bccbb8f0d9213 100644 (file)
@@ -1,5 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Ardour>
+  <UI>
+    <Option name="ui-rc-file" value="ardour2_ui_dark.rc"/>
+  </UI>
   <Canvas>
     <Option name="waveform" value="000000cc"/>
     <Option name="clipped waveform" value="ff0000e5"/>
@@ -8,7 +11,7 @@
     <Option name="audio track base" value="c6d3d868"/>
     <Option name="audio bus base" value="dbd1ea68"/>
     <Option name="midi track base" value="c67e7e5f"/>
-       <Option name="midi bus base" value="ffceea40"/>
+    <Option name="midi bus base" value="ffceea40"/>
     <Option name="time stretch fill" value="e2b5b596"/>
     <Option name="time stretch outline" value="63636396"/>
     <Option name="automation line" value="44bc59ff"/>
     <Option name="verbose canvas cursor" value="f4f214bc"/>
     <Option name="marker label" value="000000ff"/>
     <Option name="marker bar separator" value="aaaaaa77"/>
-       <Option name="meter bar" value="666672ff"/>
     <Option name="tempo bar" value="72727fff"/>
-       <Option name="range marker bar" value="7f7f8cff"/>
+    <Option name="meter bar" value="666672ff"/>
+    <Option name="marker bar" value="a1a1adff"/>
+    <Option name="cd marker bar" value="9898a3ff"/>
+    <Option name="range marker bar" value="7f7f8cff"/>
     <Option name="transport marker bar" value="8c8c96ff"/>
-       <Option name="marker bar" value="9898a3ff"/>
     <Option name="range drag bar rect" value="969696c6"/>
     <Option name="range drag rect" value="82c696c6"/>
     <Option name="transport drag rect" value="969696c6"/>
@@ -83,9 +87,9 @@
     <Option name="trim handle" value="1900ff44"/>
     <Option name="edit point" value="0000ffff"/>
     <Option name="play head" value="ff0000ff"/>
-       <Option name="meter fill min" value="0000ffff"/>
-    <Option name="meter fill mid" value="73f9baff"/>
-    <Option name="meter fill max" value="00fd5dff"/>
+    <Option name="meter fill min" value="33dd33ff"/>
+    <Option name="meter fill mid" value="eeee33ff"/>
+    <Option name="meter fill max" value="ee3333ff"/>
     <Option name="meter fill clip" value="ff0000ff"/>
     <Option name="midi select rect outline" value="5555ffff"/>
     <Option name="midi select rect fill" value="8888ff88"/>
     <Option name="midi note selected outline" value="5566ffee"/>
   </Canvas>
 </Ardour>
-
index 31df7282638930a796e7c27e09762fc0919e17c7..d0261849f6152c80c6991fc2a9858eed040b9a27 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <pbd/error.h>
 #include <pbd/misc.h>
+#include <pbd/basename.h>
 #include <pbd/compose.h>
 #include <pbd/failed_constructor.h>
 #include <pbd/enumwriter.h>
@@ -70,6 +71,7 @@
 #include <ardour/audio_track.h>
 #include <ardour/midi_track.h>
 #include <ardour/filesystem_paths.h>
+#include <ardour/filename_extensions.h>
 
 #include "actions.h"
 #include "ardour_ui.h"
@@ -123,7 +125,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
 
          /* big clock */
 
-         big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
+         big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
 
          /* transport */
 
@@ -199,7 +201,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
        have_disk_speed_dialog_displayed = false;
        session_loaded = false;
        last_speed_displayed = -1.0f;
-       ab_direction = true;
        
        sys::path key_bindings_file;
 
@@ -256,7 +257,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
        starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
        stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
 
-       platform_specific ();
+       platform_setup ();
 }
 
 int
@@ -502,6 +503,7 @@ ARDOUR_UI::save_ardour_state ()
        Config->add_extra_xml (*node);
        Config->add_extra_xml (get_transport_controllable_state());
        Config->save_state();
+       ui_config->save_state ();
 
        XMLNode enode(static_cast<Stateful*>(editor)->get_state());
        XMLNode mnode(mixer->get_state());
@@ -621,9 +623,18 @@ ARDOUR_UI::startup ()
                /* Load session or start the new session dialog */
                
                if (find_session (ARDOUR_COMMAND_LINE::session_name, path, name, isnew)) {
-                       error << string_compose(_("could not load command line session \"%1\""), 
-                                               ARDOUR_COMMAND_LINE::session_name) << endmsg;
-                       return;
+                       
+                       MessageDialog msg (string_compose(_("Could not find command line session \"%1\""), 
+                                                         ARDOUR_COMMAND_LINE::session_name),
+                                          true,
+                                          Gtk::MESSAGE_ERROR,
+                                          Gtk::BUTTONS_OK);
+                       
+                       msg.set_position (Gtk::WIN_POS_MOUSE);
+                       msg.present ();
+                       msg.run ();
+                       
+                       exit (1);
                }
 
                if (!ARDOUR_COMMAND_LINE::new_session) {
@@ -631,70 +642,34 @@ ARDOUR_UI::startup ()
                        /* Supposed to be loading an existing session, but the session doesn't exist */
                        
                        if (isnew) {
-                               error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
-                                                          "To create it from the command line, start ardour as \"ardour --new %1"), path) 
-                                     << endmsg;
-                               return;
+                               MessageDialog msg (string_compose (_("\n\nNo session named \"%1\" exists.\n"
+                                                                    "To create it from the command line, start ardour as:\n   ardour --new %1"), path),
+                                                  true,
+                                                  Gtk::MESSAGE_ERROR,
+                                                  Gtk::BUTTONS_OK);
+
+                               msg.set_position (Gtk::WIN_POS_MOUSE);
+                               msg.present ();
+                               msg.run ();
+
+                               exit (1);
                        }
                }
-               
-               new_session_dialog->set_session_name (name);
-               new_session_dialog->set_session_folder (Glib::path_get_basename (path));
-               _session_is_new = isnew;
        }
 
        hide_splash ();
 
        bool have_backend = EngineControl::engine_running();
-       bool need_nsd;
-       bool load_needed = false;
-
-       if (have_backend) {
-
-               /* backend audio is working */
-
-               if (ARDOUR_COMMAND_LINE::session_name.empty() || ARDOUR_COMMAND_LINE::new_session) {
-                       /* need NSD to get session name and other info */
-                       need_nsd = true;
-               } else {
-                       need_nsd = false;
-               }
-               
-       } else {
-
-               XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
-               
-               if (audio_setup) {
-                       new_session_dialog->engine_control.set_state (*audio_setup);
-               }
-
-               /* no backend audio, must bring up NSD to check configuration */
-               
-               need_nsd = true;
-       }
-
-       if (need_nsd) {
-
-               if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
-                       return;
-               }
-
-       } else {
-
-               if (create_engine ()) {
-                       backend_audio_error (false);
-                       exit (1);
-               }
-
-               load_needed = true;
+       XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
+       
+       if (audio_setup) {
+               new_session_dialog->engine_control.set_state (*audio_setup);
        }
        
-       if (load_needed) {
-               if (load_session (ARDOUR_COMMAND_LINE::session_name, name)) {
-                       return;
-               }
+       if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
+               return;
        }
-
+       
        show ();
 }
 
@@ -1458,7 +1433,7 @@ ARDOUR_UI::remove_last_capture()
 }
 
 void
-ARDOUR_UI::transport_record ()
+ARDOUR_UI::transport_record (bool roll)
 {
        if (session) {
                switch (session->record_status()) {
@@ -1469,8 +1444,18 @@ ARDOUR_UI::transport_record ()
                                return;
                        }
                        session->maybe_enable_record ();
+                       if (roll) {
+                               transport_roll ();
+                       }
                        break;
                case Session::Recording:
+                       if (roll) {
+                               session->request_stop();
+                       } else {
+                               session->disable_record (false, true);
+                       }
+                       break;
+
                case Session::Enabled:
                        session->disable_record (false, true);
                }
@@ -1924,6 +1909,14 @@ ARDOUR_UI::primary_clock_value_changed ()
        }
 }
 
+void
+ARDOUR_UI::big_clock_value_changed ()
+{
+       if (session) {
+               session->request_locate (big_clock.current_time ());
+       }
+}
+
 void
 ARDOUR_UI::secondary_clock_value_changed ()
 {
@@ -2027,12 +2020,40 @@ ARDOUR_UI::save_template ()
        }
 }
 
+void
+ARDOUR_UI::fontconfig_dialog ()
+{
+#ifdef GTKOSX
+       /* X11 users will always have fontconfig info around, but new GTK-OSX users 
+          may not and it can take a while to build it. Warn them.
+       */
+       
+       Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
+       
+       if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
+               MessageDialog msg (*new_session_dialog,
+                                  _("Welcome to Ardour.\n\n"
+                                    "The program will take a bit longer to start up\n"
+                                    "while the system fonts are checked.\n\n"
+                                    "This will only be done once, and you will\n"
+                                    "not see this message again\n"),
+                                  true,
+                                  Gtk::MESSAGE_INFO,
+                                  Gtk::BUTTONS_OK);
+               msg.show_all ();
+               msg.present ();
+               msg.run ();
+       }
+#endif
+}
+
 bool
 ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
 {
-       string session_name;
-       string session_path;
-       string template_name;
+       bool existing_session = false;
+       Glib::ustring session_name;
+       Glib::ustring session_path;
+       Glib::ustring template_name;
 
        if (!loading_dialog) {
                loading_dialog = new MessageDialog (*new_session_dialog, 
@@ -2041,41 +2062,117 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
                                                    Gtk::MESSAGE_INFO,
                                                    Gtk::BUTTONS_NONE);
        }
-               
+
+
        int response = Gtk::RESPONSE_NONE;
 
-       new_session_dialog->set_modal(true);
-       new_session_dialog->set_name (predetermined_path);
-       new_session_dialog->reset_recent();
+       if (predetermined_path.length()) {
+               
+               /* before we start, lets see if the given path looks like
+                  an existing ardour session. if it does, skip the
+                  tabs that we don't need
+               */
+
+               if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
+                       session_path = predetermined_path;
+                       existing_session = true;
+               } else if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_REGULAR)) {
+                       session_path = Glib::path_get_dirname (string (predetermined_path));
+                       existing_session = true;
+               } else {
+                       /* it doesn't exist, assume the best */
+                       session_path = Glib::path_get_dirname (string (predetermined_path));
+               }
+                      
+               session_name = basename_nosuffix (string (predetermined_path));
+
+               new_session_dialog->set_session_name (session_name);
+               new_session_dialog->set_session_folder (session_path);
+               new_session_dialog->set_modal (true);
+
+               if (existing_session) {
+
+                       if (session_name.length() == 0 || session_path.length() == 0) {
+                               error << string_compose (_("Ardour cannot understand \"%1\" as a session name"), predetermined_path) << endmsg;
+                               return false;
+                       }
+                       
+                       if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
+                               Glib::ustring predicted_session_file;
+                               
+                               predicted_session_file = predetermined_path;
+                               predicted_session_file += '/';
+                               predicted_session_file += session_name;
+                               predicted_session_file += ARDOUR::statefile_suffix;
+                               
+                               if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
+                                       existing_session = true;
+                               }
+                               
+                       } else if (Glib::file_test (predetermined_path, Glib::FILE_TEST_EXISTS)) {
+                               
+                               if (predetermined_path.find (ARDOUR::statefile_suffix) == predetermined_path.length() - 7) {
+                                       /* existing .ardour file */
+                                       existing_session = true;
+                               }
+                       } else {
+                               existing_session = false;
+                       }
+                       
+                       if (existing_session && have_engine) {
+                               /* lets just try to load it */
+                               
+                               loading_dialog->set_message (_("Starting audio engine"));
+                               loading_dialog->show_all ();
+                               flush_pending ();
+                               
+                               if (create_engine ()) {
+                                       backend_audio_error (!have_engine, new_session_dialog);
+                                       loading_dialog->hide ();
+                                       return false;
+                               }
+                               
+                               if (load_session (session_path, session_name) == 0) {
+                                       goto done;
+                               }
+                       }
+               }
+       }
+
+       /* loading failed, or we need the NSD for something */
+
        new_session_dialog->set_position (WIN_POS_CENTER);
        new_session_dialog->set_current_page (0);
+       new_session_dialog->set_existing_session (existing_session);
+       new_session_dialog->reset_recent();
 
        do {
                new_session_dialog->set_have_engine (have_engine);
-
-               new_session_dialog->show();
                new_session_dialog->present ();
-               response = new_session_dialog->run ();
-
+               response = new_session_dialog->run ();
+               loading_dialog->hide ();
+               
                _session_is_new = false;
+               
+               /* handle possible negative responses */
 
                if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
-
+                       
                        if (!session) {
                                quit();
                        }
                        new_session_dialog->hide ();
                        return false;
-
+                       
                } else if (response == Gtk::RESPONSE_NONE) {
-
-                       /* Clear was pressed */
-                       new_session_dialog->reset();
-                       continue;
+                       /* "Clear" was pressed */
+                       
+                       goto try_again;
                }
 
-               /* first things first ... if we're here to help set up audio parameters
-                  this is where want to do that.
+               fontconfig_dialog();
+
+               /* if we're here to help set up audio parameters this is where want to do that.
                */
 
                if (!have_engine) {
@@ -2083,45 +2180,24 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
                                new_session_dialog->hide ();
                                return false;
                        } 
-               }
-
-#ifdef GTKOSX
-               /* X11 users will always have fontconfig info around, but new GTK-OSX users 
-                  may not and it can take a while to build it. Warn them.
-               */
 
-               Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
-               
-               if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
-                       MessageDialog msg (*new_session_dialog,
-                                          _("Welcome to Ardour.\n\n"
-                                            "The program will take a bit longer to start up\n"
-                                            "while the system fonts are checked.\n\n"
-                                            "This will only be done once, and you will\n"
-                                            "not see this message again\n"),
-                                          true,
-                                          Gtk::MESSAGE_INFO,
-                                          Gtk::BUTTONS_OK);
-                       msg.show_all ();
-                       msg.present ();
-                       msg.run ();
+                       loading_dialog->set_message (_("Starting audio engine"));
+                       loading_dialog->show_all ();
+                       flush_pending ();
                }
-#endif
-               loading_dialog->set_message (_("Starting audio engine"));
-               loading_dialog->show_all ();
-               flush_pending ();
-               
+
                if (create_engine ()) {
                        backend_audio_error (!have_engine, new_session_dialog);
                        loading_dialog->hide ();
                        flush_pending ();
                        /* audio setup page */
+                       new_session_dialog->set_existing_session (false);
                        new_session_dialog->set_current_page (2);
-                       /* try again */
                        response = Gtk::RESPONSE_NONE;
-                       continue;
+                       goto try_again;
                }
 
+               loading_dialog->hide ();
                have_engine = true;             
                        
                /* now handle possible affirmative responses */
@@ -2134,16 +2210,22 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
                        
                        if (session_name.empty()) {
                                response = Gtk::RESPONSE_NONE;
-                               continue;
+                               goto try_again;
                        } 
 
                        if (session_name[0] == '/' || 
                            (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
                            (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
-                               load_session (Glib::path_get_dirname (session_name), session_name);
+                               if (load_session (Glib::path_get_dirname (session_name), session_name)) {
+                                       response = Gtk::RESPONSE_NONE;
+                                       goto try_again;
+                               }
                        } else {
                                session_path = new_session_dialog->session_folder();
-                               load_session (session_path, session_name);
+                               if (load_session (session_path, session_name)) {
+                                       response = Gtk::RESPONSE_NONE;
+                                       goto try_again;
+                               }
                        }
                        
                } else if (response == Gtk::RESPONSE_OK) {
@@ -2154,9 +2236,9 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
                
                        if (session_name.empty()) {
                                response = Gtk::RESPONSE_NONE;
-                               continue;
+                               goto try_again;
                        } 
-                               
+
                        switch (new_session_dialog->get_current_page()) {
                        case 1: /* recent session selector */
                        case 2: /* audio engine control */
@@ -2164,10 +2246,19 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
                                if (session_name[0] == '/' || 
                                    (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
                                    (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
-                                       load_session (Glib::path_get_dirname (session_name), session_name);
+                                       cerr << "here\n";
+                                       if (load_session (Glib::path_get_dirname (session_name), session_name)) {
+                                               response = Gtk::RESPONSE_NONE;
+                                               goto try_again;
+                                       }
+
                                } else {
                                        session_path = new_session_dialog->session_folder();
-                                       load_session (session_path, session_name);
+                                       cerr << "there\n";
+                                       if (load_session (session_path, session_name)) {
+                                               response = Gtk::RESPONSE_NONE;
+                                               goto try_again;
+                                       }
                                }
                                break;
 
@@ -2191,15 +2282,19 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
                                        session_path = new_session_dialog->session_folder();
 
                                }
-                               
+
                                //XXX This is needed because session constructor wants a 
                                //non-existant path. hopefully this will be fixed at some point.
                                
                                session_path = Glib::build_filename (session_path, session_name);
-                               
+
                                if (!should_be_new) {
 
-                                       load_session (session_path, session_name);
+                                       if (load_session (session_path, session_name)) {
+                                               response = Gtk::RESPONSE_NONE;
+                                               goto try_again;
+                                       }
+
                                        continue; /* leaves while() loop because response != NONE */
 
                                } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
@@ -2222,12 +2317,17 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
                                                new_session_dialog->hide ();
                                                goto_editor_window ();
                                                flush_pending ();
-                                               load_session (session_path, session_name);
+                                               if (load_session (session_path, session_name)) {
+                                                       response = Gtk::RESPONSE_NONE;
+                                                       goto try_again;
+                                               }
                                                goto done;
                                                break;
                                        default:
                                                response = RESPONSE_NONE;
                                                new_session_dialog->reset ();
+                                               new_session_dialog->set_existing_session (false);
+                                               loading_dialog->hide ();
                                                continue;
                                        }
                                } 
@@ -2242,7 +2342,11 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
                                        goto_editor_window ();
                                        flush_pending ();
 
-                                       load_session (session_path, session_name, &template_name);
+                                       if (load_session (session_path, session_name, template_name)) {
+                                               response = Gtk::RESPONSE_NONE;
+                                               goto try_again;
+                                       }
+
                          
                                } else {
 
@@ -2298,10 +2402,6 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
                                                nphysout = (uint32_t) new_session_dialog->output_limit_count();
                                        }
 
-                                       new_session_dialog->hide ();
-                                       goto_editor_window ();
-                                       flush_pending ();
-
                                        if (build_session (session_path,
                                                           session_name,
                                                           cchns,
@@ -2313,9 +2413,12 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
                                                           engine->frame_rate() * 60 * 5)) {
                                                
                                                response = Gtk::RESPONSE_NONE;
-                                               new_session_dialog->reset ();
-                                               continue;
+                                               goto try_again;
                                        }
+
+                                       new_session_dialog->hide ();
+                                       goto_editor_window ();
+                                       flush_pending ();
                                }
                                break;
 
@@ -2323,6 +2426,13 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
                                break;
                        }
                }
+
+         try_again:
+               if (response == Gtk::RESPONSE_NONE) {
+                       loading_dialog->hide ();
+                       new_session_dialog->set_existing_session (false);
+                       new_session_dialog->reset ();
+               }
                
        } while (response == Gtk::RESPONSE_NONE);
 
@@ -2346,7 +2456,7 @@ ARDOUR_UI::close_session()
 }
 
 int
-ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
+ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
 {
        Session *new_session;
        int unload_status;
@@ -2369,7 +2479,7 @@ ARDOUR_UI::load_session (const string & path, const string & snap_name, string*
 
        /* if it already exists, we must have write access */
 
-       if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
+       if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
                MessageDialog msg (*editor, _("You do not have write access to this session.\n"
                                              "This prevents the session from being loaded."));
                msg.run ();
@@ -2387,8 +2497,55 @@ ARDOUR_UI::load_session (const string & path, const string & snap_name, string*
                new_session = new Session (*engine, path, snap_name, mix_template);
        }
 
+       /* this one is special */
+
+       catch (AudioEngine::PortRegistrationFailure& err) {
+
+               MessageDialog msg (err.what(),
+                                  true,
+                                  Gtk::MESSAGE_INFO,
+                                  Gtk::BUTTONS_OK_CANCEL);
+               
+               msg.set_title (_("Loading Error"));
+               msg.set_secondary_text (_("Click the OK button to try again."));
+               msg.set_position (Gtk::WIN_POS_CENTER);
+               msg.present ();
+
+               int response = msg.run ();
+
+               msg.hide ();
+
+               switch (response) {
+               case RESPONSE_CANCEL:
+                       exit (1);
+               default:
+                       break;
+               }
+               goto out;
+       }
+
        catch (...) {
-               error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
+               cerr << "Caught something\n";
+               MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
+                                  true,
+                                  Gtk::MESSAGE_INFO,
+                                  Gtk::BUTTONS_OK_CANCEL);
+               
+               msg.set_title (_("Loading Error"));
+               msg.set_secondary_text (_("Click the OK button to try again."));
+               msg.set_position (Gtk::WIN_POS_CENTER);
+               msg.present ();
+
+               int response = msg.run ();
+
+               msg.hide ();
+
+               switch (response) {
+               case RESPONSE_CANCEL:
+                       exit (1);
+               default:
+                       break;
+               }
                goto out;
        }
 
@@ -2413,7 +2570,7 @@ ARDOUR_UI::load_session (const string & path, const string & snap_name, string*
 }
 
 int
-ARDOUR_UI::build_session (const string & path, const string & snap_name, 
+ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name, 
                          uint32_t control_channels,
                          uint32_t master_channels, 
                          AutoConnectOption input_connect,
@@ -3202,41 +3359,3 @@ ARDOUR_UI::setup_profile ()
        }
 }
 
-void
-ARDOUR_UI::disable_all_plugins ()
-{
-       if (!session) {
-               return;
-       }
-
-       // session->begin_reversible_command (_("Disable all plugins"));
-
-       boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
-
-       for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
-               // XMLNode& before = (*i)->get_redirect_state ();
-               // session->add_command (new MementoCommand<Route>(**i, &before, 0));
-               (*i)->disable_plugins ();
-               // XMLNode& after = (*i)->get_redirect_state ();
-               // session->add_command (new MementoCommand<Route>(**i, 0, &after));
-                                     
-       }
-
-       // session->commit_reversible_command ();
-}
-
-void
-ARDOUR_UI::ab_all_plugins ()
-{
-       if (!session) {
-               return;
-       }
-
-       boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
-
-       for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
-               (*i)->ab_plugins (ab_direction);
-       }
-       
-       ab_direction = !ab_direction;
-}
index 0cbc9935bf909cbd3ac14a8da598401e9bc5ac27..996349c9900e23c85694a4fd4dd36b815299f6ac 100644 (file)
@@ -112,10 +112,9 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        void show_splash ();
        void hide_splash ();
        
-       int load_session (const string & path, const string & snapshot, string* mix_template = 0);
+       int load_session (const Glib::ustring & path, const Glib::ustring& snapshot, Glib::ustring mix_template = Glib::ustring());
        bool session_loaded;
-       /// @return zero if building the session was successful
-       int build_session (const string & path, const string & snapshot, 
+       int build_session (const Glib::ustring& path, const Glib::ustring& snapshot, 
                           uint32_t ctl_chns, 
                           uint32_t master_chns,
                           ARDOUR::AutoConnectOption input_connect,
@@ -155,7 +154,9 @@ class ARDOUR_UI : public Gtkmm2ext::UI
 
        PublicEditor&     the_editor(){return *editor;}
        Mixer_UI* the_mixer() { return mixer; }
-       
+
+       ARDOUR::AudioEngine& the_engine() const { return *engine; }
+
        void toggle_key_editor ();
        void toggle_location_window ();
        void toggle_theme_manager ();
@@ -280,8 +281,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        ARDOUR::AudioEngine                 *engine;
        ARDOUR::Session                     *session;
 
-       bool check_audioengine();
-
        Gtk::Tooltips          _tooltips;
 
        void                     goto_editor_window ();
@@ -482,6 +481,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        void solo_alert_toggle ();
        void audition_alert_toggle ();
 
+       void big_clock_value_changed ();
        void primary_clock_value_changed ();
        void secondary_clock_value_changed ();
 
@@ -578,7 +578,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        void transport_goto_end ();
        void transport_stop ();
        void transport_stop_and_forget_capture ();
-       void transport_record ();
+       void transport_record (bool roll);
        void transport_roll ();
        void transport_play_selection(); 
        void transport_forward (int option);
@@ -753,10 +753,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        void no_memory_warning ();
        void check_memory_locking ();
 
-       bool ab_direction;
-       void disable_all_plugins ();
-       void ab_all_plugins ();
-
+       bool check_audioengine();
        void audioengine_setup ();
 
        void display_message (const char *prefix, gint prefix_len, 
@@ -766,6 +763,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        Gtk::MessageDialog* loading_dialog;
 
        void platform_specific ();
+       void platform_setup ();
+       void fontconfig_dialog ();
 };
 
 #endif /* __ardour_gui_h__ */
index fcb721a9f05027262eb8ff9b7b2cd7627fc00dcf..ca0615cbef387202c90967fad885b02881c92bf7 100644 (file)
@@ -316,6 +316,7 @@ ARDOUR_UI::setup_transport ()
 
        primary_clock.ValueChanged.connect (mem_fun(*this, &ARDOUR_UI::primary_clock_value_changed));
        secondary_clock.ValueChanged.connect (mem_fun(*this, &ARDOUR_UI::secondary_clock_value_changed));
+       big_clock.ValueChanged.connect (mem_fun(*this, &ARDOUR_UI::big_clock_value_changed));
 
        ARDOUR_UI::instance()->tooltips().set_tip (primary_clock, _("Primary clock"));
        ARDOUR_UI::instance()->tooltips().set_tip (secondary_clock, _("secondary clock"));
@@ -398,7 +399,9 @@ ARDOUR_UI::setup_transport ()
        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);
+       if (!Profile->get_sae()) {
+               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, 6);
@@ -408,12 +411,16 @@ ARDOUR_UI::setup_transport ()
        if (!ARDOUR::Profile->get_small_screen()) {
                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);
+
+       if (!Profile->get_sae()) {
+               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);
@@ -443,6 +450,11 @@ ARDOUR_UI::setup_transport ()
 
        transport_tearoff_hbox.pack_start (*toggle_box, false, false, 4);
        transport_tearoff_hbox.pack_start (alert_box, false, false);
+
+       if (Profile->get_sae()) {
+               Image* img = manage (new Image ((::get_icon (X_("sae")))));
+               transport_tearoff_hbox.pack_end (*img, false, false, 6);
+       }
 }
 
 void
index 6464c529679bb352fa0d20f27abeaf99210fccde..dd0889b78670eb7eb5948f46ae82fb80dfd5f60e 100644 (file)
@@ -51,7 +51,7 @@ ARDOUR_UI::shutdown ()
                session->remove_pending_capture_state ();
                session = 0;
        }
-
+       ui_config->save_state();
 }
 
 void
index 38aae959cf9ae4fcbf97f46b0f35915baea16845..af8206ceac643740c7960fff8f5b06f4f4e17e0e 100644 (file)
@@ -82,7 +82,7 @@ ARDOUR_UI::install_actions ()
        /* menus + submenus that need action items */
 
        ActionManager::register_action (main_actions, X_("Session"), _("Session"));
-       ActionManager::register_action (main_actions, X_("Files"), _("Files"));
+       ActionManager::register_action (main_actions, X_("Files"), _("Import/Export"));
        ActionManager::register_action (main_actions, X_("Regions"), _("Regions"));
        ActionManager::register_action (main_actions, X_("Cleanup"), _("Cleanup"));
        ActionManager::register_action (main_actions, X_("Sync"), _("Sync"));
@@ -269,7 +269,9 @@ ARDOUR_UI::install_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::transport_sensitive_actions.push_back (act);
 
-       act = ActionManager::register_action (transport_actions, X_("Record"), _("Enable Record"), mem_fun(*this, &ARDOUR_UI::transport_record));
+       act = ActionManager::register_action (transport_actions, X_("Record"), _("Enable Record"), bind (mem_fun(*this, &ARDOUR_UI::transport_record), false));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (transport_actions, X_("record-roll"), _("Start Recording"), bind (mem_fun(*this, &ARDOUR_UI::transport_record), true));
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::transport_sensitive_actions.push_back (act);
        act = ActionManager::register_action (transport_actions, X_("Rewind"), _("Rewind"), bind (mem_fun(*this, &ARDOUR_UI::transport_rewind), 0));
@@ -300,6 +302,10 @@ ARDOUR_UI::install_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::transport_sensitive_actions.push_back (act);
 
+       act = ActionManager::register_action (transport_actions, X_("focus-on-clock"), _("Focus On Clock"), mem_fun(primary_clock, &AudioClock::focus));
+       ActionManager::session_sensitive_actions.push_back (act);
+       ActionManager::transport_sensitive_actions.push_back (act);
+
        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);
@@ -420,7 +426,7 @@ ARDOUR_UI::install_actions ()
        ActionManager::register_toggle_action (option_actions, X_("RegionEquivalentsOverlap"), _("Region equivalents overlap"), mem_fun (*this, &ARDOUR_UI::toggle_RegionEquivalentsOverlap));
        ActionManager::register_toggle_action (option_actions, X_("PrimaryClockDeltaEditCursor"), _("Primary Clock delta to edit point"), mem_fun (*this, &ARDOUR_UI::toggle_PrimaryClockDeltaEditCursor));
        ActionManager::register_toggle_action (option_actions, X_("SecondaryClockDeltaEditCursor"), _("Secondary Clock delta to edit point"), mem_fun (*this, &ARDOUR_UI::toggle_SecondaryClockDeltaEditCursor));       
-       ActionManager::register_toggle_action (option_actions, X_("ShowTrackMeters"), _("Display Editor Meters"), mem_fun (*this, &ARDOUR_UI::toggle_ShowTrackMeters)); 
+       ActionManager::register_toggle_action (option_actions, X_("ShowTrackMeters"), _("Enable Editor Meters"), mem_fun (*this, &ARDOUR_UI::toggle_ShowTrackMeters));
        ActionManager::register_toggle_action (option_actions, X_("OnlyCopyImportedFiles"), _("Always copy imported files"), mem_fun (*this, &ARDOUR_UI::toggle_only_copy_imported_files));     
 
        RadioAction::Group denormal_group;
@@ -464,17 +470,16 @@ ARDOUR_UI::install_actions ()
 
        act = ActionManager::register_toggle_action (option_actions, X_("DoNotRunPluginsWhileRecording"), _("Do not run plugins while recording"), mem_fun (*this, &ARDOUR_UI::toggle_DoNotRunPluginsWhileRecording));
        ActionManager::session_sensitive_actions.push_back (act);
-
        
        act = ActionManager::register_toggle_action (option_actions, X_("LatchedSolo"), _("Latched solo"), mem_fun (*this, &ARDOUR_UI::toggle_LatchedSolo));
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_toggle_action (option_actions, X_("ShowSoloMutes"), _("Show solo muting"), mem_fun (*this, &ARDOUR_UI::toggle_ShowSoloMutes));
        ActionManager::session_sensitive_actions.push_back (act);
 
-       act = ActionManager::register_action (option_actions, X_("DisableAllPlugins"), _("Disable All Plugins"), mem_fun (*this, &ARDOUR_UI::disable_all_plugins));
+       /*act = ActionManager::register_action (option_actions, X_("DisableAllPlugins"), _("Disable All Plugins"), mem_fun (*this, &ARDOUR_UI::disable_all_plugins));
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (option_actions, X_("ABAllPlugins"), _("A/B All Plugins"), mem_fun (*this, &ARDOUR_UI::ab_all_plugins));
-       ActionManager::session_sensitive_actions.push_back (act);
+       ActionManager::session_sensitive_actions.push_back (act);*/
 
        /* !!! REMEMBER THAT RADIO ACTIONS HAVE TO BE HANDLED WITH MORE FINESSE THAN SIMPLE TOGGLES !!! */
 
index 56c4ac649f4e95b69620a7090c4a1118e46aea29..a76e3725a0a3f286167ae897832e6c4147e0b4c0 100644 (file)
@@ -33,6 +33,7 @@
 #include "ardour_ui.h"
 #include "actions.h"
 #include "gui_thread.h"
+#include "public_editor.h"
 
 #include "i18n.h"
 
@@ -1118,6 +1119,9 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
                ActionManager::map_some_state ("options",  "SecondaryClockDeltaEditCursor", &Configuration::get_secondary_clock_delta_edit_cursor);
        } else if (PARAM_IS ("only-copy-imported-files")) {
                map_only_copy_imported_files ();
+       } else if (PARAM_IS ("show-track-meters")) {
+               ActionManager::map_some_state ("options",  "ShowTrackMeters", &Configuration::get_show_track_meters);
+               editor->toggle_meter_updating();
        }
 
 #undef PARAM_IS
diff --git a/gtk2_ardour/au_pluginui.cc b/gtk2_ardour/au_pluginui.cc
deleted file mode 100644 (file)
index 84d3939..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
-    Copyright (C) 2006 Paul Davis 
-       Written by Taybin Rutkin
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <ardour/audio_unit.h>
-#include <ardour/processor.h>
-
-#include <gtkmm2ext/doi.h>
-
-#include "au_pluginui.h"
-#include "gui_thread.h"
-
-#include <appleutility/CAAudioUnit.h>
-#include <appleutility/CAComponent.h>
-
-#include <AudioUnit/AudioUnit.h>
-
-#include "i18n.h"
-
-using namespace ARDOUR;
-using namespace PBD;
-
-AUPluginUI::AUPluginUI (boost::shared_ptr<PluginInsert> insert)
-{
-       if ((au = boost::dynamic_pointer_cast<AUPlugin> (insert->plugin())) == 0) {
-               error << _("unknown type of editor-supplying plugin (note: no AudioUnit support in this version of ardour)") << endmsg;
-               throw failed_constructor ();
-       }
-
-       OSStatus err = noErr;
-       
-       CAComponentDescription desc;
-       Component carbonViewComponent = NULL;
-       AudioUnitCarbonView carbonView = NULL;
-       
-       GetComponentInfo(au->get_comp()->Comp(), &desc, 0, 0, 0);
-       carbonViewComponent = get_carbon_view_component(desc.componentSubType);
-       err = OpenAComponent(carbonViewComponent, &carbonView);
-       
-       Rect rec;
-       rec.top = 0;
-       rec.left = 0;
-       rec.bottom = 400;
-       rec.right = 500;
-       
-       ProcessSerialNumber ourPSN;
-       
-       /* Here we will set the MacOSX native section of the process to the foreground for putting up this
-     * dialog box.  First step is to get our process serial number.  We do this by calling 
-     * GetCurrentProcess. 
-     * First Argument: On success this PSN will be our PSN on return.
-     * Return Value: A Macintosh error indicating success or failure.
-     */
-    err = GetCurrentProcess(&ourPSN);
-    
-    //If no error then set this process to be frontmost.
-    if (err == noErr) {
-        /* Calling SetFrontProcess to make us frontmost.
-         * First Argument: The Process Serial Number of the process we want to make frontmost.  Here
-         *    of course we pass our process serial number
-         * Return Value: An error value indicating success or failure.  We just ignore the return
-         *    value here.
-         */
-        (void)SetFrontProcess(&ourPSN);
-    } else {
-               error << "couldn't get current process" << endmsg;
-       }
-       
-       err = CreateNewWindow (kDocumentWindowClass, kWindowStandardFloatingAttributes, &rec, &wr);
-       
-       ComponentResult auResult;
-       ControlRef rootControl = NULL;
-       GetRootControl(wr, &rootControl);
-       
-       int width = 500;
-       int height = 400;
-       Float32Point location = {30, 30};
-       Float32Point size = {width, height};
-       ControlRef audioUnitControl = NULL;
-       
-       auResult = AudioUnitCarbonViewCreate(carbonView,
-                                            au->get_au()->AU(),
-                                            wr,
-                                            rootControl,
-                                            &location,
-                                            &size,
-                                            &audioUnitControl);    
-       
-       ShowWindow (wr);
-       BringToFront (wr);
-//     AudioUnitCarbonViewSetEventListener(carbonView, EventListener, this);
-#if 0
-       set_name ("PluginEditor");
-       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)));
-#endif 
-
-       insert->GoingAway.connect (mem_fun(*this, &AUPluginUI::plugin_going_away));
-       
-       info << "AUPluginUI created" << endmsg;
-}
-
-AUPluginUI::~AUPluginUI ()
-{
-       // nothing to do here - plugin destructor destroys the GUI
-}
-
-void
-AUPluginUI::plugin_going_away (ARDOUR::IOProcessor* ignored)
-{
-        ENSURE_GUI_THREAD(bind (mem_fun(*this, &AUPluginUI::plugin_going_away), ignored));
-
-        delete_when_idle (this);
-}
-
-Component
-AUPluginUI::get_carbon_view_component(OSType subtype)
-{
-       ComponentDescription desc;
-       Component component;
-       
-       desc.componentType = kAudioUnitCarbonViewComponentType; // 'auvw'
-       desc.componentSubType = subtype;
-       desc.componentManufacturer = 0;
-       desc.componentFlags = 0;
-       desc.componentFlagsMask = 0;
-       
-       // First see if we can find a carbon view designed specifically for this
-       // plug-in:
-       
-       component = FindNextComponent(NULL, &desc);
-       if (component)
-          return component;
-       
-       // If not, grab the generic carbon view, which will create a GUI for
-       // any Audio Unit.
-       
-       desc.componentSubType = kAUCarbonViewSubType_Generic;
-       component = FindNextComponent(NULL, &desc);
-       
-       return component;
-}
-
index d757ea3bf0b196061c0ad5ee1103a45a345b7a15..0e31b35e031798e74f4cdb8525627bf5efeb3cfd 100644 (file)
@@ -1,29 +1,18 @@
-/*
-    Copyright (C) 2006 Paul Davis 
+#ifndef __gtk2_ardour_auplugin_ui_h__
+#define __gtk2_ardour_auplugin_ui_h__
 
-    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 <AppKit/AppKit.h>
+#include <Carbon/Carbon.h>
+#include <AudioUnit/AudioUnit.h>
 
-*/
+/* fix up stupid apple macros */
 
-#ifndef __au_plugin_ui_h__
-#define __au_plugin_ui_h__
+#undef check
+#undef require
+#undef verify
 
-#include <boost/shared_ptr.hpp>
-
-#include <Carbon/Carbon.h>
-#include <AudioUnit/AudioUnit.h>
+#include <gtkmm/box.h>
+#include "plugin_ui.h"
 
 namespace ARDOUR {
        class AUPlugin;
@@ -31,18 +20,58 @@ namespace ARDOUR {
        class IOProcessor;
 }
 
-class AUPluginUI
+class AUPluginUI : public PlugUIBase, public Gtk::VBox
 {
   public:
        AUPluginUI (boost::shared_ptr<ARDOUR::PluginInsert>);
        ~AUPluginUI ();
        
+       gint get_preferred_height () { return prefheight; }
+       gint get_preferred_width () { return prefwidth; }
+       bool start_updating(GdkEventAny*);
+       bool stop_updating(GdkEventAny*);
+       
+       virtual void activate ();
+       virtual void deactivate ();
+
+       void on_realize ();
+       void on_show ();
+
+       OSStatus carbon_event (EventHandlerCallRef nextHandlerRef, EventRef event);
+
   private:
        WindowRef wr;
        boost::shared_ptr<ARDOUR::AUPlugin> au;
+       int prefheight;
+       int prefwidth;
+
+       /* Cocoa */
+
+       NSWindow*           cocoa_window;
+       NSScrollView*       scroll_view;
+       NSView*             au_view;
+
+       /* Carbon */
+
+       NSWindow*            cocoa_parent;
+       ComponentDescription carbon_descriptor;
+       AudioUnitCarbonView  editView;
+       WindowRef            carbon_window;     
+       EventHandlerRef      carbon_event_handler;
+       bool                 carbon_parented;
+       bool                 cocoa_parented;
+
+       void test_view_support (bool&, bool&);
+       bool test_cocoa_view_support ();
+       bool test_carbon_view_support ();
+       int  create_carbon_view (bool generic);
+       int  create_cocoa_view ();
+
+       int parent_carbon_window ();
+       int parent_cocoa_window ();
+       NSWindow* get_nswindow();
 
-       void plugin_going_away (ARDOUR::IOProcessor*);
-       Component get_carbon_view_component(OSType subtype);
+       bool plugin_class_valid (Class pluginClass);
 };
 
-#endif // __au_plugin_ui_h__
+#endif /* __gtk2_ardour_auplugin_ui_h__  */
diff --git a/gtk2_ardour/au_pluginui.mm b/gtk2_ardour/au_pluginui.mm
new file mode 100644 (file)
index 0000000..51f7319
--- /dev/null
@@ -0,0 +1,567 @@
+#include <pbd/error.h>
+#include <ardour/audio_unit.h>
+#include <ardour/insert.h>
+
+#include <gdk/gdkquartz.h>
+
+#include "au_pluginui.h"
+#include "gui_thread.h"
+
+#include <appleutility/CAAudioUnit.h>
+#include <appleutility/CAComponent.h>
+
+#import <AudioUnit/AUCocoaUIView.h>
+#import <CoreAudioKit/AUGenericView.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace sigc;
+using namespace std;
+using namespace PBD;
+
+static const float kOffsetForAUView_X = 220;
+static const float kOffsetForAUView_Y = 90;
+
+AUPluginUI::AUPluginUI (boost::shared_ptr<PluginInsert> insert)
+       : PlugUIBase (insert)
+{
+       if ((au = boost::dynamic_pointer_cast<AUPlugin> (insert->plugin())) == 0) {
+               error << _("unknown type of editor-supplying plugin (note: no AudioUnit support in this version of ardour)") << endmsg;
+               throw failed_constructor ();
+       }
+
+       bool has_carbon;
+       bool has_cocoa;
+
+       carbon_parented = false;
+       cocoa_parented = false;
+       cocoa_parent = 0;
+       cocoa_window = 0;
+
+       test_view_support (has_carbon, has_cocoa);
+
+       if (has_cocoa) {
+               create_cocoa_view ();
+       } else if (has_carbon) {
+               create_carbon_view (has_carbon);
+       } else {
+               /* fallback to cocoa */
+               create_cocoa_view ();
+       }
+}
+
+
+AUPluginUI::~AUPluginUI ()
+{
+       if (carbon_parented) {
+               NSWindow* win = get_nswindow();
+               RemoveEventHandler(carbon_event_handler);
+               [win removeChildWindow:cocoa_parent];
+       }
+}
+
+void
+AUPluginUI::test_view_support (bool& has_carbon, bool& has_cocoa)
+{
+       has_carbon = test_carbon_view_support();
+       has_cocoa = test_cocoa_view_support();
+}
+
+bool
+AUPluginUI::test_carbon_view_support ()
+{
+       bool ret = false;
+       
+       carbon_descriptor.componentType = kAudioUnitCarbonViewComponentType;
+       carbon_descriptor.componentSubType = 'gnrc';
+       carbon_descriptor.componentManufacturer = 'appl';
+       carbon_descriptor.componentFlags = 0;
+       carbon_descriptor.componentFlagsMask = 0;
+       
+       OSStatus err;
+
+       // ask the AU for its first editor component
+       UInt32 propertySize;
+       err = AudioUnitGetPropertyInfo(*au->get_au(), kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, 0, &propertySize, NULL);
+       if (!err) {
+               int nEditors = propertySize / sizeof(ComponentDescription);
+               ComponentDescription *editors = new ComponentDescription[nEditors];
+               err = AudioUnitGetProperty(*au->get_au(), kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, 0, editors, &propertySize);
+               if (!err) {
+                       // just pick the first one for now
+                       carbon_descriptor = editors[0];
+                       ret = true;
+               }
+               delete[] editors;
+       }
+
+       return ret;
+}
+       
+bool
+AUPluginUI::test_cocoa_view_support ()
+{
+       UInt32 dataSize   = 0;
+       Boolean isWritable = 0;
+       OSStatus err = AudioUnitGetPropertyInfo(*au->get_au(),
+                                               kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global,
+                                               0, &dataSize, &isWritable);
+       
+       return dataSize > 0 && err == noErr;
+}
+
+bool
+AUPluginUI::plugin_class_valid (Class pluginClass)
+{
+       if([pluginClass conformsToProtocol: @protocol(AUCocoaUIBase)]) {
+               if([pluginClass instancesRespondToSelector: @selector(interfaceVersion)] &&
+                  [pluginClass instancesRespondToSelector: @selector(uiViewForAudioUnit:withSize:)]) {
+                               return true;
+               }
+       }
+       return false;
+}
+
+int
+AUPluginUI::create_cocoa_view ()
+{
+       BOOL wasAbleToLoadCustomView = NO;
+       AudioUnitCocoaViewInfo* cocoaViewInfo = NULL;
+       UInt32               numberOfClasses = 0;
+       UInt32     dataSize;
+       Boolean    isWritable;
+       NSString*           factoryClassName = 0;
+       NSURL*              CocoaViewBundlePath;
+
+       OSStatus result = AudioUnitGetPropertyInfo (*au->get_au(),
+                                                   kAudioUnitProperty_CocoaUI,
+                                                   kAudioUnitScope_Global, 
+                                                   0,
+                                                   &dataSize,
+                                                   &isWritable );
+
+       numberOfClasses = (dataSize - sizeof(CFURLRef)) / sizeof(CFStringRef);
+       
+       // Does view have custom Cocoa UI?
+       
+       if ((result == noErr) && (numberOfClasses > 0) ) {
+               cocoaViewInfo = (AudioUnitCocoaViewInfo *)malloc(dataSize);
+               if(AudioUnitGetProperty(*au->get_au(),
+                                       kAudioUnitProperty_CocoaUI,
+                                       kAudioUnitScope_Global,
+                                       0,
+                                       cocoaViewInfo,
+                                       &dataSize) == noErr) {
+
+                       CocoaViewBundlePath     = (NSURL *)cocoaViewInfo->mCocoaAUViewBundleLocation;
+                       
+                       // we only take the first view in this example.
+                       factoryClassName        = (NSString *)cocoaViewInfo->mCocoaAUViewClass[0];
+
+               } else {
+
+                       if (cocoaViewInfo != NULL) {
+                               free (cocoaViewInfo);
+                               cocoaViewInfo = NULL;
+                       }
+               }
+       }
+
+       NSRect crect = { { 0, 0 }, { 1, 1} };
+
+       // [A] Show custom UI if view has it
+
+       if (CocoaViewBundlePath && factoryClassName) {
+               NSBundle *viewBundle    = [NSBundle bundleWithPath:[CocoaViewBundlePath path]];
+               if (viewBundle == nil) {
+                       error << _("AUPluginUI: error loading AU view's bundle") << endmsg;
+                       return -1;
+               } else {
+                       Class factoryClass = [viewBundle classNamed:factoryClassName];
+                       if (!factoryClass) {
+                               error << _("AUPluginUI: error getting AU view's factory class from bundle") << endmsg;
+                               return -1;
+                       }
+                       
+                       // make sure 'factoryClass' implements the AUCocoaUIBase protocol
+                       if (!plugin_class_valid (factoryClass)) {
+                               error << _("AUPluginUI: U view's factory class does not properly implement the AUCocoaUIBase protocol") << endmsg;
+                               return -1;
+                       }
+                       // make a factory
+                       id factoryInstance = [[[factoryClass alloc] init] autorelease];
+                       if (factoryInstance == nil) {
+                               error << _("AUPluginUI: Could not create an instance of the AU view factory") << endmsg;
+                               return -1;
+                       }
+
+                       // make a view
+                       au_view = [factoryInstance uiViewForAudioUnit:*au->get_au() withSize:crect.size];
+                       
+                       // cleanup
+                       [CocoaViewBundlePath release];
+                       if (cocoaViewInfo) {
+                               UInt32 i;
+                               for (i = 0; i < numberOfClasses; i++)
+                                       CFRelease(cocoaViewInfo->mCocoaAUViewClass[i]);
+                               
+                               free (cocoaViewInfo);
+                       }
+                       wasAbleToLoadCustomView = YES;
+               }
+       }
+
+       if (!wasAbleToLoadCustomView) {
+               // [B] Otherwise show generic Cocoa view
+               au_view = [[AUGenericView alloc] initWithAudioUnit:*au->get_au()];
+               [(AUGenericView *)au_view setShowsExpertParameters:YES];
+       }
+
+       /* make a child cocoa window */
+
+       cocoa_window = [[NSWindow alloc] 
+                       initWithContentRect:crect
+                       styleMask:NSBorderlessWindowMask
+                       backing:NSBackingStoreBuffered
+                       defer:NO];
+
+       return 0;
+}
+
+int
+AUPluginUI::create_carbon_view (bool generic)
+{
+       OSStatus err;
+       ControlRef root_control;
+
+       Component editComponent = FindNextComponent(NULL, &carbon_descriptor);
+       
+       OpenAComponent(editComponent, &editView);
+       if (!editView) {
+               error << _("AU Carbon view: cannot open AU Component") << endmsg;
+               return -1;
+       }
+       
+       Rect r = { 100, 100, 100, 100 };
+       WindowAttributes attr = WindowAttributes (kWindowStandardHandlerAttribute |
+                                                 kWindowCompositingAttribute|
+                                                 kWindowNoShadowAttribute|
+                                                 kWindowNoTitleBarAttribute);
+
+       if ((err = CreateNewWindow(kDocumentWindowClass, attr, &r, &carbon_window)) != noErr) {
+               error << string_compose (_("AUPluginUI: cannot create carbon window (err: %1)"), err) << endmsg;
+               return -1;
+       }
+       
+       if ((err = GetRootControl(carbon_window, &root_control)) != noErr) {
+               error << string_compose (_("AUPlugin: cannot get root control of carbon window (err: %1)"), err) << endmsg;
+               return -1;
+       }
+
+       ControlRef viewPane;
+       Float32Point location  = { 0.0, 0.0 };
+       Float32Point size = { 0.0, 0.0 } ;
+
+       if ((err = AudioUnitCarbonViewCreate (editView, *au->get_au(), carbon_window, root_control, &location, &size, &viewPane)) != noErr) {
+               error << string_compose (_("AUPluginUI: cannot create carbon plugin view (err: %1)"), err) << endmsg;
+               return -1;
+       }
+
+       // resize window
+
+       Rect bounds;
+       GetControlBounds(viewPane, &bounds);
+       size.x = bounds.right-bounds.left;
+       size.y = bounds.bottom-bounds.top;
+       SizeWindow(carbon_window, (short) (size.x + 0.5), (short) (size.y + 0.5),  true);
+
+       prefwidth = (int) (size.x + 0.5);
+       prefheight = (int) (size.y + 0.5);
+
+#if 0  
+       mViewPaneResizer->WantEventTypes (GetControlEventTarget(mAUViewPane), GetEventTypeCount(resizeEvent), resizeEvent);
+#endif
+       return 0;
+}
+
+NSWindow*
+AUPluginUI::get_nswindow ()
+{
+       Gtk::Container* toplevel = get_toplevel();
+
+       if (!toplevel || !toplevel->is_toplevel()) {
+               error << _("AUPluginUI: no top level window!") << endmsg;
+               return 0;
+       }
+
+       NSWindow* true_parent = gdk_quartz_window_get_nswindow (toplevel->get_window()->gobj());
+
+       if (!true_parent) {
+               error << _("AUPluginUI: no top level window!") << endmsg;
+               return 0;
+       }
+
+       return true_parent;
+}
+
+void
+AUPluginUI::activate ()
+{
+       NSWindow* win = get_nswindow ();
+       [win setLevel:NSFloatingWindowLevel];
+       
+       if (carbon_parented) {
+               [cocoa_parent makeKeyAndOrderFront:nil];
+               ActivateWindow (carbon_window, TRUE);
+       } 
+}
+
+void
+AUPluginUI::deactivate ()
+{
+       /* nothing to do here */
+}
+
+
+OSStatus 
+_carbon_event (EventHandlerCallRef nextHandlerRef, EventRef event, void *userData) 
+{
+       return ((AUPluginUI*)userData)->carbon_event (nextHandlerRef, event);
+}
+
+OSStatus 
+AUPluginUI::carbon_event (EventHandlerCallRef nextHandlerRef, EventRef event)
+{
+       UInt32 eventKind = GetEventKind(event);
+       ClickActivationResult howToHandleClick;
+       NSWindow* win = get_nswindow ();
+
+       switch (eventKind) {
+       case kEventWindowHandleActivate:
+               [win makeMainWindow];
+               return eventNotHandledErr;
+               break;
+
+       case kEventWindowHandleDeactivate:
+               return eventNotHandledErr;
+               break;
+               
+       case kEventWindowGetClickActivation:
+               howToHandleClick = kActivateAndHandleClick;
+               SetEventParameter(event, kEventParamClickActivation, typeClickActivationResult, 
+                                 sizeof(ClickActivationResult), &howToHandleClick);
+               break;
+       }
+
+       return noErr;
+}
+
+int
+AUPluginUI::parent_carbon_window ()
+{
+       NSWindow* win = get_nswindow ();
+       int x, y;
+
+       if (!win) {
+               return -1;
+       }
+
+       Gtk::Container* toplevel = get_toplevel();
+
+       if (!toplevel || !toplevel->is_toplevel()) {
+               error << _("AUPluginUI: no top level window!") << endmsg;
+               return -1;
+       }
+       
+       toplevel->get_window()->get_root_origin (x, y);
+
+       /* compute how tall the title bar is, because we have to offset the position of the carbon window
+          by that much.
+       */
+
+       NSRect content_frame = [NSWindow contentRectForFrameRect:[win frame] styleMask:[win styleMask]];
+       NSRect wm_frame = [NSWindow frameRectForContentRect:content_frame styleMask:[win styleMask]];
+
+       int titlebar_height = wm_frame.size.height - content_frame.size.height;
+
+       MoveWindow (carbon_window, x, y + titlebar_height, false);
+       ShowWindow (carbon_window);
+
+       // create the cocoa window for the carbon one and make it visible
+       cocoa_parent = [[NSWindow alloc] initWithWindowRef: carbon_window];
+
+       EventTypeSpec   windowEventTypes[] = {
+               {kEventClassWindow, kEventWindowGetClickActivation },
+               {kEventClassWindow, kEventWindowHandleDeactivate },
+               {kEventClassWindow, kEventWindowHandleActivate }
+       };
+       
+       EventHandlerUPP   ehUPP = NewEventHandlerUPP(_carbon_event);
+       OSStatus result = InstallWindowEventHandler (carbon_window, ehUPP, 
+                                                    sizeof(windowEventTypes) / sizeof(EventTypeSpec), 
+                                                    windowEventTypes, this, &carbon_event_handler);
+       if (result != noErr) {
+               return -1;
+       }
+
+       [win addChildWindow:cocoa_parent ordered:NSWindowAbove];
+       [win setLevel:NSFloatingWindowLevel];
+       [win setHidesOnDeactivate:YES];
+
+       carbon_parented = true;
+               
+       return 0;
+}      
+
+int
+AUPluginUI::parent_cocoa_window ()
+{
+       NSWindow* win = get_nswindow ();
+
+       if (!win) {
+               return -1;
+       }
+
+       Gtk::Container* toplevel = get_toplevel();
+
+       if (!toplevel || !toplevel->is_toplevel()) {
+               error << _("AUPluginUI: no top level window!") << endmsg;
+               return -1;
+       }
+       
+       // Get the size of the new AU View's frame 
+       NSRect au_view_frame = [au_view frame];
+
+       if (au_view_frame.size.width > 500 || au_view_frame.size.height > 500) {
+               
+               /* its too big - use a scrollview */
+
+               NSRect frameRect = [[cocoa_window contentView] frame];
+               scroll_view = [[[NSScrollView alloc] initWithFrame:frameRect] autorelease];
+               [scroll_view setDrawsBackground:NO];
+               [scroll_view setHasHorizontalScroller:YES];
+               [scroll_view setHasVerticalScroller:YES];
+
+               NSSize frameSize = [NSScrollView  frameSizeForContentSize:au_view_frame.size
+                                   hasHorizontalScroller:[scroll_view hasHorizontalScroller]
+                                   hasVerticalScroller:[scroll_view hasVerticalScroller]
+                                   borderType:[scroll_view borderType]];
+               
+               // Create a new frame with same origin as current
+               // frame but size equal to the size of the new view
+               NSRect newFrame;
+               newFrame.origin = [scroll_view frame].origin;
+               newFrame.size = frameSize;
+               
+               // Set the new frame and document views on the scroll view
+               NSRect currentFrame = [scroll_view frame];
+               [scroll_view setFrame:newFrame];
+               [scroll_view setDocumentView:au_view];
+               
+               cerr << "scroll view size is " << newFrame.size.width << " x " << newFrame.size.height << endl;
+               
+               NSSize oldContentSize = [[cocoa_window contentView] frame].size;
+               NSSize newContentSize = oldContentSize;
+               
+               cerr << "original size is " << newContentSize.width << " x " << newContentSize.height << endl;
+               
+               newContentSize.width += (newFrame.size.width - currentFrame.size.width);
+               newContentSize.height += (newFrame.size.height - currentFrame.size.height);
+               
+               [cocoa_window setContentSize:newContentSize];
+               [cocoa_window setContentView:scroll_view];
+               
+       } else {
+
+               [cocoa_window setContentSize:au_view_frame.size];
+               [cocoa_window setContentView:au_view];
+
+       }
+
+       /* compute how tall the title bar is, because we have to offset the position of the child window
+          by that much.
+       */
+
+       NSRect content_frame = [NSWindow contentRectForFrameRect:[win frame] styleMask:[win styleMask]];
+       NSRect wm_frame = [NSWindow frameRectForContentRect:content_frame styleMask:[win styleMask]];
+       int titlebar_height = wm_frame.size.height - content_frame.size.height;
+
+       // move cocoa window into position relative to the toplevel window
+
+       NSRect view_frame = [[cocoa_window contentView] frame];
+       view_frame.origin.x = content_frame.origin.x;
+       view_frame.origin.y = content_frame.origin.y;
+
+       [cocoa_window setFrame:view_frame display:NO];
+
+       /* make top level window big enough to hold cocoa window and titlebar */
+       
+       content_frame.size.width = view_frame.size.width;
+       content_frame.size.height = view_frame.size.height + titlebar_height;
+
+       [win setFrame:content_frame display:NO];
+
+       /* now make cocoa window a child of this top level */
+
+       [win addChildWindow:cocoa_window ordered:NSWindowAbove];
+       // [win setLevel:NSFloatingWindowLevel];
+       [win setHidesOnDeactivate:YES];
+
+       cocoa_parented = true;
+
+       return 0;
+}
+
+void
+AUPluginUI::on_realize ()
+{
+       VBox::on_realize ();
+
+       if (cocoa_window) {
+               
+               if (parent_cocoa_window ()) {
+               }
+
+       } else if (carbon_window) {
+
+               if (parent_carbon_window ()) {
+                       // ShowWindow (carbon_window);
+               }
+       }
+}
+
+void
+AUPluginUI::on_show ()
+{
+       cerr << "AU plugin window shown\n";
+
+       VBox::on_show ();
+
+       if (cocoa_window) {
+               [cocoa_window setIsVisible:YES];
+       } else if (carbon_window) {
+               [cocoa_parent setIsVisible:YES];
+       }
+}
+
+bool
+AUPluginUI::start_updating (GdkEventAny* any)
+{
+       return false;
+}
+
+bool
+AUPluginUI::stop_updating (GdkEventAny* any)
+{
+       return false;
+}
+
+PlugUIBase*
+create_au_gui (boost::shared_ptr<PluginInsert> plugin_insert, VBox** box)
+{
+       AUPluginUI* aup = new AUPluginUI (plugin_insert);
+       (*box) = aup;
+       return aup;
+}
index 7a2606114c43dead8c74560f46dc0cda2e76d2ec..43862c9d0b4bcb72ca5941004a00bfa112bccf98 100644 (file)
@@ -599,10 +599,15 @@ AudioClock::set_smpte (nframes_t when, bool force)
                
                smpte_upper_info_label->set_text (buf);
                
-               if (session->smpte_drop_frames()) {
-                       sprintf (buf, "DF");
+               if ((fabs(smpte_frames - 29.97) < 0.0001) || smpte_frames == 30) {
+                       if (session->smpte_drop_frames()) {
+                               sprintf (buf, "DF");
+                       } else {
+                               sprintf (buf, "NDF");
+                       }
                } else {
-                       sprintf (buf, "NDF");
+                       // there is no drop frame alternative
+                       buf[0] = '\0';
                }
                
                smpte_lower_info_label->set_text (buf);
@@ -654,6 +659,32 @@ AudioClock::set_session (Session *s)
        }
 }
 
+void
+AudioClock::focus ()
+{
+       switch (_mode) {
+       case SMPTE:
+               hours_ebox.grab_focus ();
+               break;
+
+       case BBT:
+               bars_ebox.grab_focus ();
+               break;
+
+       case MinSec:
+               ms_hours_ebox.grab_focus ();
+               break;
+
+       case Frames:
+               frames_ebox.grab_focus ();
+               break;
+
+       case Off:
+               break;
+       }
+}
+
+
 bool
 AudioClock::field_key_press_event (GdkEventKey *ev, Field field)
 {
@@ -1020,7 +1051,7 @@ AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
        if (dragging) {
                gdk_pointer_ungrab (GDK_CURRENT_TIME);
                dragging = false;
-               if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
+               if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)){
                        // we actually dragged so return without setting editing focus, or we shift clicked
                        return true;
                }
@@ -1100,7 +1131,7 @@ AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
 
        switch (ev->button) {
        case 1:
-               if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+               if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
                        set (frames, true);
                        ValueChanged (); /* EMIT_SIGNAL */
                                        }
@@ -1116,7 +1147,7 @@ AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
                break;
 
        case 2:
-               if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+               if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
                        set (frames, true);
                        ValueChanged (); /* EMIT_SIGNAL */
                }
@@ -1149,7 +1180,7 @@ AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
        case GDK_SCROLL_UP:
               frames = get_frames (field);
               if (frames != 0) {
-                     if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+                     if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
                             frames *= 10;
                      }
                      set (current_time() + frames, true);
@@ -1160,7 +1191,7 @@ AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
        case GDK_SCROLL_DOWN:
               frames = get_frames (field);
               if (frames != 0) {
-                     if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+                     if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
                             frames *= 10;
                      }
                      
@@ -1192,13 +1223,13 @@ AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
        float pixel_frame_scale_factor = 0.2f;
 
 /*
-       if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control))  {
+       if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier))  {
                pixel_frame_scale_factor = 0.1f;
        }
 
 
        if (Keyboard::modifier_state_contains (ev->state, 
-                                              Keyboard::Control|Keyboard::Alt)) {
+                                              Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) {
 
                pixel_frame_scale_factor = 0.025f;
        }
@@ -1853,7 +1884,7 @@ AudioClock::build_ops_menu ()
        ops_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
        ops_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
        ops_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
-       ops_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
+       ops_items.push_back (MenuElem (_("Samples"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
        ops_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
 }
 
index 21a2755588704770b48cab1b599ab28474a62be2..1aa721b8648bd7ee168fcf52884257faa11c7576 100644 (file)
@@ -45,7 +45,9 @@ class AudioClock : public Gtk::HBox
        AudioClock (std::string clock_name, bool transient, std::string widget_name, bool editable, bool is_duration = false, bool with_info = false);
 
        Mode mode() const { return _mode; }
-       
+
+       void focus ();
+
        void set (nframes_t, bool force = false, nframes_t offset = 0, char which = 0);
        void set_mode (Mode);
        
index f101905012b604047461b876c75c50eeb85a42f8..96b8a57261ce48d4250f04e780dd8a35da9fad93 100644 (file)
@@ -1,7 +1,7 @@
 /*
     Copyright (C) 2001-2006 Paul Davis 
 
-    This program is free software; you can redistribute it and/or modify
+    This program is free software; you can r>edistribute 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.
@@ -411,8 +411,8 @@ void
 AudioRegionView::set_y_position_and_height (double y, double h)
 {
        //RegionView::set_y_position_and_height(y, h - 1);
-       RegionView::set_height (height);
-
+       RegionView::set_height (h);
+       
        const uint32_t wcnt = waves.size();
 
        _y_position = y;
@@ -1205,3 +1205,35 @@ AudioRegionView::color_handler ()
        envelope_active_changed();
 
 }
+
+void
+AudioRegionView::set_frame_color ()
+{
+       if (!frame) {
+               return;
+       }
+
+       if (_region->opaque()) {
+               fill_opacity = 130;
+       } else {
+               fill_opacity = 0;
+       }
+
+       uint32_t r,g,b,a;
+       
+       if (_selected && should_show_selection) {
+               frame->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_WaveForm.get();
+
+               UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_FrameBase.get(), &r, &g, &b, &a);
+               for (vector<ArdourCanvas::WaveView*>::iterator w = waves.begin(); w != waves.end(); ++w) {
+                       (*w)->property_wave_color() = RGBA_TO_UINT(r, g, b, fill_opacity ? fill_opacity : a);// Lets still use the theme's opacity value if Opaque is not set
+               }
+       } else {
+               UINT_TO_RGBA(ARDOUR_UI::config()->canvasvar_FrameBase.get(), &r, &g, &b, &a);
+               frame->property_fill_color_rgba() = RGBA_TO_UINT(r, g, b, fill_opacity ? fill_opacity : a);
+
+               for (vector<ArdourCanvas::WaveView*>::iterator w = waves.begin(); w != waves.end(); ++w) {
+                       (*w)->property_wave_color() = ARDOUR_UI::config()->canvasvar_WaveForm.get();
+               }
+       }
+}
index c8734da59b7d8fecf9a65461297bfd2721481906..f5110e6a7296535363bd9cdc7e16fa1472f81562 100644 (file)
@@ -161,7 +161,8 @@ class AudioRegionView : public RegionView
     void compute_colors (Gdk::Color&);
     void reset_width_dependent_items (double pixel_width);
     void set_waveview_data_src();
-    
+    void set_frame_color ();
+
     void color_handler ();
 
     vector<GnomeCanvasWaveViewCache*> wave_caches;
index c571cb1a7cc2a13bc909c75f5035fd9339658b34..a21de27b46826e7f6b06b73592bcce47f1bb9cca 100644 (file)
@@ -73,8 +73,6 @@ AudioStreamView::AudioStreamView (AudioTimeAxisView& tv)
        _amplitude_above_axis = 1.0;
 
        use_rec_regions = tv.editor.show_waveforms_recording ();
-
-
 }
 
 AudioStreamView::~AudioStreamView ()
index de99d25ae13a32891fd04275ab1c8d80680fb319..34566d4de285e0623c3b922360b04943be12ca2a 100644 (file)
@@ -43,6 +43,7 @@
 #include <ardour/location.h>
 #include <ardour/panner.h>
 #include <ardour/playlist.h>
+#include <ardour/profile.h>
 #include <ardour/session.h>
 #include <ardour/session_playlist.h>
 #include <ardour/utils.h>
@@ -156,8 +157,10 @@ AudioTimeAxisView::append_extra_display_menu_items ()
        MenuList& items = display_menu->items();
 
        // 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)));
+       if (!Profile->get_sae()) {
+               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);
@@ -177,8 +180,12 @@ AudioTimeAxisView::append_extra_display_menu_items ()
        waveform_items.push_back (RadioMenuElem (group, _("Traditional"), bind (mem_fun(*this, &AudioTimeAxisView::set_waveform_shape), Traditional)));
        traditional_item = static_cast<RadioMenuItem *> (&waveform_items.back());
 
-       waveform_items.push_back (RadioMenuElem (group, _("Rectified"), bind (mem_fun(*this, &AudioTimeAxisView::set_waveform_shape), Rectified)));
-       rectified_item = static_cast<RadioMenuItem *> (&waveform_items.back());
+       if (!Profile->get_sae()) {
+               waveform_items.push_back (RadioMenuElem (group, _("Rectified"), bind (mem_fun(*this, &AudioTimeAxisView::set_waveform_shape), Rectified)));
+               rectified_item = static_cast<RadioMenuItem *> (&waveform_items.back());
+       } else {
+               rectified_item = 0;
+       }
 
        waveform_items.push_back (SeparatorElem());
        
@@ -194,9 +201,11 @@ AudioTimeAxisView::append_extra_display_menu_items ()
        AudioStreamView* asv = audio_view();
        if (asv) {
                ignore_toggle = true;
-               if (asv->get_waveform_shape() == Rectified
+               if (asv->get_waveform_shape() == Rectified && rectified_item) {
                        rectified_item->set_active(true);
-               else traditional_item->set_active(true);
+               } else {
+                       traditional_item->set_active(true);
+               }
 
                if (asv->get_waveform_scale() == LogWaveform) 
                        logscale_item->set_active(true);
index fc73d49608a35bd10a7d9e67253dbc05ae1a8f4d..7d291b7a5d5b9f9c5061566b929f4ee11479b2a0 100644 (file)
@@ -41,6 +41,7 @@ CANVAS_VARIABLE(canvasvar_MarkerBarSeparator, "marker bar separator")
 CANVAS_VARIABLE(canvasvar_TempoBar, "tempo bar")
 CANVAS_VARIABLE(canvasvar_MeterBar, "meter bar")
 CANVAS_VARIABLE(canvasvar_MarkerBar, "marker bar")
+CANVAS_VARIABLE(canvasvar_CDMarkerBar, "cd marker bar")
 CANVAS_VARIABLE(canvasvar_RangeMarkerBar, "range marker bar")
 CANVAS_VARIABLE(canvasvar_TransportMarkerBar, "transport marker bar")
 CANVAS_VARIABLE(canvasvar_RangeDragBarRect, "range drag bar rect")
diff --git a/gtk2_ardour/cocoacarbon.mm b/gtk2_ardour/cocoacarbon.mm
new file mode 100644 (file)
index 0000000..b60352e
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+    Copyright (C) 2007 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 <Carbon/Carbon.h>
+#undef check // stupid, stupid carbon
+
+#include "ardour_ui.h"
+#include "actions.h"
+#include "opts.h"
+#include "sync-menu.h"
+
+#include <Appkit/Appkit.h>
+
+sigc::signal<void,bool> ApplicationActivationChanged;
+static EventHandlerRef  application_event_handler_ref;
+
+/* Called for clicks on the dock icon. Can be used to unminimize or
+ * create a new window for example.
+ */
+
+static OSErr
+handle_reopen_application (const AppleEvent *inAppleEvent, 
+                           AppleEvent       *outAppleEvent, 
+                           long              inHandlerRefcon)
+{
+       cerr << "reopen app\n";
+        return noErr;
+}
+
+static OSErr
+handle_quit_application (const AppleEvent *inAppleEvent, 
+                         AppleEvent       *outAppleEvent, 
+                         long              inHandlerRefcon)
+{
+       cerr << "quit app\n";
+       ARDOUR_UI::instance()->quit ();
+
+        return noErr;
+}
+
+static OSStatus 
+application_event_handler (EventHandlerCallRef nextHandlerRef, EventRef event, void *userData) 
+{
+       UInt32 eventKind = GetEventKind (event);
+       
+       switch (eventKind) {
+       case kEventAppActivated:
+               ApplicationActivationChanged (true); // EMIT SIGNAL
+               return eventNotHandledErr;
+
+       case kEventAppDeactivated:
+               ApplicationActivationChanged (false); // EMIT SIGNAL
+               return eventNotHandledErr;
+               
+       default:
+               // pass-thru all kEventClassApplication events we're not interested in.
+               break;
+       }
+       return eventNotHandledErr;
+}
+
+void
+ARDOUR_UI::platform_specific ()
+{
+        AEInstallEventHandler (kCoreEventClass, kAEReopenApplication, 
+                               handle_reopen_application, 0, true);
+
+        AEInstallEventHandler (kCoreEventClass, kAEQuitApplication, 
+                               handle_quit_application, 0, true);
+
+       Gtk::Widget* widget = ActionManager::get_widget ("/ui/Main/Session/Quit");
+       if (widget) {
+               ige_mac_menu_set_quit_menu_item ((GtkMenuItem*) widget->gobj());
+       }
+
+       IgeMacMenuGroup* group = ige_mac_menu_add_app_menu_group ();
+
+       widget = ActionManager::get_widget ("/ui/Main/Session/About");
+       if (widget) {
+               ige_mac_menu_add_app_menu_item (group, (GtkMenuItem*) widget->gobj(), 0);
+       }
+       widget = ActionManager::get_widget ("/ui/Main/Session/ToggleOptionsEditor");
+       if (widget) {
+               ige_mac_menu_add_app_menu_item (group, (GtkMenuItem*) widget->gobj(), 0);
+       }
+
+       EventTypeSpec applicationEventTypes[] = {
+               {kEventClassApplication, kEventAppActivated },
+               {kEventClassApplication, kEventAppDeactivated }
+       };      
+       
+       EventHandlerUPP ehUPP = NewEventHandlerUPP (application_event_handler);
+       
+       InstallApplicationEventHandler (ehUPP, sizeof(applicationEventTypes) / sizeof(EventTypeSpec), 
+                                       applicationEventTypes, 0, &application_event_handler_ref);
+}
+
+void
+ARDOUR_UI::platform_setup ()
+{
+       if (!ARDOUR_COMMAND_LINE::finder_invoked_ardour) {
+               
+               /* if invoked from the command line, make sure we're visible */
+               
+               [NSApp activateIgnoringOtherApps:YES];
+       } 
+}
index 8e9c4f07dd15b9b362dce7539922e1e5e85f704d..b5aebdfb8dab5972ae0ff57035e439d2d6f38b5e 100644 (file)
@@ -637,9 +637,15 @@ CrossfadeEditor::redraw ()
 
        for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
                fade[current].normative_curve.add ((*i)->x, (*i)->y);
-               fade[current].gain_curve.add (((*i)->x * len), (*i)->y);
+               double offset;
+               if (current==In)
+                       offset = xfade->in()->start();
+               else
+                       offset = xfade->out()->start()+xfade->out()->length()-xfade->length();
+               fade[current].gain_curve.add (((*i)->x * len) + offset, (*i)->y);
        }
 
+
        size_t npoints = (size_t) effective_width();
        float vec[npoints];
 
@@ -1079,6 +1085,11 @@ CrossfadeEditor::make_waves (boost::shared_ptr<AudioRegion> region, WhichFade wh
                        waveview->property_amplitude_above_axis() = 2.0;
                        waveview->property_wave_color() = color;
                        
+                       if (which==In)
+                               waveview->property_region_start() = region->start();
+                       else
+                               waveview->property_region_start() = region->start()+region->length()-xfade->length();
+
                        waveview->lower_to_bottom();
                        fade[which].waves.push_back (waveview);
                }
@@ -1110,13 +1121,13 @@ CrossfadeEditor::audition_both ()
        nframes_t left_length;
 
        if (preroll_button.get_active()) {
-               preroll = ARDOUR_UI::instance()->preroll_clock.current_duration ();
+               preroll = session.frame_rate() * 2;  //2 second hardcoded preroll for now
        } else {
                preroll = 0;
        }
 
        if (postroll_button.get_active()) {
-               postroll = ARDOUR_UI::instance()->postroll_clock.current_duration ();
+               postroll = session.frame_rate() * 2;  //2 second hardcoded postroll for now
        } else {
                postroll = 0;
        }
index b48f97c8da15d31e75a89bb53659ef23e53be2fe..1cbb2decd8e2d962affe41307ef9ec980ad07568 100644 (file)
@@ -18,7 +18,6 @@
 */
 
 /* Changing this order will break the menu */
-SNAPTYPE(SnapToFrame)
 SNAPTYPE(SnapToCDFrame)
 SNAPTYPE(SnapToSMPTEFrame)
 SNAPTYPE(SnapToSMPTESeconds)
@@ -33,13 +32,13 @@ SNAPTYPE(SnapToAThirdBeat)
 SNAPTYPE(SnapToBeat)
 SNAPTYPE(SnapToBar)
 SNAPTYPE(SnapToMark)
-SNAPTYPE(SnapToEditPoint)
 SNAPTYPE(SnapToRegionStart)
 SNAPTYPE(SnapToRegionEnd)
 SNAPTYPE(SnapToRegionSync)
 SNAPTYPE(SnapToRegionBoundary)
 
 /* Changing this order will break the menu */
+SNAPMODE(SnapOff)
 SNAPMODE(SnapNormal)
 SNAPMODE(SnapMagnetic)
 
index e0f8b24b5336c818d648b8fe21cbf9a22dc588d1..613c34f551f3133c48b8f543a416c11c1d4bfbfa 100644 (file)
@@ -110,7 +110,6 @@ const double Editor::timebar_height = 15.0;
 #include "editor_xpms"
 
 static const gchar *_snap_type_strings[] = {
-       N_("None"),
        N_("CD Frames"),
        N_("SMPTE Frames"),
        N_("SMPTE Seconds"),
@@ -125,7 +124,6 @@ static const gchar *_snap_type_strings[] = {
        N_("Beats"),
        N_("Bars"),
        N_("Marks"),
-       N_("Edit Point"),
        N_("Region starts"),
        N_("Region ends"),
        N_("Region syncs"),
@@ -134,7 +132,8 @@ static const gchar *_snap_type_strings[] = {
 };
 
 static const gchar *_snap_mode_strings[] = {
-       N_("Normal"),
+       N_("No Grid"),
+       N_("Grid"),
        N_("Magnetic"),
        0
 };
@@ -152,7 +151,7 @@ static const gchar *_zoom_focus_strings[] = {
        N_("Center"),
        N_("Playhead"),
        N_("Mouse"),
-       N_("Marker"),
+       N_("Edit Point"),
        0
 };
 
@@ -186,14 +185,15 @@ Editor::Editor ()
          minsec_label (_("Mins:Secs")),
          bbt_label (_("Bars:Beats")),
          smpte_label (_("Timecode")),
-         frame_label (_("Frames")),
+         frame_label (_("Samples")),
          tempo_label (_("Tempo")),
          meter_label (_("Meter")),
          mark_label (_("Location Markers")),
          range_mark_label (_("Range Markers")),
          transport_mark_label (_("Loop/Punch Ranges")),
+         cd_mark_label (_("CD Markers")),
 
-         edit_packer (3, 3, false),
+         edit_packer (3, 3, true),
 
          /* the values here don't matter: layout widgets
             reset them as needed.
@@ -221,7 +221,8 @@ Editor::Editor ()
 
          /* nudge */
 
-         nudge_clock (X_("nudge"), false, X_("NudgeClock"), true, true)
+         nudge_clock (X_("nudge"), false, X_("NudgeClock"), true, true),
+         meters_running(false)
 
 {
        constructed = false;
@@ -246,7 +247,6 @@ Editor::Editor ()
        clicked_routeview = 0;
        clicked_crossfadeview = 0;
        clicked_control_point = 0;
-       latest_regionview = 0;
        last_update_frame = 0;
        drag_info.item = 0;
        current_mixer_strip = 0;
@@ -257,15 +257,6 @@ Editor::Editor ()
        zoom_focus_strings = I18N (_zoom_focus_strings);
        edit_point_strings = I18N (_edit_point_strings);
 
-       snap_type = SnapToFrame;
-       set_snap_to (snap_type);
-
-       snap_mode = SnapNormal;
-       set_snap_mode (snap_mode);
-
-       _edit_point = EditAtMouse;
-       set_edit_point_preference (_edit_point);
-
        snap_threshold = 5.0;
        bbt_beat_subdivision = 4;
        canvas_width = 0;
@@ -292,7 +283,8 @@ Editor::Editor ()
        verbose_cursor_on = true;
        route_removal = false;
        show_automatic_regions_in_region_list = true;
-       region_list_sort_type = (Editing::RegionListSortType) 0; 
+
+       region_list_sort_type = (Editing::RegionListSortType) 0;
        have_pending_keyboard_selection = false;
        _follow_playhead = true;
        _xfade_visibility = true;
@@ -322,7 +314,7 @@ Editor::Editor ()
        entered_marker = 0;
        clear_entered_track = false;
        _new_regionviews_show_envelope = false;
-       current_timestretch = 0;
+       current_timefx = 0;
        in_edit_group_row_change = false;
        last_canvas_frame = 0;
        playhead_cursor = 0;
@@ -331,6 +323,8 @@ Editor::Editor ()
        _dragging_playhead = false;
        _dragging_edit_point = false;
        _dragging_hscrollbar = false;
+       select_new_marker = false;
+       zoomed_to_region = false;
 
        scrubbing_direction = 0;
 
@@ -350,6 +344,8 @@ Editor::Editor ()
        set_midi_edit_mode (MidiEditPencil, true);
        set_mouse_mode (MouseObject, true);
 
+       last_visual_state.frames_per_unit = 0;
+
        frames_per_unit = 2048; /* too early to use reset_zoom () */
        reset_hscrollbar_stepping ();
        
@@ -361,7 +357,7 @@ Editor::Editor ()
        initialize_canvas ();
 
        edit_controls_vbox.set_spacing (0);
-       horizontal_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
+       horizontal_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled), false);
        vertical_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling), true);
        
        track_canvas.set_hadjustment (horizontal_adjustment);
@@ -438,6 +434,10 @@ Editor::Editor ()
        mark_label.set_size_request (-1, (int)timebar_height);
        mark_label.set_alignment (1.0, 0.5);
        mark_label.set_padding (5,0);
+       cd_mark_label.set_name ("EditorTimeButton");
+       cd_mark_label.set_size_request (-1, (int)timebar_height);
+       cd_mark_label.set_alignment (1.0, 0.5);
+       cd_mark_label.set_padding (5,0);
        range_mark_label.set_name ("EditorTimeButton");
        range_mark_label.set_size_request (-1, (int)timebar_height);
        range_mark_label.set_alignment (1.0, 0.5);
@@ -510,7 +510,7 @@ Editor::Editor ()
        CellRendererToggle* route_list_visible_cell = dynamic_cast<CellRendererToggle*>(route_list_display.get_column_cell_renderer (0));
        route_list_visible_cell->property_activatable() = true;
        route_list_visible_cell->property_radio() = false;
-       
+
        route_display_model->signal_row_deleted().connect (mem_fun (*this, &Editor::route_list_delete));
        route_display_model->signal_row_changed().connect (mem_fun (*this, &Editor::route_list_change));
 
@@ -599,6 +599,10 @@ Editor::Editor ()
        region_list_display.append_column (_("Regions"), region_list_columns.name);
        region_list_display.set_headers_visible (false);
 
+       CellRendererText* region_name_cell = dynamic_cast<CellRendererText*>(region_list_display.get_column_cell_renderer (0));
+       region_name_cell->property_editable() = true;
+       region_name_cell->signal_edited().connect (mem_fun (*this, &Editor::region_name_edit));
+
        region_list_display.get_selection()->set_select_function (mem_fun (*this, &Editor::region_list_selection_filter));
        
        TreeViewColumn* tv_col = region_list_display.get_column(0);
@@ -675,9 +679,12 @@ Editor::Editor ()
        nlabel = manage (new Label (_("Edit Groups")));
        nlabel->set_angle (-90);
        the_notebook.append_page (*edit_group_display_packer, *nlabel);
-       nlabel = manage (new Label (_("Chunks")));
-       nlabel->set_angle (-90);
-       the_notebook.append_page (named_selection_scroller, *nlabel);
+       
+       if (!Profile->get_sae()) {
+               nlabel = manage (new Label (_("Chunks")));
+               nlabel->set_angle (-90);
+               the_notebook.append_page (named_selection_scroller, *nlabel);
+       }
 
        the_notebook.set_show_tabs (true);
        the_notebook.set_scrollable (true);
@@ -713,7 +720,14 @@ Editor::Editor ()
        /* register actions now so that set_state() can find them and set toggles/checks etc */
        
        register_actions ();
-       
+
+       snap_type = SnapToBeat;
+       set_snap_to (snap_type);
+       snap_mode = SnapOff;
+       set_snap_mode (snap_mode);
+       _edit_point = EditAtMouse;
+       set_edit_point_preference (_edit_point);
+
        XMLNode* node = ARDOUR_UI::instance()->editor_settings();
        set_state (*node);
 
@@ -882,19 +896,6 @@ Editor::tie_vertical_scrolling ()
        }
 
        controls_layout.get_vadjustment()->set_value (y1);
-
-#ifdef GTKOSX
-       /* the way idle updates and immediate window flushing work on GTK-Quartz
-          requires that we force an immediate redraw right here. The controls
-          layout will do the same all by itself, as does the canvas widget, but
-          most of the time, the canvas itself hasn't updated itself because its
-          idle handler hasn't run. consequently, the call that its layout makes
-          to gdk_window_process_updates() finds nothing to do. here, we force
-          the update to happen, then request a flush of the new window state.
-       */
-       track_canvas.update_now ();
-       gdk_window_process_updates (GTK_LAYOUT(track_canvas.gobj())->bin_window, true);
-#endif
 }
 
 void
@@ -1277,6 +1278,8 @@ Editor::connect_to_session (Session *t)
        /* register for undo history */
 
        session->register_with_memento_command_factory(_id, this);
+
+               start_updating ();
 }
 
 void
@@ -1320,6 +1323,14 @@ Editor::build_cursors ()
                transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0);
        }
 
+       { 
+               RefPtr<Bitmap> bits;
+               char pix[4] = { 0, 0, 0, 0 };
+               bits = Bitmap::create (pix, 2, 2);
+               Gdk::Color c;
+               transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0);
+       }
+
        grabber_cursor = new Gdk::Cursor (HAND2);
        cross_hair_cursor = new Gdk::Cursor (CROSSHAIR);
        trimmer_cursor =  new Gdk::Cursor (SB_H_DOUBLE_ARROW);
@@ -1602,10 +1613,21 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items)
 
        items.push_back (MenuElem (_("Sync points"), *sync_point_menu));
 
-       add_item_with_sensitivity (items, MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)), selection->regions.size() == 1);
+       //add_item_with_sensitivity (items, MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)), selection->regions.size() == 1);
        
        add_item_with_sensitivity (items, MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)), selection->regions.size() == 1);
 
+       items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region)));
+       items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
+       items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
+       items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun  (*this, &Editor::lower_region_to_bottom)));
+       items.push_back (SeparatorElem());
+       items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_point)));
+       items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
+       items.push_back (SeparatorElem());
+
+       items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::play_selected_region)));
+       items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
        items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
 
 #ifdef FFT_ANALYSIS
@@ -1779,7 +1801,8 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items)
        items.push_back (MenuElem (_("Trim"), *trim_menu));
        items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
        items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
-       items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
+       items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), false))));
+       items.push_back (MenuElem (_("Multi-Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
        items.push_back (MenuElem (_("Fill track"), (mem_fun(*this, &Editor::region_fill_track))));
        items.push_back (SeparatorElem());
        items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_selected_regions)));
@@ -1990,8 +2013,15 @@ Editor::add_bus_or_audio_track_context_items (Menu_Helpers::MenuList& edit_items
 void
 Editor::set_snap_to (SnapType st)
 {      
+   unsigned int snap_ind = (unsigned int)st;
        snap_type = st;
-       string str = snap_type_strings[(int) st];
+
+   if ( snap_ind > snap_type_strings.size() - 1 ) {
+      snap_ind = 0;
+      snap_type = (SnapType)snap_ind;
+   }
+
+       string str = snap_type_strings[snap_ind];
 
        if (str != snap_type_selector.get_active_text()) {
                snap_type_selector.set_active_text (str);
@@ -2029,6 +2059,8 @@ Editor::set_snap_mode (SnapMode mode)
 void
 Editor::set_edit_point_preference (EditPoint ep)
 {
+       bool changed = _edit_point != ep;
+
        _edit_point = ep;
        string str = edit_point_strings[(int)ep];
 
@@ -2036,6 +2068,33 @@ Editor::set_edit_point_preference (EditPoint ep)
                edit_point_selector.set_active_text (str);
        }
 
+       if (!changed) {
+               return;
+       }
+
+       if (Profile->get_sae()) {
+
+               switch (zoom_focus) {
+               case ZoomFocusMouse:
+               case ZoomFocusPlayhead:
+               case ZoomFocusEdit:
+                       switch (_edit_point) {
+                       case EditAtMouse:
+                               set_zoom_focus (ZoomFocusMouse);
+                               break;
+                       case EditAtPlayhead:
+                               set_zoom_focus (ZoomFocusPlayhead);
+                               break;
+                       case EditAtSelectedMarker:
+                               set_zoom_focus (ZoomFocusEdit);
+                               break;
+                       }
+                       break;
+               default:
+                       break;
+               }
+       } 
+                                               
        instant_save ();
 }
 
@@ -2314,7 +2373,7 @@ Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark)
        Location* before = 0;
        Location* after = 0;
 
-       if (!session) {
+       if (!session || snap_mode == SnapOff) {
                return;
        }
 
@@ -2325,9 +2384,6 @@ Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark)
        nframes64_t presnap = start;
 
        switch (snap_type) {
-       case SnapToFrame:
-               break;
-
        case SnapToCDFrame:
                if (direction) {
                        start = (nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
@@ -2429,10 +2485,6 @@ Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark)
                start = session->tempo_map().round_to_beat_subdivision (start, 3);
                break;
 
-       case SnapToEditPoint:
-               start = get_preferred_edit_position ();
-               break;
-
        case SnapToMark:
                if (for_mark) {
                        return;
@@ -2513,6 +2565,7 @@ Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark)
                }
                
        default:
+               /* handled at entry */
                return;
                
        }
@@ -2563,8 +2616,11 @@ Editor::setup_toolbar ()
 {
        string pixmap_path;
 
+#ifdef GTKOSX
+       const guint32 FUDGE = 38; // Combo's are stupid - they steal space from the entry for the button
+#else
        const guint32 FUDGE = 18; // Combo's are stupid - they steal space from the entry for the button
-
+#endif
 
        /* Mode Buttons (tool selection) */
 
@@ -2573,12 +2629,17 @@ Editor::setup_toolbar ()
        mouse_move_button.add (*(manage (new Image (::get_icon("tool_object")))));
        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_icon("tool_gain")))));
-       mouse_gain_button.set_relief(Gtk::RELIEF_NONE);
-       mouse_mode_buttons.push_back (&mouse_gain_button);
+
+       if (!Profile->get_sae()) {
+               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_icon("tool_gain")))));
+               mouse_gain_button.set_relief(Gtk::RELIEF_NONE);
+               mouse_mode_buttons.push_back (&mouse_gain_button);
+       }
+
        mouse_zoom_button.add (*(manage (new Image (::get_icon("tool_zoom")))));
        mouse_zoom_button.set_relief(Gtk::RELIEF_NONE);
        mouse_mode_buttons.push_back (&mouse_zoom_button);
@@ -2599,9 +2660,13 @@ Editor::setup_toolbar ()
        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);
+       if (!Profile->get_sae()) {
+               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);
+       if (!Profile->get_sae()) {
+               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.pack_start(mouse_note_button, true, true);
@@ -2692,7 +2757,7 @@ Editor::setup_toolbar ()
        ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to Session"));
 
        zoom_focus_selector.set_name ("ZoomFocusSelector");
-       Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Playhead", FUDGE, 0);
+       Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, _("Playhead"), FUDGE, 0);
        set_popdown_strings (zoom_focus_selector, zoom_focus_strings);
        zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
        ARDOUR_UI::instance()->tooltips().set_tip (zoom_focus_selector, _("Zoom focus"));
@@ -2706,19 +2771,19 @@ Editor::setup_toolbar ()
        snap_box.set_border_width (2);
 
        snap_type_selector.set_name ("SnapTypeSelector");
-       Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "SMPTE Seconds", 2+FUDGE, 10);
+       Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, _("SMPTE Seconds"), 2+FUDGE, 10);
        set_popdown_strings (snap_type_selector, snap_type_strings);
        snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
        ARDOUR_UI::instance()->tooltips().set_tip (snap_type_selector, _("Snap/Grid Units"));
 
        snap_mode_selector.set_name ("SnapModeSelector");
-       Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "Magnetic Snap", 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, snap_mode_strings);
        snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
        ARDOUR_UI::instance()->tooltips().set_tip (snap_mode_selector, _("Snap/Grid Mode"));
 
        edit_point_selector.set_name ("SnapModeSelector");
-       Gtkmm2ext::set_size_request_to_display_given_text (edit_point_selector, "Playhead", 2+FUDGE, 10);
+       Gtkmm2ext::set_size_request_to_display_given_text (edit_point_selector, _("Playhead"), 2+FUDGE, 10);
        set_popdown_strings (edit_point_selector, edit_point_strings);
        edit_point_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_point_selection_done));
        ARDOUR_UI::instance()->tooltips().set_tip (edit_point_selector, _("Edit point"));
@@ -3090,50 +3155,67 @@ Editor::history_changed ()
 }
 
 void
-Editor::duplicate_dialog (bool dup_region)
+Editor::duplicate_dialog (bool with_dialog)
 {
-       if (selection->regions.empty() && (selection->time.length() == 0)) {
-               return;
-       }
-
-       ArdourDialog win ("duplicate dialog");
-       Label  label (_("Duplicate how many times?"));
-       Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
-       SpinButton spinner (adjustment);
+       float times = 1.0f;
 
-       win.get_vbox()->set_spacing (12);
-       win.get_vbox()->pack_start (label);
-
-       /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
-          place, visually. so do this by hand.
-       */
-
-       win.get_vbox()->pack_start (spinner);
-       spinner.signal_activate().connect (sigc::bind (mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
+       if (mouse_mode == MouseRange) {
+               if (selection->time.length() == 0) {
+                       return;
+               }
+       }
 
-       label.show ();
-       spinner.show ();
+       
+       if (mouse_mode != MouseRange) {
 
-       win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
-       win.add_button (Stock::OK, RESPONSE_ACCEPT);
+               ensure_entered_region_selected (true);
 
-       win.set_position (WIN_POS_MOUSE);
+               if (selection->regions.empty()) {
+                       return;
+               }
+       }
 
-       spinner.grab_focus ();
+       if (with_dialog) {
 
-       switch (win.run ()) {
-       case RESPONSE_ACCEPT:
-               break;
-       default:
-               return;
+               ArdourDialog win ("duplicate dialog");
+               Label  label (_("Duplicate how many times?"));
+               Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
+               SpinButton spinner (adjustment);
+               
+               win.get_vbox()->set_spacing (12);
+               win.get_vbox()->pack_start (label);
+               
+               /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
+                  place, visually. so do this by hand.
+               */
+               
+               win.get_vbox()->pack_start (spinner);
+               spinner.signal_activate().connect (sigc::bind (mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
+               
+               label.show ();
+               spinner.show ();
+               
+               win.add_button (Stock::OK, RESPONSE_ACCEPT);
+               win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
+               
+               win.set_position (WIN_POS_MOUSE);
+               
+               spinner.grab_focus ();
+               
+               switch (win.run ()) {
+               case RESPONSE_ACCEPT:
+                       break;
+               default:
+                       return;
+               }
+               
+               times = adjustment.get_value();
        }
 
-       float times = adjustment.get_value();
-
-       if (!selection->regions.empty()) {
-               duplicate_some_regions (selection->regions, times);
-       } else {
+       if (mouse_mode == MouseRange) {
                duplicate_selection (times);
+       } else {
+               duplicate_some_regions (selection->regions, times);
        }
 }
 
@@ -3169,6 +3251,25 @@ Editor::set_verbose_canvas_cursor_text (const string & txt)
        verbose_canvas_cursor->property_text() = txt.c_str();
 }
 
+void
+Editor::set_edit_mode (EditMode m)
+{
+       Config->set_edit_mode (m);
+}
+
+void
+Editor::cycle_edit_mode ()
+{
+       switch (Config->get_edit_mode()) {
+       case Slide:
+               Config->set_edit_mode (Splice);
+               break;
+       case Splice:
+               Config->set_edit_mode (Slide);
+               break;
+       }
+}
+
 void
 Editor::edit_mode_selection_done ()
 {
@@ -3192,7 +3293,7 @@ void
 Editor::snap_type_selection_done ()
 {
        string choice = snap_type_selector.get_active_text();
-       SnapType snaptype = SnapToFrame;
+       SnapType snaptype = SnapToBeat;
 
        if (choice == _("Beats/3")) {
                snaptype = SnapToAThirdBeat;
@@ -3210,8 +3311,6 @@ Editor::snap_type_selection_done ()
                snaptype = SnapToBar;
        } else if (choice == _("Marks")) {
                snaptype = SnapToMark;
-       } else if (choice == _("Edit Point")) {
-               snaptype = SnapToEditPoint;
        } else if (choice == _("Region starts")) {
                snaptype = SnapToRegionStart;
        } else if (choice == _("Region ends")) {
@@ -3232,8 +3331,6 @@ Editor::snap_type_selection_done ()
                snaptype = SnapToSeconds;
        } else if (choice == _("Minutes")) {
                snaptype = SnapToMinutes;
-       } else if (choice == _("None")) {
-               snaptype = SnapToFrame;
        }
 
        RefPtr<RadioAction> ract = snap_type_action (snaptype);
@@ -3248,7 +3345,9 @@ Editor::snap_mode_selection_done ()
        string choice = snap_mode_selector.get_active_text();
        SnapMode mode = SnapNormal;
 
-       if (choice == _("Normal")) {
+       if (choice == _("No Grid")) {
+               mode = SnapOff;
+       } else if (choice == _("Grid")) {
                mode = SnapNormal;
        } else if (choice == _("Magnetic")) {
                mode = SnapMagnetic;
@@ -3261,6 +3360,26 @@ Editor::snap_mode_selection_done ()
        }
 }
 
+void
+Editor::cycle_edit_point (bool with_marker)
+{
+       switch (_edit_point) {
+       case EditAtMouse:
+               set_edit_point_preference (EditAtPlayhead);
+               break;
+       case EditAtPlayhead:
+               if (with_marker) {
+                       set_edit_point_preference (EditAtSelectedMarker);
+               } else {
+                       set_edit_point_preference (EditAtMouse);
+               }
+               break;
+       case EditAtSelectedMarker:
+               set_edit_point_preference (EditAtMouse);
+               break;
+       }
+}
+
 void
 Editor::edit_point_selection_done ()
 {
@@ -3268,11 +3387,11 @@ Editor::edit_point_selection_done ()
        EditPoint ep = EditAtSelectedMarker;
 
        if (choice == _("Marker")) {
-               _edit_point = EditAtSelectedMarker;
+               set_edit_point_preference (EditAtSelectedMarker);
        } else if (choice == _("Playhead")) {
-               _edit_point = EditAtPlayhead;
+               set_edit_point_preference (EditAtPlayhead);
        } else {
-               _edit_point = EditAtMouse;
+               set_edit_point_preference (EditAtMouse);
        }
 
        RefPtr<RadioAction> ract = edit_point_action (ep);
@@ -3925,6 +4044,13 @@ Editor::on_key_press_event (GdkEventKey* ev)
        return key_press_focus_accelerator_handler (*this, ev);
 }
 
+bool
+Editor::on_key_release_event (GdkEventKey* ev)
+{
+       return Gtk::Window::on_key_release_event (ev);
+       // return key_press_focus_accelerator_handler (*this, ev);
+}
+
 void
 Editor::reset_x_origin (nframes_t frame)
 {
@@ -3945,10 +4071,26 @@ Editor::reposition_and_zoom (nframes_t frame, double fpu)
 }
 
 void
-Editor::set_frames_per_unit (double fpu)
+Editor::swap_visual_state ()
 {
-       nframes_t frames;
+       if (last_visual_state.frames_per_unit == 0) {
+               // never set
+               return;
+       }
 
+       /* note: the correct functionality here is very dependent on the ordering of 
+          setting zoom focus, horizontal position and finally zoom. this is because
+          it is set_frames_per_unit() that overwrites last_visual_state.
+       */
+
+       set_zoom_focus (last_visual_state.zoom_focus);
+       reposition_and_zoom (last_visual_state.leftmost_frame, last_visual_state.frames_per_unit);
+       zoomed_to_region = false;
+}
+
+void
+Editor::set_frames_per_unit (double fpu)
+{
        /* this is the core function that controls the zoom level of the canvas. it is called
           whenever one or more calls are made to reset_zoom(). it executes in an idle handler.
        */
@@ -3961,9 +4103,6 @@ Editor::set_frames_per_unit (double fpu)
                fpu = 2.0;
        }
 
-       // convert fpu to frame count
-
-       frames = (nframes_t) floor (fpu * canvas_width);
        
        /* don't allow zooms that fit more than the maximum number
           of frames into an 800 pixel wide space.
@@ -3976,8 +4115,25 @@ Editor::set_frames_per_unit (double fpu)
        if (fpu == frames_per_unit) {
                return;
        }
+       
+       last_visual_state.frames_per_unit = frames_per_unit;
+       last_visual_state.leftmost_frame = leftmost_frame;
+       last_visual_state.zoom_focus = zoom_focus;
 
        frames_per_unit = fpu;
+       post_zoom ();
+}
+
+void
+Editor::post_zoom ()
+{
+       // convert fpu to frame count
+
+       nframes_t frames = (nframes_t) floor (frames_per_unit * canvas_width);
+
+       if (frames_per_unit != zoom_range_clock.current_duration()) {
+               zoom_range_clock.set (frames);
+       }
 
        if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
                if (!selection->tracks.empty()) {
@@ -3995,7 +4151,7 @@ Editor::set_frames_per_unit (double fpu)
 
        reset_hscrollbar_stepping ();
        reset_scrolling_region ();
-       
+
        if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
 
        instant_save ();
@@ -4006,7 +4162,7 @@ Editor::queue_visual_change (nframes_t where)
 {
        pending_visual_change.pending = VisualChange::Type (pending_visual_change.pending | VisualChange::TimeOrigin);
        pending_visual_change.time_origin = where;
-
+       
        if (pending_visual_change.idle_handler_id < 0) {
                pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this);
        }
@@ -4036,7 +4192,7 @@ Editor::idle_visual_changer ()
        VisualChange::Type p = pending_visual_change.pending;
 
        pending_visual_change.pending = (VisualChange::Type) 0;
-       
+
        if (p & VisualChange::ZoomLevel) {
                set_frames_per_unit (pending_visual_change.frames_per_unit);
 
@@ -4046,9 +4202,11 @@ Editor::idle_visual_changer ()
                update_tempo_based_rulers ();
        }
        if (p & VisualChange::TimeOrigin) {
-               if (pending_visual_change.time_origin != leftmost_frame) {
+               
+               nframes_t time_origin = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
+
+               if (time_origin != pending_visual_change.time_origin) {
                        horizontal_adjustment.set_value (pending_visual_change.time_origin/frames_per_unit);
-                       /* the signal handler will do the rest */
                } else {
                        update_fixed_rulers();
                        redisplay_tempo (true);
@@ -4073,22 +4231,35 @@ Editor::sort_track_selection ()
 }
 
 nframes64_t
-Editor::get_preferred_edit_position()
+Editor::get_preferred_edit_position (bool ignore_playhead)
 {
        bool ignored;
        nframes64_t where = 0;
+       EditPoint ep = _edit_point;
 
-       switch (_edit_point) {
+       if (entered_marker) {
+               return entered_marker->position();
+       }
+
+       if (ignore_playhead && ep == EditAtPlayhead) {
+               ep = EditAtSelectedMarker;
+       }
+
+       switch (ep) {
        case EditAtPlayhead:
                where = session->audible_frame();
                break;
                
        case EditAtSelectedMarker:
                if (!selection->markers.empty()) {
-                       bool whocares;
-                       Location* loc = find_location_from_marker (selection->markers.front(), whocares);
+                       bool is_start;
+                       Location* loc = find_location_from_marker (selection->markers.front(), is_start);
                        if (loc) {
-                               where =  loc->start();
+                               if (is_start) {
+                                       where =  loc->start();
+                               } else {
+                                       where = loc->end();
+                               }
                                break;
                        }
                } 
@@ -4204,6 +4375,48 @@ Editor::get_regions_at (nframes64_t where, const TrackSelection& ts) const
        return rs;
 }
 
+
+RegionSelection
+Editor::get_regions_after (nframes64_t where, const TrackSelection& ts) const
+{
+       RegionSelection rs;
+       const TrackSelection* tracks;
+
+       if (ts.empty()) {
+               tracks = &track_views;
+       } else {
+               tracks = &ts;
+       }
+
+       for (TrackSelection::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
+       
+               AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*t);
+
+               if (atv) {
+                       boost::shared_ptr<Diskstream> ds;
+                       boost::shared_ptr<Playlist> pl;
+                       
+                       if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
+
+                               Playlist::RegionList* regions = pl->regions_touched ((nframes_t) floor ( (double)where * ds->speed()), max_frames);
+
+                               for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
+
+                                       RegionView* rv = atv->audio_view()->find_view (*i);
+
+                                       if (rv) {
+                                               rs.push_back (rv);
+                                       }
+                               }
+
+                               delete regions;
+                       }
+               }
+       }
+
+       return rs;
+}
+
 RegionSelection&
 Editor::get_regions_for_action ()
 {
@@ -4215,3 +4428,37 @@ Editor::get_regions_for_action ()
        tmp_regions = get_regions_at (where, selection->tracks);
        return tmp_regions;
 }
+
+void
+Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions)
+{
+
+       for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+               
+               RouteTimeAxisView* tatv;
+               
+               if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
+                       
+                       boost::shared_ptr<Playlist> pl;
+                       vector<boost::shared_ptr<Region> > results;
+                       RegionView* marv;
+                       boost::shared_ptr<Diskstream> ds;
+                       
+                       if ((ds = tatv->get_diskstream()) == 0) {
+                               /* bus */
+                               continue;
+                       }
+                       
+                       if ((pl = (ds->playlist())) != 0) {
+                               pl->get_region_list_equivalent_regions (region, results);
+                       }
+                       
+                       for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
+                               if ((marv = tatv->view()->find_view (*ir)) != 0) {
+                                       regions.push_back (marv);
+                               }
+                       }
+                       
+               }
+       }
+}      
index faefda51ab5900b0c06f76f9cd46a9b7993fb5c2..69f7e18a7f4ce46835fdd046aadc06ff177e6b7b 100644 (file)
@@ -46,8 +46,8 @@
 
 #include <pbd/stateful.h>
 #include <ardour/session.h>
-#include <ardour/stretch.h>
 #include <ardour/tempo.h>
+#include <ardour/stretch.h>
 #include <ardour/location.h>
 #include <ardour/audioregion.h>
 
@@ -136,6 +136,8 @@ class Editor : public PublicEditor
                return (nframes_t) floor (canvas_width * frames_per_unit);
        }
 
+       void cycle_snap_mode ();
+       void cycle_snap_choice ();
        void set_snap_to (Editing::SnapType);
        void set_snap_mode (Editing::SnapMode);
        void set_snap_threshold (double pixel_distance) {snap_threshold = pixel_distance;}
@@ -177,6 +179,7 @@ class Editor : public PublicEditor
        /* things that need to be public to be used in the main menubar */
 
        void new_region_from_selection ();
+       void separate_regions_between (const TimeSelection&);
        void separate_region_from_selection ();
        void separate_regions_using_location (ARDOUR::Location&);
        void toggle_playback (bool with_abort);
@@ -222,6 +225,8 @@ class Editor : public PublicEditor
                return (gulong) rint ((frame / (frames_per_unit *  GNOME_CANVAS(track_canvas.gobj())->pixels_per_unit)));
        }
 
+       void flush_canvas ();
+
        /* selection */
 
        Selection& get_selection() const { return *selection; }
@@ -234,6 +239,7 @@ class Editor : public PublicEditor
        void select_all (Selection::Operation op);
        void invert_selection_in_selected_tracks ();
        void invert_selection ();
+       void deselect_all ();
 
        /* tempo */
 
@@ -260,7 +266,7 @@ class Editor : public PublicEditor
 
        void      set_zoom_focus (Editing::ZoomFocus);
        Editing::ZoomFocus get_zoom_focus () const { return zoom_focus; }
-       gdouble   get_current_zoom () { return frames_per_unit; }
+       double   get_current_zoom () const { return frames_per_unit; }
 
        void temporal_zoom_step (bool coarser);
 
@@ -268,8 +274,6 @@ class Editor : public PublicEditor
 
        PlaylistSelector& playlist_selector() const;
        void route_name_changed (TimeAxisView *);
-       gdouble        frames_per_unit;
-       nframes_t leftmost_frame;
        void clear_playlist (boost::shared_ptr<ARDOUR::Playlist>);
 
        void new_playlists (TimeAxisView* v);
@@ -330,6 +334,8 @@ class Editor : public PublicEditor
        /* layers */
        void set_layer_model (ARDOUR::LayerModel);
        void update_layering_model ();
+       
+       void toggle_link_region_and_track_selection ();
 
        /* redirect shared ops menu. caller must free returned menu */
 
@@ -354,11 +360,13 @@ class Editor : public PublicEditor
        void reset_zoom (double);
        void reposition_and_zoom (nframes_t, double);
 
-       nframes64_t get_preferred_edit_position ();
+       nframes64_t get_preferred_edit_position (bool ignore_playhead = false);
 
        bool update_mouse_speed ();
        bool decelerate_mouse_speed ();
 
+       void toggle_meter_updating();
+
   protected:
        void map_transport_state ();
        void map_position_change (nframes_t);
@@ -377,9 +385,24 @@ class Editor : public PublicEditor
  
        PlaylistSelector* _playlist_selector;
 
-       void          set_frames_per_unit (double);
+       struct VisualState {
+           double    frames_per_unit;
+           nframes_t leftmost_frame;
+           Editing::ZoomFocus zoom_focus;
+       };
+       
+       VisualState last_visual_state;
+
+       nframes_t   leftmost_frame;
+       double      frames_per_unit;
+       Editing::ZoomFocus zoom_focus;
+
+       void use_visual_state (const VisualState&);
+       void set_frames_per_unit (double);
+       void swap_visual_state ();
+       void post_zoom ();
 
-       Editing::MouseMode    mouse_mode;
+       Editing::MouseMode mouse_mode;
        Editing::MidiEditMode midi_edit_mode;
 
        int  post_maximal_editor_width;
@@ -406,6 +429,7 @@ class Editor : public PublicEditor
        void location_gone (ARDOUR::Location *);
        void remove_marker (ArdourCanvas::Item&, GdkEvent*);
        gint really_remove_marker (ARDOUR::Location* loc);
+       void goto_nth_marker (int nth);
 
        uint32_t location_marker_color;
        uint32_t location_range_color;
@@ -438,7 +462,9 @@ class Editor : public PublicEditor
 
        void hide_marker (ArdourCanvas::Item*, GdkEvent*);
        void clear_marker_display ();
-       void mouse_add_new_marker (nframes_t where);
+       void mouse_add_new_marker (nframes_t where, bool is_cd=false);
+       void update_cd_marker_display ();
+       void ensure_cd_marker_updated (LocationMarkers * lam, ARDOUR::Location * location);
 
        TimeAxisView*      clicked_axisview;
        RouteTimeAxisView* clicked_routeview;
@@ -447,8 +473,7 @@ class Editor : public PublicEditor
          * editor_canvas_events.cc
          */
        RegionView*        clicked_regionview;
-       
-       RegionView*        latest_regionview;
+       RegionSelection    latest_regionviews;
        uint32_t           clicked_selection;
        CrossfadeView*     clicked_crossfadeview;
        ControlPoint*      clicked_control_point;
@@ -473,11 +498,12 @@ class Editor : public PublicEditor
 
        void catch_vanishing_regionview (RegionView *);
 
-       bool set_selected_track (TimeAxisView&, Selection::Operation op = Selection::Set, bool no_remove=false);
+       void set_selected_track (TimeAxisView&, Selection::Operation op = Selection::Set, bool no_remove=false);
        void select_all_tracks ();
 
        bool set_selected_control_point_from_click (Selection::Operation op = Selection::Set, bool no_remove=false);
-       bool set_selected_track_from_click (bool press, Selection::Operation op = Selection::Set, bool no_remove=false);
+       void set_selected_track_from_click (bool press, Selection::Operation op = Selection::Set, bool no_remove=false);
+       void set_selected_track_as_side_effect (bool force = false);
        bool set_selected_regionview_from_click (bool press, Selection::Operation op = Selection::Set, bool no_track_remove=false);
 
        void set_selected_regionview_from_region_list (boost::shared_ptr<ARDOUR::Region> region, Selection::Operation op = Selection::Set);
@@ -539,6 +565,7 @@ class Editor : public PublicEditor
        ArdourCanvas::Group      *marker_group;
        ArdourCanvas::Group      *range_marker_group;
        ArdourCanvas::Group      *transport_marker_group;
+       ArdourCanvas::Group*      cd_marker_group;
        
        enum {
                ruler_metric_smpte = 0,
@@ -551,15 +578,17 @@ class Editor : public PublicEditor
                ruler_time_marker = 6,
                ruler_time_range_marker = 7,
                ruler_time_transport_marker = 8,
+               ruler_time_cd_marker = 9,
        };
 
        static GtkCustomMetric ruler_metrics[4];
-       bool                   ruler_shown[9];
+       bool                   ruler_shown[10];
        bool                   no_ruler_shown_update;
        
        gint ruler_button_press (GdkEventButton*);
        gint ruler_button_release (GdkEventButton*);
        gint ruler_mouse_motion (GdkEventMotion*);
+       bool ruler_scroll (GdkEventScroll* event);
 
        gint ruler_pressed_button;
        Gtk::Widget * ruler_grabbed_widget;
@@ -655,7 +684,8 @@ class Editor : public PublicEditor
        ArdourCanvas::SimpleRect* marker_bar;
        ArdourCanvas::SimpleRect* range_marker_bar;
        ArdourCanvas::SimpleRect* transport_marker_bar;
-
+       ArdourCanvas::SimpleRect* cd_marker_bar;
+       
        Gtk::Label  minsec_label;
        Gtk::Label  bbt_label;
        Gtk::Label  smpte_label;
@@ -665,6 +695,7 @@ class Editor : public PublicEditor
        Gtk::Label  mark_label;
        Gtk::Label  range_mark_label;
        Gtk::Label  transport_mark_label;
+       Gtk::Label  cd_mark_label;
        
 
        Gtk::VBox          time_button_vbox;
@@ -692,17 +723,23 @@ class Editor : public PublicEditor
        Cursor* playhead_cursor;
        ArdourCanvas::Group* cursor_group;
 
+       void    cursor_to_region_boundary (Cursor*, int32_t dir);
+       void    cursor_to_next_region_boundary (Cursor*);
+       void    cursor_to_previous_region_boundary (Cursor*);
        void    cursor_to_next_region_point (Cursor*, ARDOUR::RegionPoint);
        void    cursor_to_previous_region_point (Cursor*, ARDOUR::RegionPoint);
        void    cursor_to_region_point (Cursor*, ARDOUR::RegionPoint, int32_t dir);
        void    cursor_to_selection_start (Cursor *);
        void    cursor_to_selection_end   (Cursor *);
 
-       void    edit_point_to_next_region_point (ARDOUR::RegionPoint);
-       void    edit_point_to_previous_region_point (ARDOUR::RegionPoint);
-       void    edit_point_to_region_point (ARDOUR::RegionPoint, int32_t dir);
-       void    edit_point_to_selection_start ();
-       void    edit_point_to_selection_end   ();
+       void    selected_marker_to_region_boundary (int32_t dir);
+       void    selected_marker_to_next_region_boundary ();
+       void    selected_marker_to_previous_region_boundary ();
+       void    selected_marker_to_next_region_point (ARDOUR::RegionPoint);
+       void    selected_marker_to_previous_region_point (ARDOUR::RegionPoint);
+       void    selected_marker_to_region_point (ARDOUR::RegionPoint, int32_t dir);
+       void    selected_marker_to_selection_start ();
+       void    selected_marker_to_selection_end   ();
 
        void    select_all_selectables_using_cursor (Cursor *, bool);
        void    select_all_selectables_using_edit (bool);
@@ -710,6 +747,7 @@ class Editor : public PublicEditor
        void    select_range_between ();
 
        boost::shared_ptr<ARDOUR::Region> find_next_region (nframes_t, ARDOUR::RegionPoint, int32_t dir, TrackViewList&, TimeAxisView ** = 0);
+       nframes64_t find_next_region_boundary (nframes64_t, int32_t dir, const TrackViewList&);
 
        vector<nframes_t> region_boundary_cache;
        void build_region_boundary_cache ();
@@ -761,8 +799,7 @@ class Editor : public PublicEditor
 
        void tie_vertical_scrolling ();
        void canvas_horizontally_scrolled ();
-       static int _idle_canvas_horizontally_scrolled (void *arg);
-       bool idle_canvas_horizontally_scrolled ();
+       void canvas_scroll_to (nframes64_t);
 
        struct VisualChange {
            enum Type { 
@@ -803,8 +840,7 @@ class Editor : public PublicEditor
            
        RegionListDisplayModelColumns          region_list_columns;
        Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Region> > region_list_display;
-       std::list<sigc::connection> region_state_changed_connections;
-
+       
        Glib::RefPtr<Gtk::TreeStore>           region_list_model;
        Glib::RefPtr<Gtk::ToggleAction>        toggle_full_region_list_action;
        Glib::RefPtr<Gtk::ToggleAction>        toggle_show_auto_regions_action;
@@ -812,6 +848,8 @@ class Editor : public PublicEditor
        void region_list_region_changed (ARDOUR::Change, boost::weak_ptr<ARDOUR::Region>);
        void region_list_selection_changed ();
        bool region_list_selection_filter (const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::Path& path, bool yn);
+       void region_name_edit (const Glib::ustring&, const Glib::ustring&);
+       void get_regions_corresponding_to (boost::shared_ptr<ARDOUR::Region> region, std::vector<RegionView*>& regions);
 
        Gtk::Menu          *region_list_menu;
        Gtk::ScrolledWindow region_list_scroller;
@@ -961,14 +999,16 @@ class Editor : public PublicEditor
        void toggle_region_lock ();
        void toggle_region_opaque ();
        void toggle_region_position_lock ();
+       void raise_region ();
        void raise_region_to_top ();
+       void lower_region ();
        void lower_region_to_bottom ();
        void split_region ();
        void split_region_at (nframes_t);
        void split_regions_at (nframes_t, RegionSelection&);
        void crop_region_to_selection ();
        void crop_region_to (nframes_t start, nframes_t end);
-       void set_a_regions_sync_position (boost::shared_ptr<ARDOUR::Region>, nframes_t);
+       void set_sync_point (nframes64_t, const RegionSelection&);
        void set_region_sync_from_edit_point ();
        void remove_region_sync();
        void align_selection (ARDOUR::RegionPoint, nframes_t position, const RegionSelection&);
@@ -978,6 +1018,7 @@ class Editor : public PublicEditor
        void remove_selected_regions ();
        void remove_clicked_region ();
        void edit_region ();
+       void rename_region ();
        void duplicate_some_regions (RegionSelection&, float times);
        void duplicate_selection (float times);
        void region_fill_selection ();
@@ -1010,28 +1051,24 @@ class Editor : public PublicEditor
        int  get_prefix (float&, bool&);
 
        void keyboard_paste ();
-       void keyboard_duplicate_region ();
-       void keyboard_duplicate_selection ();
        void keyboard_insert_region_list_selection ();
 
        void region_from_selection ();
        void create_region_from_selection (std::vector<boost::shared_ptr<ARDOUR::AudioRegion> >&);
 
-       bool region_renamed;
-       void rename_region ();
-       void rename_region_finished (bool);
-
        void play_from_start ();
        void play_from_edit_point ();
+       void play_from_edit_point_and_return ();
        void play_selected_region ();
-       void audition_selected_region ();
+       void play_edit_range ();
        void loop_selected_region ();
        void play_location (ARDOUR::Location&);
        void loop_location (ARDOUR::Location&);
 
-       Editing::ZoomFocus zoom_focus;
-
        void temporal_zoom_selection ();
+       void temporal_zoom_region ();
+       void toggle_zoom_region ();
+       bool zoomed_to_region;
        void temporal_zoom_session ();
        void temporal_zoom (gdouble scale);
        void temporal_zoom_by_frame (nframes_t start, nframes_t end, const string & op);
@@ -1137,15 +1174,21 @@ class Editor : public PublicEditor
        void set_selection_from_loop ();
        void set_selection_from_audio_region ();
 
+       void add_location_mark (nframes64_t where);
        void add_location_from_audio_region ();
        void add_location_from_selection ();
        void set_loop_from_selection (bool play);
        void set_punch_from_selection ();
        
+       void set_loop_from_edit_range (bool play);
+       void set_loop_from_region (bool play);
+       void set_punch_from_edit_range ();
+
        void set_loop_range (nframes_t start, nframes_t end, std::string cmd);
        void set_punch_range (nframes_t start, nframes_t end, std::string cmd);
 
        void add_location_from_playhead_cursor ();
+       bool select_new_marker;
 
        void reverse_selection ();
        void edit_envelope ();
@@ -1199,15 +1242,20 @@ class Editor : public PublicEditor
        void set_fade_out_shape (ARDOUR::AudioRegion::FadeShape);
        
        void set_fade_length (bool in);
-
+       void toggle_fade_active (bool in);
        void set_fade_in_active (bool);
        void set_fade_out_active (bool);
        
        std::set<boost::shared_ptr<ARDOUR::Playlist> > motion_frozen_playlists;
+       RegionSelection pre_drag_region_selection;
        void region_drag_motion_callback (ArdourCanvas::Item*, GdkEvent*);
        void region_drag_finished_callback (ArdourCanvas::Item*, GdkEvent*);
        void create_region_drag_motion_callback (ArdourCanvas::Item*, GdkEvent*);
        void create_region_drag_finished_callback (ArdourCanvas::Item*, GdkEvent*);
+       bool check_region_drag_possible (RouteTimeAxisView**);
+       void possibly_copy_regions_during_grab (GdkEvent*);
+       void region_drag_splice_motion_callback (ArdourCanvas::Item*, GdkEvent*);
+       void region_drag_splice_finished_callback (ArdourCanvas::Item*, GdkEvent*);
 
        bool _dragging_playhead;
        bool _dragging_edit_point;
@@ -1282,6 +1330,7 @@ class Editor : public PublicEditor
        bool canvas_marker_bar_event (GdkEvent* event, ArdourCanvas::Item*);
        bool canvas_range_marker_bar_event (GdkEvent* event, ArdourCanvas::Item*);
        bool canvas_transport_marker_bar_event (GdkEvent* event, ArdourCanvas::Item*);
+       bool canvas_cd_marker_bar_event (GdkEvent* event, ArdourCanvas::Item*);
 
        bool canvas_imageframe_item_view_event(GdkEvent* event, ArdourCanvas::Item*,ImageFrameView*);
        bool canvas_imageframe_view_event(GdkEvent* event, ArdourCanvas::Item*,ImageFrameTimeAxis*);
@@ -1296,12 +1345,15 @@ class Editor : public PublicEditor
 
        bool canvas_playhead_cursor_event (GdkEvent* event, ArdourCanvas::Item*);
        bool track_canvas_scroll (GdkEventScroll* event);
+       bool time_canvas_scroll (GdkEventScroll* event);
 
        bool track_canvas_scroll_event (GdkEventScroll* event);
        bool track_canvas_button_press_event (GdkEventButton* event);
        bool track_canvas_button_release_event (GdkEventButton* event);
        bool track_canvas_motion_notify_event (GdkEventMotion* event);
 
+       bool time_canvas_scroll_event (GdkEventScroll* event);
+
        Gtk::Allocation canvas_allocation;
        bool canvas_idle_queued;
        void track_canvas_allocate (Gtk::Allocation alloc);
@@ -1311,11 +1363,8 @@ class Editor : public PublicEditor
 
        void kbd_driver (sigc::slot<void,GdkEvent*>, bool use_track_canvas = true, bool use_time_canvas = true, bool can_select = true);
        void kbd_mute_unmute_region ();
-       void kbd_set_sync_position ();
        void kbd_brush ();
-       void kbd_audition ();
 
-       void kbd_do_set_sync_position (GdkEvent* ev);
        void kbd_do_brush (GdkEvent*);
        void kbd_do_audition (GdkEvent*);
 
@@ -1396,6 +1445,7 @@ class Editor : public PublicEditor
        Gtk::Menu* range_marker_menu;
        Gtk::Menu* transport_marker_menu;
        Gtk::Menu* new_transport_marker_menu;
+       Gtk::Menu* cd_marker_menu;
        ArdourCanvas::Item* marker_menu_item;
 
        typedef list<Marker*> Marks;
@@ -1463,6 +1513,8 @@ class Editor : public PublicEditor
        Gtk::ComboBoxText edit_mode_selector;
        Gtk::VBox         edit_mode_box;
 
+       void set_edit_mode (ARDOUR::EditMode);
+       void cycle_edit_mode ();
        void edit_mode_selection_done ();
 
        Gtk::ComboBoxText snap_type_selector;
@@ -1553,7 +1605,8 @@ class Editor : public PublicEditor
        /* transport range select process */
        enum RangeMarkerOp {
                CreateRangeMarker,
-               CreateTransportMarker
+               CreateTransportMarker,
+               CreateCDMarker
        } range_marker_op;
 
        void start_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event, RangeMarkerOp);
@@ -1629,6 +1682,13 @@ class Editor : public PublicEditor
        bool ignore_route_order_sync;
 
        bool route_list_display_button_press (GdkEventButton*);
+       void route_list_display_drag_data_received  (const Glib::RefPtr<Gdk::DragContext>& context,
+                                                    gint                x,
+                                                    gint                y,
+                                                    const Gtk::SelectionData& data,
+                                                    guint               info,
+                                                    guint               time);
+
        bool route_list_selection_filter (const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::Path& path, bool yn);
 
        void route_list_change (const Gtk::TreeModel::Path&,const Gtk::TreeModel::iterator&);
@@ -1724,7 +1784,11 @@ class Editor : public PublicEditor
 
        void trim_finished_callback (ArdourCanvas::Item*, GdkEvent*);
        void thaw_region_after_trim (RegionView& rv);
-       
+
+       void trim_region_front();
+       void trim_region_back();
+       void trim_region (bool front);
+
        void trim_region_to_edit_point ();
        void trim_region_from_edit_point ();
        void trim_region_to_loop ();
@@ -1842,7 +1906,7 @@ class Editor : public PublicEditor
 
        /* duplication */
 
-       void duplicate_dialog (bool for_region);
+       void duplicate_dialog (bool with_dialog);
        
        nframes64_t event_frame (GdkEvent*, double* px = 0, double* py = 0) const;
 
@@ -1854,9 +1918,16 @@ class Editor : public PublicEditor
        void start_time_fx (ArdourCanvas::Item*, GdkEvent*);
        void end_time_fx (ArdourCanvas::Item*, GdkEvent*);
 
-       struct TimeStretchDialog : public ArdourDialog {
-           ARDOUR::TimeStretchRequest request;
+       struct TimeFXDialog : public ArdourDialog {
+           ARDOUR::TimeFXRequest request;
            Editor&               editor;
+           bool                  pitching;
+           Gtk::Adjustment       pitch_octave_adjustment;
+           Gtk::Adjustment       pitch_semitone_adjustment;
+           Gtk::Adjustment       pitch_cent_adjustment;
+           Gtk::SpinButton       pitch_octave_spinner;
+           Gtk::SpinButton       pitch_semitone_spinner;
+           Gtk::SpinButton       pitch_cent_spinner;
            RegionSelection       regions;
            Gtk::ProgressBar      progress_bar;
            Gtk::ToggleButton     quick_button;
@@ -1867,24 +1938,28 @@ class Editor : public PublicEditor
            Gtk::VBox             packer;
            int                   status;
 
-           TimeStretchDialog (Editor& e);
+           TimeFXDialog (Editor& e, bool for_pitch);
 
            gint update_progress ();
            sigc::connection first_cancel;
            sigc::connection first_delete;
-           void cancel_timestretch_in_progress ();
-           gint delete_timestretch_in_progress (GdkEventAny*);
+           void cancel_in_progress ();
+           gint delete_in_progress (GdkEventAny*);
        };
 
        /* "whats mine is yours" */
 
-       friend class TimeStretchDialog;
+       friend class TimeFXDialog;
 
-       TimeStretchDialog* current_timestretch;
+       TimeFXDialog* current_timefx;
 
-       static void* timestretch_thread (void *arg);
-       int run_timestretch (RegionSelection&, float fraction);
-       void do_timestretch (TimeStretchDialog&);
+       static void* timefx_thread (void *arg);
+       void do_timefx (TimeFXDialog&);
+
+       int time_stretch (RegionSelection&, float fraction);
+       int pitch_shift (RegionSelection&, float cents);
+       void pitch_shift_regions ();
+       int time_fx (RegionSelection&, float val, bool pitching);
 
        /* editor-mixer strip */
 
@@ -1986,7 +2061,8 @@ class Editor : public PublicEditor
 
        TimeAxisView* entered_track;
        RegionView*   entered_regionview;
-       void ensure_entered_selected ();
+       void ensure_entered_region_selected (bool op_acts_on_objects = false);
+       void ensure_entered_track_selected (bool op_acts_on_objects = false);
        bool clear_entered_track;
        gint left_track_canvas (GdkEventCrossing*);
        void set_entered_track (TimeAxisView*);
@@ -2007,6 +2083,7 @@ class Editor : public PublicEditor
        Gtk::CheckMenuItem* region_opaque_item;
        
        bool on_key_press_event (GdkEventKey*);
+       bool on_key_release_event (GdkEventKey*);
 
        void session_state_saved (string);
 
@@ -2022,6 +2099,7 @@ class Editor : public PublicEditor
        Gtk::ComboBoxText edit_point_selector;
 
        void set_edit_point_preference (Editing::EditPoint ep);
+       void cycle_edit_point (bool with_marker);
        void set_edit_point ();
        void edit_point_selection_done ();
        void edit_point_chosen (Editing::EditPoint);
@@ -2035,6 +2113,7 @@ class Editor : public PublicEditor
        bool get_edit_op_range (nframes64_t& start, nframes64_t& end) const;
 
        RegionSelection get_regions_at (nframes64_t where, const TrackSelection& ts) const;
+       RegionSelection get_regions_after (nframes64_t where, const TrackSelection& ts) const;
        
        RegionSelection tmp_regions;
        
@@ -2043,10 +2122,11 @@ class Editor : public PublicEditor
        sigc::connection fast_screen_update_connection;
        gint start_updating ();
        gint stop_updating ();
-       void toggle_meter_updating();
        void fast_update_strips ();
-
        bool meters_running;
+
+       void select_next_route ();
+       void select_prev_route ();
 };
 
 #endif /* __ardour_editor_h__ */
index 8b607f50809d83359fcac91651801736a45228f6..fd95fd46b9d42ace6e92a63d0e75ebf1e1a2752b 100644 (file)
@@ -63,10 +63,13 @@ Editor::register_actions ()
        ActionManager::register_action (editor_actions, X_("Timecode"), _("Timecode fps"));
        ActionManager::register_action (editor_actions, X_("Pullup"), _("Pullup / Pulldown"));
        ActionManager::register_action (editor_actions, X_("Subframes"), _("Subframes"));
+       ActionManager::register_action (editor_actions, X_("LocateToMarker"), _("Locate To Markers"));
 
 
        /* add named actions for the editor */
 
+       ActionManager::register_toggle_action (editor_actions, "link-region-and-track-selection", _("Link Region/Track Selection"), mem_fun (*this, &Editor::toggle_link_region_and_track_selection));
+
        act = ActionManager::register_toggle_action (editor_actions, "show-editor-mixer", _("Show Editor Mixer"), mem_fun (*this, &Editor::editor_mixer_button_toggled));
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_toggle_action (editor_actions, "show-editor-list", _("Show Editor List"), mem_fun (*this, &Editor::editor_list_button_toggled));
@@ -86,6 +89,11 @@ Editor::register_actions ()
        act = ActionManager::register_toggle_action (editor_actions, "toggle-auto-xfades", _("Created Automatically"), mem_fun(*this, &Editor::toggle_auto_xfade));
        ActionManager::session_sensitive_actions.push_back (act);
 
+       act = ActionManager::register_action (editor_actions, "playhead-to-next-region-boundary", _("Playhead to Next Region Boundary"), bind (mem_fun(*this, &Editor::cursor_to_next_region_boundary), playhead_cursor));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "playhead-to-previous-region-boundary", _("Playhead to Previous Region Boundary"), bind (mem_fun(*this, &Editor::cursor_to_previous_region_boundary), playhead_cursor));
+       ActionManager::session_sensitive_actions.push_back (act);
+
        act = ActionManager::register_action (editor_actions, "playhead-to-next-region-start", _("Playhead to Next Region Start"), bind (mem_fun(*this, &Editor::cursor_to_next_region_point), playhead_cursor, RegionPoint (Start)));
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "playhead-to-next-region-end", _("Playhead to Next Region End"), bind (mem_fun(*this, &Editor::cursor_to_next_region_point), playhead_cursor, RegionPoint (End)));
@@ -100,23 +108,28 @@ Editor::register_actions ()
        act = ActionManager::register_action (editor_actions, "playhead-to-previous-region-sync", _("Playhead to Previous Region Sync"), bind (mem_fun(*this, &Editor::cursor_to_previous_region_point), playhead_cursor, RegionPoint (SyncPoint)));
        ActionManager::session_sensitive_actions.push_back (act);
 
-       act = ActionManager::register_action (editor_actions, "edit-cursor-to-next-region-start", _("Edit Cursor to Next Region Start"), bind (mem_fun(*this, &Editor::edit_point_to_next_region_point), RegionPoint (Start)));
+       act = ActionManager::register_action (editor_actions, "selected-marker-to-next-region-boundary", _("to Next Region Boundary"), mem_fun(*this, &Editor::selected_marker_to_next_region_boundary));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "selected-marker-to-previous-region-boundary", _("to Previous Region Boundary"), mem_fun(*this, &Editor::selected_marker_to_previous_region_boundary));
+       ActionManager::session_sensitive_actions.push_back (act);
+
+       act = ActionManager::register_action (editor_actions, "edit-cursor-to-next-region-start", _("to Next Region Start"), bind (mem_fun(*this, &Editor::selected_marker_to_next_region_point), RegionPoint (Start)));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "edit-cursor-to-next-region-end", _("Edit Cursor to Next Region End"), bind (mem_fun(*this, &Editor::edit_point_to_next_region_point), RegionPoint (End)));
+       act = ActionManager::register_action (editor_actions, "edit-cursor-to-next-region-end", _("to Next Region End"), bind (mem_fun(*this, &Editor::selected_marker_to_next_region_point), RegionPoint (End)));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "edit-cursor-to-next-region-sync", _("Edit Cursor to Next Region Sync"), bind (mem_fun(*this, &Editor::edit_point_to_next_region_point), RegionPoint (SyncPoint)));
+       act = ActionManager::register_action (editor_actions, "edit-cursor-to-next-region-sync", _("to Next Region Sync"), bind (mem_fun(*this, &Editor::selected_marker_to_next_region_point), RegionPoint (SyncPoint)));
        ActionManager::session_sensitive_actions.push_back (act);
 
-       act = ActionManager::register_action (editor_actions, "edit-cursor-to-previous-region-start", _("Edit Cursor to Previous Region Start"), bind (mem_fun(*this, &Editor::edit_point_to_previous_region_point), RegionPoint (Start)));
+       act = ActionManager::register_action (editor_actions, "edit-cursor-to-previous-region-start", _("to Previous Region Start"), bind (mem_fun(*this, &Editor::selected_marker_to_previous_region_point), RegionPoint (Start)));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "edit-cursor-to-previous-region-end", _("Edit Cursor to Previous Region End"), bind (mem_fun(*this, &Editor::edit_point_to_previous_region_point), RegionPoint (End)));
+       act = ActionManager::register_action (editor_actions, "edit-cursor-to-previous-region-end", _("to Previous Region End"), bind (mem_fun(*this, &Editor::selected_marker_to_previous_region_point), RegionPoint (End)));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "edit-cursor-to-previous-region-sync", _("Edit Cursor to Previous Region Sync"), bind (mem_fun(*this, &Editor::edit_point_to_previous_region_point), RegionPoint (SyncPoint)));
+       act = ActionManager::register_action (editor_actions, "edit-cursor-to-previous-region-sync", _("to Previous Region Sync"), bind (mem_fun(*this, &Editor::selected_marker_to_previous_region_point), RegionPoint (SyncPoint)));
        ActionManager::session_sensitive_actions.push_back (act);
 
-        act = ActionManager::register_action (editor_actions, "edit-cursor-to-range-start", _("Edit Cursor to Range Start"), mem_fun(*this, &Editor::edit_point_to_selection_start));
+        act = ActionManager::register_action (editor_actions, "edit-cursor-to-range-start", _("to Range Start"), mem_fun(*this, &Editor::selected_marker_to_selection_start));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "edit-cursor-to-range-end", _("Edit Cursor to Range End"), mem_fun(*this, &Editor::edit_point_to_selection_end));
+       act = ActionManager::register_action (editor_actions, "edit-cursor-to-range-end", _("to Range End"), mem_fun(*this, &Editor::selected_marker_to_selection_end));
        ActionManager::session_sensitive_actions.push_back (act);
 
        act = ActionManager::register_action (editor_actions, "playhead-to-range-start", _("Playhead to Range Start"), bind (mem_fun(*this, &Editor::cursor_to_selection_start), playhead_cursor));
@@ -126,9 +139,13 @@ Editor::register_actions ()
 
        act = ActionManager::register_action (editor_actions, "select-all", _("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "select-all-after-edit-cursor", _("Select All After Edit Cursor"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), true));
+       act = ActionManager::register_action (editor_actions, "deselect-all", _("Deselect All"), mem_fun(*this, &Editor::deselect_all));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "select-all-before-edit-cursor", _("Select All Before Edit Cursor"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), false));
+       act = ActionManager::register_action (editor_actions, "invert-selection", _("Invert Selection"), mem_fun(*this, &Editor::invert_selection));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "select-all-after-edit-cursor", _("Select All After Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), true));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "select-all-before-edit-cursor", _("Select All Before Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), false));
        ActionManager::session_sensitive_actions.push_back (act);
 
        act = ActionManager::register_action (editor_actions, "select-all-after-playhead", _("Select All After Playhead"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true));
@@ -137,7 +154,7 @@ Editor::register_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "select-all-between-cursors", _("Select All Between Playhead & Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_between), false));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "select-all-within-cursors", _("Select All Between Playhead & Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_between), true));
+       act = ActionManager::register_action (editor_actions, "select-all-within-cursors", _("Select All Within Playhead & Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_between), true));
        ActionManager::session_sensitive_actions.push_back (act);
 
        act = ActionManager::register_action (editor_actions, "select-range-between-cursors", _("Select Range Between Playhead & Edit Point"), mem_fun(*this, &Editor::select_range_between));
@@ -147,6 +164,31 @@ Editor::register_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
                act = ActionManager::register_action (editor_actions, "select-all-in-loop-range", _("Select All in Loop Range"), mem_fun(*this, &Editor::select_all_selectables_using_loop));
        ActionManager::session_sensitive_actions.push_back (act);
+       
+               act = ActionManager::register_action (editor_actions, "select-next-route", _("Select Next Track/Bus"), mem_fun(*this, &Editor::select_next_route));
+       ActionManager::session_sensitive_actions.push_back (act);
+               act = ActionManager::register_action (editor_actions, "select-prev-route", _("Select Previous Track/Bus"), mem_fun(*this, &Editor::select_prev_route));
+       ActionManager::session_sensitive_actions.push_back (act);
+       
+
+       act = ActionManager::register_action (editor_actions, "goto-mark-1", _("Locate to Mark 1"), bind (mem_fun (*this, &Editor::goto_nth_marker), 0));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "goto-mark-2", _("Locate to Mark 2"), bind (mem_fun (*this, &Editor::goto_nth_marker), 1));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "goto-mark-3", _("Locate to Mark 3"), bind (mem_fun (*this, &Editor::goto_nth_marker), 2));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "goto-mark-4", _("Locate to Mark 4"), bind (mem_fun (*this, &Editor::goto_nth_marker), 3));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "goto-mark-5", _("Locate to Mark 5"), bind (mem_fun (*this, &Editor::goto_nth_marker), 4));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "goto-mark-6", _("Locate to Mark 6"), bind (mem_fun (*this, &Editor::goto_nth_marker), 5));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "goto-mark-7", _("Locate to Mark 7"), bind (mem_fun (*this, &Editor::goto_nth_marker), 6));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "goto-mark-8", _("Locate to Mark 8"), bind (mem_fun (*this, &Editor::goto_nth_marker), 7));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "goto-mark-9", _("Locate to Mark 9"), bind (mem_fun (*this, &Editor::goto_nth_marker), 8));
+       ActionManager::session_sensitive_actions.push_back (act);
 
        act = ActionManager::register_action (editor_actions, "jump-forward-to-mark", _("Jump Forward to Mark"), mem_fun(*this, &Editor::jump_forward_to_mark));
        ActionManager::session_sensitive_actions.push_back (act);
@@ -164,12 +206,17 @@ Editor::register_actions ()
        act = ActionManager::register_action (editor_actions, "nudge-next-backward", _("Nudge Next Backward"), bind (mem_fun(*this, &Editor::nudge_backward), true));
        ActionManager::session_sensitive_actions.push_back (act);
 
+
        act = ActionManager::register_action (editor_actions, "temporal-zoom-out", _("Zoom Out"), bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "temporal-zoom-in", _("Zoom In"), bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "zoom-to-session", _("Zoom to Session"), mem_fun(*this, &Editor::temporal_zoom_session));
        ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "zoom-to-region", _("Zoom to Region"), mem_fun(*this, &Editor::toggle_zoom_region));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "toggle-zoom", _("Toggle Zoom State"), mem_fun(*this, &Editor::swap_visual_state));
+       ActionManager::session_sensitive_actions.push_back (act);
 
        act = ActionManager::register_action (editor_actions, "scroll-tracks-up", _("Scroll Tracks Up"), mem_fun(*this, &Editor::scroll_tracks_up));
        ActionManager::session_sensitive_actions.push_back (act);
@@ -186,9 +233,9 @@ Editor::register_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "goto", _("goto"), mem_fun(*this, &Editor::goto_frame));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "center-playhead", _("Center Playhead"), mem_fun(*this, &Editor::center_playhead));
+       act = ActionManager::register_action (editor_actions, "center-playhead", _("to Center"), mem_fun(*this, &Editor::center_playhead));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "center-edit-cursor", _("Center Edit Point"), mem_fun(*this, &Editor::center_edit_point));
+       act = ActionManager::register_action (editor_actions, "center-edit-cursor", _("to Center"), mem_fun(*this, &Editor::center_edit_point));
        ActionManager::session_sensitive_actions.push_back (act);
 
        act = ActionManager::register_action (editor_actions, "scroll-playhead-forward", _("Playhead forward"), bind (mem_fun(*this, &Editor::scroll_playhead), true));;
@@ -196,11 +243,15 @@ Editor::register_actions ()
        act = ActionManager::register_action (editor_actions, "scroll-playhead-backward", _("Playhead Backward"), bind (mem_fun(*this, &Editor::scroll_playhead), false));
        ActionManager::session_sensitive_actions.push_back (act);
 
-       act = ActionManager::register_action (editor_actions, "playhead-to-edit", _("Playhead to Edit"), bind (mem_fun(*this, &Editor::cursor_align), true));
+       act = ActionManager::register_action (editor_actions, "playhead-to-edit", _("to Edit"), bind (mem_fun(*this, &Editor::cursor_align), true));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "edit-to-playhead", _("Edit to Playhead"), bind (mem_fun(*this, &Editor::cursor_align), false));
+       act = ActionManager::register_action (editor_actions, "edit-to-playhead", _("to Playhead"), bind (mem_fun(*this, &Editor::cursor_align), false));
        ActionManager::session_sensitive_actions.push_back (act);
 
+       act = ActionManager::register_action (editor_actions, "trim-front", _("Trim start at edit point"), mem_fun(*this, &Editor::trim_region_front));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "trim-back", _("Trim end at edit point"), mem_fun(*this, &Editor::trim_region_back));
+       ActionManager::session_sensitive_actions.push_back (act);
 
        act = ActionManager::register_action (editor_actions, "trim-from-start", _("Start to edit point"), mem_fun(*this, &Editor::trim_region_from_edit_point));
        ActionManager::session_sensitive_actions.push_back (act);
@@ -210,11 +261,28 @@ Editor::register_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "trim-region-to-punch", _("Trim To Punch"), mem_fun(*this, &Editor::trim_region_to_punch));
        ActionManager::session_sensitive_actions.push_back (act);
+
+       act = ActionManager::register_action (editor_actions, "set-loop-from-edit-range", _("Set Loop From Edit Range"), bind (mem_fun(*this, &Editor::set_loop_from_edit_range), false));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "set-loop-from-region", _("Set Loop From Region"), bind (mem_fun(*this, &Editor::set_loop_from_region), false));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "loop-region", _("Loop Region"), bind (mem_fun(*this, &Editor::set_loop_from_region), true));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "set-punch-from-edit-range", _("Set Punch From Edit Range"), mem_fun(*this, &Editor::set_punch_from_edit_range));
+       ActionManager::session_sensitive_actions.push_back (act);
+       
+       
+       act = ActionManager::register_action (editor_actions, "pitch-shift-region", _("Transpose"), mem_fun(*this, &Editor::pitch_shift_regions));
+       ActionManager::session_sensitive_actions.push_back (act);
        
        act = ActionManager::register_action (editor_actions, "set-fade-in-length", _("Set Fade In Length"), bind (mem_fun(*this, &Editor::set_fade_length), true));
        ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "toggle-fade-in-active", _("Toggle Fade In Active"), bind (mem_fun(*this, &Editor::toggle_fade_active), true));
+       ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "set-fade-out-length", _("Set Fade Out Length"), bind (mem_fun(*this, &Editor::set_fade_length), false));
        ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "toggle-fade-out-active", _("Toggle Fade Out Active"), bind (mem_fun(*this, &Editor::toggle_fade_active), false));
+       ActionManager::session_sensitive_actions.push_back (act);
 
        act = ActionManager::register_action (editor_actions, "align-regions-start", _("Align Regions Start"), bind (mem_fun(*this, &Editor::align), ARDOUR::Start));
        ActionManager::session_sensitive_actions.push_back (act);
@@ -229,15 +297,19 @@ Editor::register_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "align-regions-sync-relative", _("Align Regions Sync Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint));
        ActionManager::session_sensitive_actions.push_back (act);
-       
-        act = ActionManager::register_action (editor_actions, "audition-at-mouse", _("Audition at Mouse"), mem_fun(*this, &Editor::kbd_audition));
+
+        act = ActionManager::register_action (editor_actions, "play-from-edit-point", _("Play From Edit Point"), mem_fun(*this, &Editor::play_from_edit_point));
+        ActionManager::session_sensitive_actions.push_back (act);
+        act = ActionManager::register_action (editor_actions, "play-from-edit-point-and-return", _("Play from Edit Point & Return"), mem_fun(*this, &Editor::play_from_edit_point_and_return));
+        ActionManager::session_sensitive_actions.push_back (act);
+
+        act = ActionManager::register_action (editor_actions, "play-edit-range", _("Play Edit Range"), mem_fun(*this, &Editor::play_edit_range));
+        act = ActionManager::register_action (editor_actions, "play-selected-regions", _("Play Selected Region(s)"), mem_fun(*this, &Editor::play_selected_region));
         ActionManager::session_sensitive_actions.push_back (act);
         act = ActionManager::register_action (editor_actions, "brush-at-mouse", _("Brush at Mouse"), mem_fun(*this, &Editor::kbd_brush));
         ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "mute-unmute-region", _("Mute/Unmute Region"), mem_fun(*this, &Editor::kbd_mute_unmute_region));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "set-region-sync-position", _("Set Region Sync Position"), mem_fun(*this, &Editor::kbd_set_sync_position));
-        ActionManager::session_sensitive_actions.push_back (act);
 
        act = ActionManager::register_action (editor_actions, "set-playhead", _("Set Playhead"), mem_fun(*this, &Editor::set_playhead_cursor));
        ActionManager::session_sensitive_actions.push_back (act);
@@ -245,6 +317,8 @@ Editor::register_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "split-region", _("Split Region"), mem_fun(*this, &Editor::split));
         ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "set-region-sync-position", _("Set Region Sync Position"), mem_fun(*this, &Editor::set_region_sync_from_edit_point));
+        ActionManager::session_sensitive_actions.push_back (act);
 
        undo_action = act = ActionManager::register_action (editor_actions, "undo", _("Undo"), bind (mem_fun(*this, &Editor::undo), 1U));
        ActionManager::session_sensitive_actions.push_back (act);
@@ -256,6 +330,10 @@ Editor::register_actions ()
        act = ActionManager::register_action (editor_actions, "export-range", _("Export Range"), mem_fun(*this, &Editor::export_selection));
        ActionManager::session_sensitive_actions.push_back (act);
 
+       act = ActionManager::register_action (editor_actions, "editor-separate", _("Separate"), mem_fun(*this, &Editor::separate_region_from_selection));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "editor-crop", _("Crop"), mem_fun(*this, &Editor::crop_region_to_selection));
+       ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "editor-cut", _("Cut"), mem_fun(*this, &Editor::cut));
        ActionManager::session_sensitive_actions.push_back (act);
        /* Note: for now, editor-delete does the exact same thing as editor-cut */
@@ -265,9 +343,11 @@ Editor::register_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "editor-paste", _("Paste"), mem_fun(*this, &Editor::keyboard_paste));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "duplicate-region", _("Duplicate Region"), mem_fun(*this, &Editor::keyboard_duplicate_region));
+       act = ActionManager::register_action (editor_actions, "duplicate-region", _("Duplicate Region"), bind (mem_fun(*this, &Editor::duplicate_dialog), false));
+       ActionManager::session_sensitive_actions.push_back (act);
+       act = ActionManager::register_action (editor_actions, "multi-duplicate-region", _("Multi-Duplicate Region"), bind (mem_fun(*this, &Editor::duplicate_dialog), true));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "duplicate-range", _("Duplicate Range"), mem_fun(*this, &Editor::keyboard_duplicate_selection));
+       act = ActionManager::register_action (editor_actions, "duplicate-range", _("Duplicate Range"), bind (mem_fun(*this, &Editor::duplicate_dialog), false));
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (editor_actions, "insert-region", _("Insert Region"), mem_fun(*this, &Editor::keyboard_insert_region_list_selection));
        ActionManager::session_sensitive_actions.push_back (act);
@@ -333,17 +413,27 @@ Editor::register_actions ()
        ActionManager::register_radio_action (editor_actions, edit_point_group, X_("edit-at-mouse"), _("Mouse"), (bind (mem_fun(*this, &Editor::edit_point_chosen), Editing::EditAtPlayhead)));
        ActionManager::register_radio_action (editor_actions, edit_point_group, X_("edit-at-selected-marker"), _("Marker"), (bind (mem_fun(*this, &Editor::edit_point_chosen), Editing::EditAtPlayhead)));
 
+       ActionManager::register_action (editor_actions, "cycle-edit-point", _("Change edit point"), bind (mem_fun (*this, &Editor::cycle_edit_point), false));
+       ActionManager::register_action (editor_actions, "cycle-edit-point-with-marker", _("Change edit point (w/Marker)"), bind (mem_fun (*this, &Editor::cycle_edit_point), true));
+
+       ActionManager::register_action (editor_actions, "set-edit-splice", _("Splice"), bind (mem_fun (*this, &Editor::set_edit_mode), Splice));
+       ActionManager::register_action (editor_actions, "set-edit-slide", _("Slide"), bind (mem_fun (*this, &Editor::set_edit_mode), Slide));
+       ActionManager::register_action (editor_actions, "toggle-edit-mode", _("Toggle Edit Mode"), mem_fun (*this, &Editor::cycle_edit_mode));
+
        ActionManager::register_action (editor_actions, X_("SnapTo"), _("Snap To"));
        ActionManager::register_action (editor_actions, X_("SnapMode"), _("Snap Mode"));
 
        RadioAction::Group snap_mode_group;
-       ActionManager::register_radio_action (editor_actions, snap_mode_group, X_("snap-normal"), _("Normal"), (bind (mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapNormal)));
+       ActionManager::register_radio_action (editor_actions, snap_mode_group, X_("snap-off"), _("No Grid"), (bind (mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapOff)));
+       ActionManager::register_radio_action (editor_actions, snap_mode_group, X_("snap-normal"), _("Grid"), (bind (mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapNormal)));
        ActionManager::register_radio_action (editor_actions, snap_mode_group, X_("snap-magnetic"), _("Magnetic"), (bind (mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapMagnetic)));
 
+       ActionManager::register_action (editor_actions, X_("cycle-snap-mode"), _("Next Snap Mode"), mem_fun (*this, &Editor::cycle_snap_mode));
+       ActionManager::register_action (editor_actions, X_("cycle-snap-choice"), _("Next Snap Choice"), mem_fun (*this, &Editor::cycle_snap_choice));
+
        Glib::RefPtr<ActionGroup> snap_actions = ActionGroup::create (X_("Snap"));
        RadioAction::Group snap_choice_group;
 
-       ActionManager::register_radio_action (snap_actions, snap_choice_group, X_("snap-to-frame"), _("Snap to frame"), (bind (mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToFrame)));
        ActionManager::register_radio_action (snap_actions, snap_choice_group, X_("snap-to-cd-frame"), _("Snap to cd frame"), (bind (mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToCDFrame)));
        ActionManager::register_radio_action (snap_actions, snap_choice_group, X_("snap-to-smpte-frame"), _("Snap to SMPTE frame"), (bind (mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToSMPTEFrame)));
        ActionManager::register_radio_action (snap_actions, snap_choice_group, X_("snap-to-smpte-seconds"), _("Snap to SMPTE seconds"), (bind (mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToSMPTESeconds)));
@@ -358,7 +448,6 @@ Editor::register_actions ()
        ActionManager::register_radio_action (snap_actions, snap_choice_group, X_("snap-to-beat"), _("Snap to beat"), (bind (mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeat)));
        ActionManager::register_radio_action (snap_actions, snap_choice_group, X_("snap-to-bar"), _("Snap to bar"), (bind (mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBar)));
        ActionManager::register_radio_action (snap_actions, snap_choice_group, X_("snap-to-mark"), _("Snap to mark"), (bind (mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToMark)));
-       ActionManager::register_radio_action (snap_actions, snap_choice_group, X_("snap-to-edit-cursor"), _("Snap to edit point"), (bind (mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToEditPoint)));
        ActionManager::register_radio_action (snap_actions, snap_choice_group, X_("snap-to-region-start"), _("Snap to region start"), (bind (mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToRegionStart)));
        ActionManager::register_radio_action (snap_actions, snap_choice_group, X_("snap-to-region-end"), _("Snap to region end"), (bind (mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToRegionEnd)));
        ActionManager::register_radio_action (snap_actions, snap_choice_group, X_("snap-to-region-sync"), _("Snap to region sync"), (bind (mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToRegionSync)));
@@ -567,6 +656,7 @@ Editor::update_crossfade_model ()
        }
 }
 
+
 void
 Editor::update_smpte_mode ()
 {
@@ -721,9 +811,6 @@ Editor::snap_type_action (SnapType type)
        RefPtr<Action> act;
        
        switch (type) {
-       case Editing::SnapToFrame:
-               action = "snap-to-frame";
-               break;
        case Editing::SnapToCDFrame:
                action = "snap-to-cd-frame";
                break;
@@ -766,9 +853,6 @@ Editor::snap_type_action (SnapType type)
        case Editing::SnapToMark:
                action = "snap-to-mark";
                break;
-       case Editing::SnapToEditPoint:
-               action = "snap-to-edit-cursor";
-               break;
        case Editing::SnapToRegionStart:
                action = "snap-to-region-start";
                break;
@@ -798,6 +882,67 @@ Editor::snap_type_action (SnapType type)
        }
 }
 
+void
+Editor::cycle_snap_choice()
+{
+       switch (snap_type) {
+       case Editing::SnapToCDFrame:
+               set_snap_to (Editing::SnapToSMPTEFrame);
+               break;
+       case Editing::SnapToSMPTEFrame:
+               set_snap_to (Editing::SnapToSMPTESeconds);
+               break;
+       case Editing::SnapToSMPTESeconds:
+               set_snap_to (Editing::SnapToSMPTEMinutes);
+               break;
+       case Editing::SnapToSMPTEMinutes:
+               set_snap_to (Editing::SnapToSeconds);
+               break;
+       case Editing::SnapToSeconds:
+               set_snap_to (Editing::SnapToMinutes);
+               break;
+       case Editing::SnapToMinutes:
+               set_snap_to (Editing::SnapToAThirtysecondBeat);
+               break;
+       case Editing::SnapToAThirtysecondBeat:
+               set_snap_to (Editing::SnapToASixteenthBeat);
+               break;
+       case Editing::SnapToASixteenthBeat:
+               set_snap_to (Editing::SnapToAEighthBeat);
+               break;
+       case Editing::SnapToAEighthBeat:
+               set_snap_to (Editing::SnapToAQuarterBeat);
+               break;
+       case Editing::SnapToAQuarterBeat:
+               set_snap_to (Editing::SnapToAThirdBeat);
+               break;
+       case Editing::SnapToAThirdBeat:
+               set_snap_to (Editing::SnapToBeat);
+               break;
+       case Editing::SnapToBeat:
+               set_snap_to (Editing::SnapToBar);
+               break;
+       case Editing::SnapToBar:
+               set_snap_to (Editing::SnapToMark);
+               break;
+       case Editing::SnapToMark:
+               set_snap_to (Editing::SnapToRegionStart);
+               break;
+       case Editing::SnapToRegionStart:
+               set_snap_to (Editing::SnapToRegionEnd);
+               break;
+       case Editing::SnapToRegionEnd:
+               set_snap_to (Editing::SnapToRegionSync);
+               break;
+       case Editing::SnapToRegionSync:
+               set_snap_to (Editing::SnapToRegionBoundary);
+               break;
+       case Editing::SnapToRegionBoundary:
+               set_snap_to (Editing::SnapToCDFrame);
+               break;
+       }
+}
+
 void
 Editor::snap_type_chosen (SnapType type)
 {
@@ -820,6 +965,9 @@ Editor::snap_mode_action (SnapMode mode)
        RefPtr<Action> act;
        
        switch (mode) {
+       case Editing::SnapOff:
+               action = X_("snap-off");
+               break;
        case Editing::SnapNormal:
                action = X_("snap-normal");
                break;
@@ -843,6 +991,22 @@ Editor::snap_mode_action (SnapMode mode)
        }
 }
 
+void
+Editor::cycle_snap_mode ()
+{
+       switch (snap_mode) {
+       case SnapOff:
+               set_snap_mode (SnapNormal);
+               break;
+       case SnapNormal:
+               set_snap_mode (SnapMagnetic);
+               break;
+       case SnapMagnetic:
+               set_snap_mode (SnapOff);
+               break;
+       }
+}
+
 void
 Editor::snap_mode_chosen (SnapMode mode)
 {
@@ -1171,6 +1335,12 @@ Editor::toggle_xfade_visibility ()
        ActionManager::toggle_config_state ("Editor", "toggle-xfades-visible", &Configuration::set_xfades_visible, &Configuration::get_xfades_visible);
 }
 
+void
+Editor::toggle_link_region_and_track_selection ()
+{
+       ActionManager::toggle_config_state ("Editor", "link-region-and-track-selection", &Configuration::set_link_region_and_track_selection, &Configuration::get_link_region_and_track_selection);
+}
+
 /** A Configuration parameter has changed.
  * @param parameter_name Name of the changed parameter.
  */
@@ -1178,7 +1348,7 @@ void
 Editor::parameter_changed (const char* parameter_name)
 {
 #define PARAM_IS(x) (!strcmp (parameter_name, (x)))
-
+       //cerr << "Editor::parameter_changed: " << parameter_name << endl;
        ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::parameter_changed), parameter_name));
 
        if (PARAM_IS ("auto-loop")) {
@@ -1210,7 +1380,9 @@ Editor::parameter_changed (const char* parameter_name)
                update_just_smpte ();
        } else if (PARAM_IS ("show-track-meters")) {
                toggle_meter_updating();
-       }
+       } else if (PARAM_IS ("link-region-and-track-selection")) {
+               ActionManager::map_some_state ("Editor", "link-region-and-track-selection", &Configuration::get_link_region_and_track_selection);
+       }
 
 #undef PARAM_IS
 }
index 43f63eed7901abfc2fa1cc96008d6233e0264308..cfb8f0a5572d4ec8445573f438ade641ae88f9f5 100644 (file)
 using namespace ARDOUR;
 using namespace PBD;
 
-void
-Editor::set_loop_from_selection (bool play)
-{
-       if (session == 0 || selection->time.empty()) {
-               return;
-       }
-
-       nframes_t start = selection->time[clicked_selection].start;
-       nframes_t end = selection->time[clicked_selection].end;
-       
-       set_loop_range (start, end,  _("set loop range from selection"));
-
-       if (play) {
-               session->request_play_loop (true);
-               session->request_locate (start, true);
-       }
-}
-
-void
-Editor::set_punch_from_selection ()
-{
-       if (session == 0 || selection->time.empty()) {
-               return;
-       }
-
-       nframes_t start = selection->time[clicked_selection].start;
-       nframes_t end = selection->time[clicked_selection].end;
-       
-       set_punch_range (start, end,  _("set punch range from selection"));
-}
-
 void
 Editor::set_show_waveforms (bool yn)
 {
index 40f6b05026822fa92621b6840dd2d941ca3b4111..87a92790bc916ca8612c4338e827c2f69b702018 100644 (file)
@@ -113,6 +113,9 @@ Editor::initialize_canvas ()
        track_canvas.signal_button_press_event().connect (mem_fun (*this, &Editor::track_canvas_button_press_event));
        track_canvas.signal_button_release_event().connect (mem_fun (*this, &Editor::track_canvas_button_release_event));
 
+       /* just scroll stuff for the timecanvas */
+       time_canvas.signal_scroll_event().connect (mem_fun (*this, &Editor::time_canvas_scroll_event));
+
        track_canvas.set_name ("EditorMainCanvas");
        track_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK|Gdk::SCROLL_MASK);
        track_canvas.signal_leave_notify_event().connect (mem_fun(*this, &Editor::left_track_canvas));
@@ -173,6 +176,7 @@ Editor::initialize_canvas ()
        range_marker_group = new ArdourCanvas::Group (*time_canvas.root(), 0.0, timebar_height * 2.0);
        transport_marker_group = new ArdourCanvas::Group (*time_canvas.root(), 0.0, timebar_height * 3.0);
        marker_group = new ArdourCanvas::Group (*time_canvas.root(), 0.0, timebar_height * 4.0);
+       cd_marker_group = new ArdourCanvas::Group (*time_canvas.root(), 0.0, timebar_height * 5.0);
        
        tempo_bar = new ArdourCanvas::SimpleRect (*tempo_group, 0.0, 0.0, max_canvas_coordinate, timebar_height-1.0);
        tempo_bar->property_outline_what() = (0x1 | 0x8);
@@ -185,6 +189,10 @@ Editor::initialize_canvas ()
        marker_bar = new ArdourCanvas::SimpleRect (*marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height-1.0);
        marker_bar->property_outline_what() = (0x1 | 0x8);
        marker_bar->property_outline_pixels() = 1;
+
+       cd_marker_bar = new ArdourCanvas::SimpleRect (*cd_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height-1.0);
+       cd_marker_bar->property_outline_what() = (0x1 | 0x8);
+       cd_marker_bar->property_outline_pixels() = 1;
        
        range_marker_bar = new ArdourCanvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height-1.0);
        range_marker_bar->property_outline_what() = (0x1 | 0x8);
@@ -252,6 +260,7 @@ Editor::initialize_canvas ()
        tempo_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_tempo_bar_event), tempo_bar));
        meter_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_meter_bar_event), meter_bar));
        marker_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_marker_bar_event), marker_bar));
+       cd_marker_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_cd_marker_bar_event), cd_marker_bar));
        range_marker_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_range_marker_bar_event), range_marker_bar));
        transport_marker_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_transport_marker_bar_event), transport_marker_bar));
        
@@ -291,7 +300,6 @@ Editor::track_canvas_allocate (Gtk::Allocation alloc)
        } 
 
        initial_ruler_update_required = false;
-       
        track_canvas_size_allocated ();
 }
 
@@ -327,8 +335,10 @@ Editor::track_canvas_size_allocated ()
        reset_scrolling_region ();
 
        if (playhead_cursor) playhead_cursor->set_length (canvas_height);
-
-       // EDIT CURSOR XXX set line height for selected markers here
+       
+       for (MarkerSelection::iterator x = selection->markers.begin(); x != selection->markers.end(); ++x) {
+               (*x)->set_line_length (canvas_height);
+       }
 
        if (range_marker_drag_rect) {
                range_marker_drag_rect->property_y1() = 0.0;
@@ -355,6 +365,7 @@ Editor::track_canvas_size_allocated ()
                transport_punchout_line->property_y2() = canvas_height;
        }
        compute_fixed_ruler_scale ();
+       
        update_fixed_rulers();
        redisplay_tempo (true);
 
@@ -382,12 +393,20 @@ Editor::reset_scrolling_region (Gtk::Allocation* alloc)
                }
        }
 
-       double last_canvas_unit =  last_canvas_frame / frames_per_unit;
+       double last_canvas_unit =  max ((last_canvas_frame / frames_per_unit), canvas_width);
 
-       track_canvas.set_scroll_region (0.0, 0.0, max (last_canvas_unit, canvas_width), pos);
+       track_canvas.set_scroll_region (0.0, 0.0, last_canvas_unit, pos);
 
        // XXX what is the correct height value for the time canvas ? this overstates it
-       time_canvas.set_scroll_region ( 0.0, 0.0, max (last_canvas_unit, canvas_width), canvas_height);
+       time_canvas.set_scroll_region ( 0.0, 0.0, last_canvas_unit, canvas_height);
+
+       range_marker_drag_rect->property_y2() = canvas_height;
+       transport_loop_range_rect->property_y2() = canvas_height;
+       transport_punch_range_rect->property_y2() = canvas_height;
+       transport_punchin_line->property_y2() = canvas_height;
+       transport_punchout_line->property_y2() = canvas_height;
+
+       update_punch_range_view (true);
 
        controls_layout.queue_resize();
 }
@@ -399,8 +418,8 @@ Editor::controls_layout_size_request (Requisition* req)
        TreeModel::Children::iterator i;
        double pos;
 
-        for (pos = 0, i = rows.begin(); i != rows.end(); ++i) {
-               TimeAxisView *tv = (*i)[route_display_columns.tv];
+       for (pos = 0, i = rows.begin(); i != rows.end(); ++i) {
+               TimeAxisView *tv = (*i)[route_display_columns.tv];
                if (tv != 0) {
                        pos += tv->effective_height;
                }
@@ -412,12 +431,9 @@ Editor::controls_layout_size_request (Requisition* req)
                screen = Gdk::Screen::get_default();
        }
 
-       /* never let the width of the controls area shrink horizontally */
-
        edit_controls_vbox.check_resize();
-
        req->width = max (edit_controls_vbox.get_width(),  controls_layout.get_width());
-       
+
        /* don't get too big. the fudge factors here are just guesses */
        
        req->width = min (req->width, screen->get_width() - 300);
@@ -426,8 +442,13 @@ Editor::controls_layout_size_request (Requisition* req)
        /* this one is important: it determines how big the layout thinks it really is, as 
           opposed to what it displays on the screen
        */
+       
+       controls_layout.set_size (edit_controls_vbox.get_width(), (gint) pos);
+       controls_layout.set_size_request(edit_controls_vbox.get_width(), -1);
+       zoom_box.set_size_request(edit_controls_vbox.get_width(), -1);
+       time_button_frame.set_size_request(edit_controls_vbox.get_width() + edit_vscrollbar.get_width(), -1);
 
-       controls_layout.set_size (req->width, (gint) pos);
+       //cerr << "sizes = " << req->width << " " << edit_controls_vbox.get_width() << " " << controls_layout.get_width() << " " << zoom_box.get_width() << " " << time_button_frame.get_width() << endl;//DEBUG        
 }
 
 bool
@@ -700,17 +721,19 @@ Editor::left_track_canvas (GdkEventCrossing *ev)
 void 
 Editor::canvas_horizontally_scrolled ()
 {
-       cerr << "chs\n";
+       nframes64_t time_origin = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
 
-       /* this is the core function that controls horizontal scrolling of the canvas. it is called
-          whenever the horizontal_adjustment emits its "value_changed" signal. it typically executes in an
-          idle handler, which is important because tempo_map_changed() should issue redraws immediately
-          and not defer them to an idle handler.
-       */
+       if (time_origin != leftmost_frame) {
+               canvas_scroll_to (time_origin);
+       }
+}
 
-       leftmost_frame = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
+void
+Editor::canvas_scroll_to (nframes64_t time_origin)
+{
+       leftmost_frame = time_origin;
        nframes_t rightmost_frame = leftmost_frame + current_page_frames ();
-       
+
        if (rightmost_frame > last_canvas_frame) {
                last_canvas_frame = rightmost_frame;
                reset_scrolling_region ();
@@ -740,6 +763,9 @@ Editor::color_handler()
        marker_bar->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerBar.get();
        marker_bar->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerBarSeparator.get();
 
+       cd_marker_bar->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_CDMarkerBar.get();
+       cd_marker_bar->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerBarSeparator.get();
+
        range_marker_bar->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_RangeMarkerBar.get();
        range_marker_bar->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerBarSeparator.get();
 
index ef11f546ef252e19e736f5030b87e5e6540eaea9..ec43d1bac0cf9f934bb5ce5c82d89c63c0421a55 100644 (file)
@@ -52,10 +52,13 @@ Editor::track_canvas_scroll (GdkEventScroll* ev)
 {
        int x, y;
        double wx, wy;
+       nframes_t xdelta;
+       int direction = ev->direction;
 
-       switch (ev->direction) {
+  retry:
+       switch (direction) {
        case GDK_SCROLL_UP:
-               if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+               if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
                        //if (ev->state == GDK_CONTROL_MASK) {
                        /* XXX 
                           the ev->x will be out of step with the canvas
@@ -75,7 +78,10 @@ Editor::track_canvas_scroll (GdkEventScroll* ev)
                        nframes_t where = event_frame (&event, 0, 0);
                        temporal_zoom_to_frame (false, where);
                        return true;
-               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
+                       direction = GDK_SCROLL_LEFT;
+                       goto retry;
+               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
                        if (!current_stepping_trackview) {
                                step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
                                if (!(current_stepping_trackview = trackview_by_y_position (ev->y))) {
@@ -90,8 +96,9 @@ Editor::track_canvas_scroll (GdkEventScroll* ev)
                        return true;
                }
                break;
+
        case GDK_SCROLL_DOWN:
-               if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+               if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
                        //if (ev->state == GDK_CONTROL_MASK) {
                        track_canvas.get_pointer (x, y);
                        track_canvas.window_to_world (x, y, wx, wy);
@@ -106,7 +113,10 @@ Editor::track_canvas_scroll (GdkEventScroll* ev)
                        nframes_t where = event_frame (&event, 0, 0);
                        temporal_zoom_to_frame (true, where);
                        return true;
-               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
+                       direction = GDK_SCROLL_RIGHT;
+                       goto retry;
+               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
                        if (!current_stepping_trackview) {
                                step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
                                if (!(current_stepping_trackview = trackview_by_y_position (ev->y))) {
@@ -122,8 +132,26 @@ Editor::track_canvas_scroll (GdkEventScroll* ev)
                }
                break;  
 
+       case GDK_SCROLL_LEFT:
+               xdelta = (current_page_frames() / 2);
+               if (leftmost_frame > xdelta) {
+                       reset_x_origin (leftmost_frame - xdelta);
+               } else {
+                       reset_x_origin (0);
+               }
+               break;
+
+       case GDK_SCROLL_RIGHT:
+               xdelta = (current_page_frames() / 2);
+               if (max_frames - xdelta > leftmost_frame) {
+                       reset_x_origin (leftmost_frame + xdelta);
+               } else {
+                       reset_x_origin (max_frames - current_page_frames());
+               }
+               break;
+
        default:
-               /* no left/right handling yet */
+               /* what? */
                break;
        }
        
@@ -138,9 +166,59 @@ Editor::track_canvas_scroll_event (GdkEventScroll *event)
        return false;
 }
 
+bool
+Editor::time_canvas_scroll (GdkEventScroll* ev)
+{
+       nframes_t xdelta;
+       int direction = ev->direction;
+
+       switch (direction) {
+       case GDK_SCROLL_UP:
+               temporal_zoom_step (true);
+               break;
+
+       case GDK_SCROLL_DOWN:
+               temporal_zoom_step (false);
+               break;  
+
+       case GDK_SCROLL_LEFT:
+               xdelta = (current_page_frames() / 2);
+               if (leftmost_frame > xdelta) {
+                       reset_x_origin (leftmost_frame - xdelta);
+               } else {
+                       reset_x_origin (0);
+               }
+               break;
+
+       case GDK_SCROLL_RIGHT:
+               xdelta = (current_page_frames() / 2);
+               if (max_frames - xdelta > leftmost_frame) {
+                       reset_x_origin (leftmost_frame + xdelta);
+               } else {
+                       reset_x_origin (max_frames - current_page_frames());
+               }
+               break;
+
+       default:
+               /* what? */
+               break;
+       }
+
+       return false;
+}
+
+bool
+Editor::time_canvas_scroll_event (GdkEventScroll *event)
+{
+       time_canvas.grab_focus();
+       time_canvas_scroll (event);
+       return false;
+}
+
 bool
 Editor::track_canvas_button_press_event (GdkEventButton *event)
 {
+       selection->clear ();
        track_canvas.grab_focus();
        return false;
 }
@@ -170,6 +248,11 @@ Editor::track_canvas_motion (GdkEvent *ev)
                verbose_canvas_cursor->property_x() = ev->motion.x + 20;
                verbose_canvas_cursor->property_y() = ev->motion.y + 20;
        }
+
+#ifdef GTKOSX
+       flush_canvas ();
+#endif
+
        return false;
 }
 
@@ -235,10 +318,12 @@ Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, Reg
                break;
 
        case GDK_ENTER_NOTIFY:
+               set_entered_track (&rv->get_time_axis_view ());
                set_entered_regionview (rv);
                break;
 
        case GDK_LEAVE_NOTIFY:
+               set_entered_track (0);
                set_entered_regionview (0);
                break;
 
@@ -274,6 +359,11 @@ Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, Rou
                break;
 
        case GDK_ENTER_NOTIFY:
+               set_entered_track (tv);
+               break;
+
+       case GDK_LEAVE_NOTIFY:
+               set_entered_track (0);
                break;
 
        default:
@@ -283,8 +373,6 @@ Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, Rou
        return ret;
 }
 
-
-
 bool
 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
 {
@@ -805,6 +893,12 @@ Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item*
        return typed_event (item, event, TransportMarkerBarItem);
 }
 
+bool
+Editor::canvas_cd_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
+{
+       return typed_event (item, event, CdMarkerBarItem);
+}
+
 bool
 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
 {
index 3ab2012588bda379404397049ef450319e14c787..157494b84617c1e9c23bad18bf90b1c5653b1b6d 100644 (file)
@@ -103,7 +103,7 @@ Editor::export_region ()
        ExportDialog* dialog = new ExportRegionDialog (*this, r);
                
        dialog->connect_to_session (session);
-       dialog->set_range (r->first_frame(), r->last_frame());
+       dialog->set_range (clicked_regionview->region()->first_frame(), clicked_regionview->region()->last_frame());
        dialog->start_export();
 }
 
index aa68f37720769af3ff4a09361271c956d353ab4d..042fd20852fcd287c1659d79b5e6a299412e275a 100644 (file)
@@ -27,6 +27,7 @@ enum ItemType {
        MarkerItem,
        MarkerBarItem,
        RangeMarkerBarItem,
+       CdMarkerBarItem,
        TransportMarkerBarItem,
        SelectionItem,
        ControlPointItem,
index 2912e2f4eeaf4de046737f3f4d78616e776ce801..4a5d55d879427bbc4871fc732bd44d8fdc554582 100644 (file)
@@ -90,29 +90,6 @@ Editor::kbd_mute_unmute_region ()
        }
 }
 
-void
-Editor::kbd_set_sync_position ()
-{
-       kbd_driver (mem_fun(*this, &Editor::kbd_do_set_sync_position), true, true, false);
-}
-
-void
-Editor::kbd_do_set_sync_position (GdkEvent* ev)
-{
-       if (entered_regionview) {
-               nframes64_t where = event_frame (ev);
-               snap_to (where);
-
-               set_a_regions_sync_position (entered_regionview->region(), where);
-
-       } else if (entered_marker) {
-
-               if (!selection->regions.empty()) {
-                       set_a_regions_sync_position (selection->regions.front()->region(), entered_marker->position());
-               }
-       }
-}
-
 void
 Editor::kbd_do_brush (GdkEvent *ev)
 {
@@ -125,14 +102,3 @@ Editor::kbd_brush ()
        kbd_driver (mem_fun(*this, &Editor::kbd_do_brush), true, true, false);
 }
 
-void
-Editor::kbd_do_audition (GdkEvent *ignored)
-{
-       audition_selected_region ();
-}
-
-void
-Editor::kbd_audition ()
-{
-       kbd_driver (mem_fun(*this, &Editor::kbd_do_audition), true, false, true);
-}
index d06b9f85aad8c0e62546fc9e67878af69d352d39..efbe0cb522be71fa182e336d477bed3b2eb4b4ed 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <ardour/session.h>
 #include <ardour/region.h>
+#include <gtkmm/treeview.h>
 
 #include "ardour_ui.h"
 #include "editor.h"
@@ -41,8 +42,6 @@ using namespace sigc;
 void
 Editor::keyboard_selection_finish (bool add)
 {
-       cerr << "here\n";
-
        if (session && have_pending_keyboard_selection) {
 
                nframes64_t end;
@@ -86,60 +85,17 @@ Editor::keyboard_selection_begin ()
        }
 }
 
-void
-Editor::keyboard_duplicate_region ()
-{
-       if (selection->regions.empty()) {
-               return;
-       }
-
-       float prefix = 0;
-       bool was_floating;
-
-       if (get_prefix (prefix, was_floating) == 0) {
-               duplicate_some_regions (selection->regions, prefix);
-       } else {
-               duplicate_some_regions (selection->regions, 1);
-       }
-}
-
-void
-Editor::keyboard_duplicate_selection ()
-{
-       float prefix = 0;
-       bool was_floating;
-
-       if (get_prefix (prefix, was_floating) == 0) {
-               duplicate_selection (prefix);
-       } else {
-               duplicate_selection (1);
-       }
-}
-
 void
 Editor::keyboard_paste ()
 {
-       float prefix = 0;
-       bool was_floating;
-
-       if (get_prefix (prefix, was_floating) == 0) {
-               paste (prefix);
-       } else {
-               paste (1);
-       }
+       ensure_entered_track_selected (true);
+       paste (1);
 }
 
 void
 Editor::keyboard_insert_region_list_selection ()
 {
-       float prefix = 0;
-       bool was_floating;
-
-       if (get_prefix (prefix, was_floating) == 0) {
-               insert_region_list_selection (prefix);
-       } else {
-               insert_region_list_selection (1);
-       }
+       insert_region_list_selection (1);
 }
 
 int
index 75776a7844c02513a1da1f9b353a63e326d70a82..68ce914025356e007dbb07eadf091ec4d8a06049 100644 (file)
@@ -26,6 +26,7 @@
 #include <gtkmm2ext/window_title.h>
 
 #include <ardour/location.h>
+#include <ardour/profile.h>
 #include <pbd/memento_command.h>
 
 #include "editor.h"
@@ -77,9 +78,15 @@ Editor::add_new_location (Location *location)
        }
 
        if (location->is_mark()) {
-               lam->start = new Marker (*this, *marker_group, color, location->name(), Marker::Mark, location->start());
-               lam->end   = 0;
 
+               if (location->is_cd_marker() && ruler_shown[ruler_time_cd_marker]) {
+                       lam->start = new Marker (*this, *cd_marker_group, color, location->name(), Marker::Mark, location->start());
+               }
+               else {
+                       lam->start = new Marker (*this, *marker_group, color, location->name(), Marker::Mark, location->start());
+               }
+               lam->end   = 0;
+                       
        } else if (location->is_auto_loop()) {
                // transport marker
                lam->start = new Marker (*this, *transport_marker_group, color, 
@@ -95,12 +102,20 @@ Editor::add_new_location (Location *location)
                                         location->name(), Marker::PunchOut, location->end());
                
        } else {
-
                // range marker
-               lam->start = new Marker (*this, *range_marker_group, color, 
-                                        location->name(), Marker::Start, location->start());
-               lam->end   = new Marker (*this, *range_marker_group, color, 
-                                        location->name(), Marker::End, location->end());
+               if (location->is_cd_marker() && ruler_shown[ruler_time_cd_marker]) {
+                       lam->start = new Marker (*this, *cd_marker_group, color, 
+                                                location->name(), Marker::Start, location->start());
+                       lam->end   = new Marker (*this, *cd_marker_group, color, 
+                                                location->name(), Marker::End, location->end());
+               }
+               else {
+                       
+                       lam->start = new Marker (*this, *range_marker_group, color, 
+                                                location->name(), Marker::Start, location->start());
+                       lam->end   = new Marker (*this, *range_marker_group, color, 
+                                                location->name(), Marker::End, location->end());
+               }
        }
 
        if (location->is_hidden ()) {
@@ -121,6 +136,11 @@ Editor::add_new_location (Location *location)
        newpair.second = lam;
 
        location_markers.insert (newpair);
+
+       if (select_new_marker && location->is_mark()) {
+               selection->set (lam->start);
+               select_new_marker = false;
+       }
 }
 
 void
@@ -157,6 +177,9 @@ Editor::location_flags_changed (Location *location, void *src)
                return;
        }
 
+       // move cd markers to/from cd marker bar as appropriate
+       ensure_cd_marker_updated (lam, location);
+
        if (location->is_cd_marker()) {
                lam->set_color_rgba (location_cd_marker_color);
        } else if (location->is_mark()) {
@@ -176,6 +199,52 @@ Editor::location_flags_changed (Location *location, void *src)
        }
 }
 
+void Editor::update_cd_marker_display ()
+{
+       for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
+               LocationMarkers * lam = i->second;
+               Location * location = i->first;
+
+               ensure_cd_marker_updated (lam, location);
+       }
+}
+
+void Editor::ensure_cd_marker_updated (LocationMarkers * lam, Location * location)
+{
+       if (location->is_cd_marker()
+           && (ruler_shown[ruler_time_cd_marker] &&  lam->start->get_parent() != cd_marker_group))
+       {
+               //cerr << "reparenting non-cd marker so it can be relocated: " << location->name() << endl;
+               if (lam->start) {
+                       lam->start->reparent (*cd_marker_group);
+               }
+               if (lam->end) {
+                       lam->end->reparent (*cd_marker_group);
+               }
+       }
+       else if ( (!location->is_cd_marker() || !ruler_shown[ruler_time_cd_marker]) 
+                 && (lam->start->get_parent() == cd_marker_group))  
+       {
+               //cerr << "reparenting non-cd marker so it can be relocated: " << location->name() << endl;
+               if (location->is_mark()) {
+                       if (lam->start) {
+                               lam->start->reparent (*marker_group);
+                       }
+                       if (lam->end) {
+                               lam->end->reparent (*marker_group);
+                       }
+               }
+               else {
+                       if (lam->start) {
+                               lam->start->reparent (*range_marker_group);
+                       }
+                       if (lam->end) {
+                               lam->end->reparent (*range_marker_group);
+                       }
+               }
+       }
+}
+
 Editor::LocationMarkers::~LocationMarkers ()
 {
        if (start) {
@@ -319,12 +388,14 @@ Editor::LocationMarkers::set_color_rgba (uint32_t rgba)
 }
 
 void
-Editor::mouse_add_new_marker (nframes_t where)
+Editor::mouse_add_new_marker (nframes_t where, bool is_cd)
 {
        string markername;
+       int flags = (is_cd ? Location::IsCDMarker|Location::IsMark : Location::IsMark);
+       
        if (session) {
                session->locations()->next_available_name(markername,"mark");
-               Location *location = new Location (where, where, markername, Location::IsMark);
+               Location *location = new Location (where, where, markername, (Location::Flags) flags);
                session->begin_reversible_command (_("add marker"));
                 XMLNode &before = session->locations()->get_state();
                session->locations()->add (location, true);
@@ -353,6 +424,10 @@ Editor::remove_marker (ArdourCanvas::Item& item, GdkEvent* event)
                /*NOTREACHED*/
        }
 
+       if (entered_marker == marker) {
+               entered_marker = NULL;
+       }
+
        Location* loc = find_location_from_marker (marker, is_start);
 
        if (session && loc) {
@@ -535,19 +610,21 @@ Editor::build_range_marker_menu (bool loop_or_punch)
        MenuList& items = markerMenu->items();
        markerMenu->set_name ("ArdourContextMenu");
 
+       items.push_back (MenuElem (_("Play Range"), mem_fun(*this, &Editor::marker_menu_play_range)));
        items.push_back (MenuElem (_("Locate to Range Mark"), mem_fun(*this, &Editor::marker_menu_set_playhead)));
        items.push_back (MenuElem (_("Play from Range Mark"), mem_fun(*this, &Editor::marker_menu_play_from)));
        if (! loop_or_punch) {
-               items.push_back (MenuElem (_("Play Range"), mem_fun(*this, &Editor::marker_menu_play_range)));
                items.push_back (MenuElem (_("Loop Range"), mem_fun(*this, &Editor::marker_menu_loop_range)));
        }
        items.push_back (MenuElem (_("Set Range Mark from Playhead"), mem_fun(*this, &Editor::marker_menu_set_from_playhead)));
-       items.push_back (MenuElem (_("Set Range from Range Selection"), mem_fun(*this, &Editor::marker_menu_set_from_selection)));
+       if (!Profile->get_sae()) {
+               items.push_back (MenuElem (_("Set Range from Range Selection"), mem_fun(*this, &Editor::marker_menu_set_from_selection)));
+       }
 
        items.push_back (SeparatorElem());
 
-       items.push_back (MenuElem (_("Hide Range"), mem_fun(*this, &Editor::marker_menu_hide)));
        if (! loop_or_punch) {
+               items.push_back (MenuElem (_("Hide Range"), mem_fun(*this, &Editor::marker_menu_hide)));
                items.push_back (MenuElem (_("Rename Range"), mem_fun(*this, &Editor::marker_menu_rename)));
                items.push_back (MenuElem (_("Remove Range"), mem_fun(*this, &Editor::marker_menu_remove)));
        }
@@ -556,8 +633,9 @@ Editor::build_range_marker_menu (bool loop_or_punch)
 
        items.push_back (MenuElem (_("Separate Regions in Range"), mem_fun(*this, &Editor::marker_menu_separate_regions_using_location)));
        items.push_back (MenuElem (_("Select All in Range"), mem_fun(*this, &Editor::marker_menu_select_all_selectables_using_range)));
-       items.push_back (MenuElem (_("Select Range"), mem_fun(*this, &Editor::marker_menu_select_using_range)));
-
+       if (!Profile->get_sae()) {
+               items.push_back (MenuElem (_("Select Range"), mem_fun(*this, &Editor::marker_menu_select_using_range)));
+       }
 }
 
 void
@@ -736,13 +814,13 @@ Editor::marker_menu_set_from_playhead ()
        if ((l = find_location_from_marker (marker, is_start)) != 0) {
 
                if (l->is_mark()) {
-                       l->set_start (session->transport_frame ());
+                       l->set_start (session->audible_frame ());
                }
                else {
                        if (is_start) {
-                               l->set_start (session->transport_frame ());
+                               l->set_start (session->audible_frame ());
                        } else {
-                               l->set_end (session->transport_frame ());
+                               l->set_end (session->audible_frame ());
                        }
                }
        }
@@ -1027,9 +1105,15 @@ Editor::update_punch_range_view (bool visibility)
                double x1 = frame_to_pixel (tpl->start());
                double x2 = frame_to_pixel (tpl->end());
                
+               guint track_canvas_width,track_canvas_height;
+               track_canvas.get_size(track_canvas_width,track_canvas_height);
+               
                transport_punch_range_rect->property_x1() = x1;
                transport_punch_range_rect->property_x2() = x2;
                
+               transport_punch_range_rect->property_x1() = (Config->get_punch_in() ? x1 : 0);
+               transport_punch_range_rect->property_x2() = (Config->get_punch_out() ? x2 : track_canvas_width);
+               
                if (visibility) {
                        transport_punch_range_rect->show();
                }
@@ -1108,3 +1192,33 @@ Editor::selected_marker_moved (Location* loc)
 {
        edit_point_clock.set (loc->start());
 }
+
+struct SortLocationsByPosition { 
+    bool operator() (Location* a, Location* b) {
+           return a->start() < b->start();
+    }
+};
+
+void
+Editor::goto_nth_marker (int n)
+{
+       if (!session) {
+               return;
+       }
+       const Locations::LocationList& l (session->locations()->list());
+       Locations::LocationList ordered;
+       ordered = l;
+
+       SortLocationsByPosition cmp;
+       ordered.sort (cmp);
+       
+       for (Locations::LocationList::iterator i = ordered.begin(); n >= 0 && i != ordered.end(); ++i) {
+               if ((*i)->is_mark() && !(*i)->is_hidden() && !(*i)->is_start()) {
+                       if (n == 0) {
+                               session->request_locate ((*i)->start(), session->transport_rolling());
+                               break;
+                       }
+                       --n;
+               }
+       }
+}
index 7264df552d2c0ca4a39034f152cc2ebb26f7596e..0f432cc62857091bc7a162eb91545b216f66f4c6 100644 (file)
@@ -198,7 +198,7 @@ Editor::update_current_screen ()
 
                /* only update if the playhead is on screen or we are following it */
 
-               if (_follow_playhead) {
+               if (_follow_playhead && session->requested_return_frame() < 0) {
 
                        playhead_cursor->canvas_item.show();
 
@@ -316,7 +316,6 @@ Editor::session_going_away ()
        clicked_crossfadeview = 0;
        entered_regionview = 0;
        entered_track = 0;
-       latest_regionview = 0;
        last_update_frame = 0;
        drag_info.item = 0;
        last_canvas_frame = 0;
index 78fdf5d2b2dbab326ed9cb5f01cec9967649e0ab..35f410eb25590bcba6af10f67b4ff2fbd38be966 100644 (file)
@@ -271,7 +271,11 @@ Editor::set_mouse_mode (MouseMode m, bool force)
 
        case MouseObject:
                mouse_move_button.set_active (true);
-               current_canvas_cursor = grabber_cursor;
+               if (Profile->get_sae()) {
+                       current_canvas_cursor = timebar_cursor;
+               } else {
+                       current_canvas_cursor = grabber_cursor;
+               }
                break;
 
        case MouseGain:
@@ -445,8 +449,6 @@ Editor::set_midi_edit_cursor (MidiEditMode m)
 void
 Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
 {
-       bool commit = false;
-
        /* in object/audition/timefx mode, any button press sets
           the selection if the object can be selected. this is a
           bit of hack, because we want to avoid this if the
@@ -485,18 +487,18 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
        switch (item_type) {
        case RegionItem:
                if (mouse_mode != MouseRange) {
-                       commit = set_selected_regionview_from_click (press, op, true);
+                       set_selected_regionview_from_click (press, op, true);
                } else if (event->type == GDK_BUTTON_PRESS) {
-                       commit = set_selected_track_from_click (press, op, false);
+                       set_selected_track_as_side_effect ();
                }
                break;
                
        case RegionViewNameHighlight:
        case RegionViewName:
                if (mouse_mode != MouseRange) {
-                       commit = set_selected_regionview_from_click (press, op, true);
+                       set_selected_regionview_from_click (press, op, true);
                } else if (event->type == GDK_BUTTON_PRESS) {
-                       commit = set_selected_track_from_click (press, op, false);
+                       set_selected_track_as_side_effect ();
                }
                break;
 
@@ -506,43 +508,35 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
        case FadeOutHandleItem:
        case FadeOutItem:
                if (mouse_mode != MouseRange) {
-                       commit = set_selected_regionview_from_click (press, op, true);
+                       set_selected_regionview_from_click (press, op, true);
                } else if (event->type == GDK_BUTTON_PRESS) {
-                       commit = set_selected_track_from_click (press, op, false);
+                       set_selected_track_as_side_effect ();
                }
                break;
 
-       case CrossfadeViewItem:
-               commit = set_selected_track_from_click (press, op, false);
-               break;
-                       
        case ControlPointItem:
-               commit = set_selected_track_from_click (press, op, true);
+               set_selected_track_as_side_effect ();
                if (mouse_mode != MouseRange) {
-                       commit |= set_selected_control_point_from_click (op, false);
+                       set_selected_control_point_from_click (op, false);
                }
                break;
                
        case StreamItem:
                /* for context click or range selection, select track */
                if (event->button.button == 3) {
-                       commit = set_selected_track_from_click (press, op, true);
+                       set_selected_track_as_side_effect ();
                } else if (event->type == GDK_BUTTON_PRESS && mouse_mode == MouseRange) {
-                       commit = set_selected_track_from_click (press, op, false);
+                       set_selected_track_as_side_effect ();
                }
                break;
                    
        case AutomationTrackItem:
-               commit = set_selected_track_from_click (press, op, true);
+               set_selected_track_as_side_effect (true);
                break;
                
        default:
                break;
        }
-       
-//     if (commit) {
-//             commit_reversible_command ();
-//     }
 }
 
 bool
@@ -586,7 +580,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
                                return true;
 
                        case MarkerItem:
-                               if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask(Keyboard::Control|Keyboard::Shift))) {
+                               if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
                                        hide_marker (item, event);
                                } else {
                                        start_marker_grab (item, event);
@@ -594,7 +588,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
                                return true;
 
                        case TempoMarkerItem:
-                               if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
+                               if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
                                        start_tempo_marker_copy_grab (item, event);
                                } else {
                                        start_tempo_marker_grab (item, event);
@@ -602,7 +596,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
                                return true;
 
                        case MeterMarkerItem:
-                               if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
+                               if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
                                        start_meter_marker_copy_grab (item, event);
                                } else {
                                        start_meter_marker_grab (item, event);
@@ -620,6 +614,11 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
                                return true;
                                break;
 
+                       case CdMarkerBarItem:
+                               start_range_markerbar_op (item, event, CreateCDMarker); 
+                               return true;
+                               break;
+
                        case TransportMarkerBarItem:
                                start_range_markerbar_op (item, event, CreateTransportMarker); 
                                return true;
@@ -643,10 +642,10 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
 
                        case SelectionItem:
                                if (Keyboard::modifier_state_contains 
-                                   (event->button.state, Keyboard::ModifierMask(Keyboard::Alt))) {
+                                   (event->button.state, Keyboard::ModifierMask(Keyboard::SecondaryModifier))) {
                                        // contains and not equals because I can't use alt as a modifier alone.
                                        start_selection_grab (item, event);
-                               } else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) {
+                               } else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
                                        /* grab selection for moving */
                                        start_selection_op (item, event, SelectionMove);
                                } else {
@@ -663,7 +662,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
                        break;
                        
                case MouseObject:
-                       if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::Control|Keyboard::Alt)) &&
+                       if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) &&
                            event->type == GDK_BUTTON_PRESS) {
                                
                                start_rubberband_select (item, event);
@@ -680,7 +679,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
                                        return true;
 
                                case RegionItem:
-                                       if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
+                                       if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
                                                start_region_copy_grab (item, event);
                                        } else if (Keyboard::the_keyboard().key_is_down (GDK_b)) {
                                                start_region_brush_grab (item, event);
@@ -832,12 +831,12 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
                        if (event->type == GDK_BUTTON_PRESS) {
                                switch (item_type) {
                                case RegionItem:
-                                       if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
+                                       if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
                                                start_region_copy_grab (item, event);
                                        } else {
                                                start_region_grab (item, event);
                                        }
-                                       
+                                       return true;
                                        break;
                                case ControlPointItem:
                                        start_control_point_grab (item, event);
@@ -876,7 +875,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
                                        
                                
                case MouseZoom:
-                       if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) {
+                       if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
                                temporal_zoom_session();
                        } else {
                                temporal_zoom_to_frame (true, event_frame(event));
@@ -990,7 +989,8 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
 
                        case MarkerBarItem: 
                        case RangeMarkerBarItem: 
-                       case TransportMarkerBarItem: 
+                       case TransportMarkerBarItem:
+                       case CdMarkerBarItem:
                        case TempoBarItem:
                        case MeterBarItem:
                                popup_ruler_menu (pixel_to_frame(event->button.x), item_type);
@@ -1088,6 +1088,14 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        mouse_add_new_marker (where);
                        return true;
 
+               case CdMarkerBarItem:
+                       // if we get here then a dragged range wasn't done
+                       if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+                               snap_to (where, 0, true);
+                       }
+                       mouse_add_new_marker (where, true);
+                       return true;
+
                case TempoBarItem:
                        if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
                                snap_to (where);
@@ -1151,7 +1159,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                                /* no drag, just a click */
                                switch (item_type) {
                                case RegionItem:
-                                       audition_selected_region ();
+                                       play_selected_region ();
                                        break;
                                default:
                                        break;
@@ -1174,6 +1182,25 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
        case 2:
                switch (mouse_mode) {
                        
+               case MouseObject:
+                       switch (item_type) {
+                       case RegionItem:
+                               if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
+                                       raise_region ();
+                               } else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::TertiaryModifier|Keyboard::SecondaryModifier))) {
+                                       lower_region ();
+                               } else {
+                                       // Button2 click is unused
+                               }
+                               return true;
+                               
+                               break;
+                               
+                       default:
+                               break;
+                       }
+                       break;
+                       
                case MouseRange:
                        
                        // x_style_paste (where, 1.0);
@@ -1220,12 +1247,12 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                        set_verbose_canvas_cursor (cp->line().get_verbose_cursor_string (fraction), at_x, at_y);
                        show_verbose_canvas_cursor ();
 
-                       if (is_drawable()) {
-                               track_canvas.get_window()->set_cursor (*fader_cursor);
+                       if (is_drawable() && !_scrubbing) {
+                               track_canvas.get_window()->set_cursor (*fader_cursor);
                        }
                }
                break;
-               
+
        case GainLineItem:
                if (mouse_mode == MouseGain) {
                        ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
@@ -1317,6 +1344,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
        case MarkerBarItem:
        case RangeMarkerBarItem:
        case TransportMarkerBarItem:
+       case CdMarkerBarItem:
        case MeterBarItem:
        case TempoBarItem:
                if (is_drawable()) {
@@ -1442,6 +1470,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
 
        case RangeMarkerBarItem:
        case TransportMarkerBarItem:
+       case CdMarkerBarItem:
        case MeterBarItem:
        case TempoBarItem:
        case MarkerBarItem:
@@ -1508,19 +1537,21 @@ Editor::left_automation_track ()
 bool
 Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type, bool from_autoscroll)
 {
-       gint x, y;
+       if (event->motion.is_hint) {
+               gint x, y;
+               
+               /* We call this so that MOTION_NOTIFY events continue to be
+                  delivered to the canvas. We need to do this because we set
+                  Gdk::POINTER_MOTION_HINT_MASK on the canvas. This reduces
+                  the density of the events, at the expense of a round-trip
+                  to the server. Given that this will mostly occur on cases
+                  where DISPLAY = :0.0, and given the cost of what the motion
+                  event might do, its a good tradeoff.  
+               */
+               
+               track_canvas.get_pointer (x, y);
+       }
        
-       /* We call this so that MOTION_NOTIFY events continue to be
-          delivered to the canvas. We need to do this because we set
-          Gdk::POINTER_MOTION_HINT_MASK on the canvas. This reduces
-          the density of the events, at the expense of a round-trip
-          to the server. Given that this will mostly occur on cases
-          where DISPLAY = :0.0, and given the cost of what the motion
-          event might do, its a good tradeoff.  
-       */
-
-       track_canvas.get_pointer (x, y);
-
        if (current_stepping_trackview) {
                /* don't keep the persistent stepped trackview if the mouse moves */
                current_stepping_trackview = 0;
@@ -1727,7 +1758,7 @@ Editor::start_grab (GdkEvent* event, Gdk::Cursor *cursor)
        // if dragging with button2, the motion is x constrained, with Alt-button2 it is y constrained
 
        if (event->button.button == 2) {
-               if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Alt)) {
+               if (Keyboard::modifier_state_equals (event->button.state, Keyboard::SecondaryModifier)) {
                        drag_info.y_constrained = true;
                        drag_info.x_constrained = false;
                } else {
@@ -2102,7 +2133,7 @@ Editor::cursor_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
        }
        
        if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
-               if (cursor == playhead_cursor && snap_type != SnapToEditPoint) {
+               if (cursor == playhead_cursor) {
                        snap_to (adjusted_frame);
                }
        }
@@ -2255,7 +2286,7 @@ Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 
        f_delta = copy_location->end() - copy_location->start();
        
-       if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) {
+       if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
                move_both = true;
        }
 
@@ -2681,7 +2712,7 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent*
        double dx = drag_info.current_pointer_x - drag_info.last_pointer_x;
        double dy = drag_info.current_pointer_y - drag_info.last_pointer_y;
 
-       if (event->button.state & Keyboard::Alt) {
+       if (event->button.state & Keyboard::SecondaryModifier) {
                dx *= 0.1;
                dy *= 0.1;
        }
@@ -2728,7 +2759,7 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent*
 
        bool push;
 
-       if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
+       if (Keyboard::modifier_state_contains (event->button.state, Keyboard::PrimaryModifier)) {
                push = true;
        } else {
                push = false;
@@ -2750,7 +2781,7 @@ Editor::control_point_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent
 
                /* just a click */
                
-               if ((event->type == GDK_BUTTON_RELEASE) && (event->button.button == 1) && Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) {
+               if ((event->type == GDK_BUTTON_RELEASE) && (event->button.button == 1) && Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
                        reset_point_selection ();
                }
 
@@ -2831,7 +2862,7 @@ Editor::line_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 
        double dy = drag_info.current_pointer_y - drag_info.last_pointer_y;
 
-       if (event->button.state & Keyboard::Alt) {
+       if (event->button.state & Keyboard::SecondaryModifier) {
                dy *= 0.1;
        }
 
@@ -2861,7 +2892,7 @@ Editor::line_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 
        bool push;
 
-       if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
+       if (Keyboard::modifier_state_contains (event->button.state, Keyboard::PrimaryModifier)) {
                push = false;
        } else {
                push = true;
@@ -2890,8 +2921,14 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
        drag_info.copy = false;
        drag_info.item = item;
        drag_info.data = clicked_regionview;
-       drag_info.motion_callback = &Editor::region_drag_motion_callback;
-       drag_info.finished_callback = &Editor::region_drag_finished_callback;
+
+       if (Config->get_edit_mode() == Splice) {
+               drag_info.motion_callback = &Editor::region_drag_splice_motion_callback;
+               drag_info.finished_callback = &Editor::region_drag_splice_finished_callback;
+       } else {
+               drag_info.motion_callback = &Editor::region_drag_motion_callback;
+               drag_info.finished_callback = &Editor::region_drag_finished_callback;
+       }
 
        start_grab (event);
 
@@ -2961,7 +2998,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
 void
 Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event)
 {
-       if (selection->regions.empty() || clicked_regionview == 0) {
+       if (selection->regions.empty() || clicked_regionview == 0 || Config->get_edit_mode() == Splice) {
                return;
        }
 
@@ -2992,18 +3029,8 @@ Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event)
 }
 
 void
-Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
+Editor::possibly_copy_regions_during_grab (GdkEvent* event)
 {
-       double x_delta;
-       double y_delta = 0;
-       RegionView* rv = reinterpret_cast<RegionView*> (drag_info.data); 
-       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
-       bool clamp_y_axis = false;
-       vector<int32_t>  height_list(512) ;
-       vector<int32_t>::iterator j;
-
        if (drag_info.copy && drag_info.move_threshold_passed && drag_info.want_move_threshold) {
 
                drag_info.want_move_threshold = false; // don't copy again
@@ -3049,24 +3076,123 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 
                swap_grab (new_regionviews.front()->get_canvas_group (), 0, event->motion.time);
        }
+}
 
+bool
+Editor::check_region_drag_possible (RouteTimeAxisView** tv)
+{
        /* Which trackview is this ? */
 
        TimeAxisView* tvp = trackview_by_y_position (drag_info.current_pointer_y);
-       RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
+       (*tv) = dynamic_cast<RouteTimeAxisView*>(tvp);
 
        /* The region motion is only processed if the pointer is over
           an audio track.
        */
        
-       if (!tv || !tv->is_track()) {
+       if (!(*tv) || !(*tv)->is_track()) {
                /* To make sure we hide the verbose canvas cursor when the mouse is 
-                  not held over a track. 
+                  not held over and audiotrack. 
                */
                hide_verbose_canvas_cursor ();
-               return;
+               return false;
        }
        
+       return true;
+}
+
+struct RegionSelectionByPosition {
+    bool operator() (RegionView*a, RegionView* b) {
+           return a->region()->position () < b->region()->position();
+    }
+};
+
+void
+Editor::region_drag_splice_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
+{
+       RouteTimeAxisView* tv;
+       
+       if (!check_region_drag_possible (&tv)) {
+               return;
+       }
+
+       if (!drag_info.move_threshold_passed) {
+               return;
+       }
+
+       int dir;
+
+       if (drag_info.current_pointer_x - drag_info.grab_x > 0) {
+               dir = 1;
+       } else {
+               dir = -1;
+       }
+
+       RegionSelection copy (selection->regions);
+
+       RegionSelectionByPosition cmp;
+       copy.sort (cmp);
+
+       for (RegionSelection::iterator i = copy.begin(); i != copy.end(); ++i) {
+
+               RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*> (&(*i)->get_time_axis_view());
+
+               if (!atv) {
+                       continue;
+               }
+
+               boost::shared_ptr<Playlist> playlist;
+
+               if ((playlist = atv->playlist()) == 0) {
+                       continue;
+               }
+
+               if (!playlist->region_is_shuffle_constrained ((*i)->region())) {
+                       continue;
+               } 
+
+               if (dir > 0) {
+                       if (drag_info.current_pointer_frame < (*i)->region()->last_frame() + 1) {
+                               continue;
+                       }
+               } else {
+                       if (drag_info.current_pointer_frame > (*i)->region()->first_frame()) {
+                               continue;
+                       }
+               }
+
+               
+               playlist->shuffle ((*i)->region(), dir);
+
+               drag_info.grab_x = drag_info.current_pointer_x;
+       }
+}
+
+void
+Editor::region_drag_splice_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
+{
+}
+
+void
+Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
+{
+       double x_delta;
+       double y_delta = 0;
+       RegionView* rv = reinterpret_cast<RegionView*> (drag_info.data); 
+       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
+       bool clamp_y_axis = false;
+       vector<int32_t>  height_list(512) ;
+       vector<int32_t>::iterator j;
+       RouteTimeAxisView* tv;
+
+       possibly_copy_regions_during_grab (event);
+
+       if (!check_region_drag_possible (&tv)) {
+               return;
+       }
+
        original_pointer_order = drag_info.last_trackview->order;
                
        /************************************************************
@@ -3078,7 +3204,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                pointer_y_span = 0;
                goto y_axis_done;
        }
-       
+
        if ((pointer_y_span = (drag_info.last_trackview->order - tv->order)) != 0) {
 
                int32_t children = 0, numtracks = 0;
@@ -3253,7 +3379,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        }
            
                        if (sync_frame - sync_offset <= sync_frame) {
-                               pending_region_position = sync_frame - (sync_dir*sync_offset);
+                               pending_region_position = sync_frame + (sync_dir*sync_offset);
                        } else {
                                pending_region_position = 0;
                        }
@@ -3270,7 +3396,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
          
                if (pending_region_position != drag_info.last_frame_position && !drag_info.x_constrained) {
 
-                       /* now compute the canvas unit distance we need to move the regiondrag_info.last_trackview->order
+                       /* now compute the canvas unit distance we need to move the regionview
                           to make it appear at the new location.
                        */
 
@@ -3449,7 +3575,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 
                                rv->fake_set_opaque (true);
                        }
-                       
+
                        if (drag_info.brushing) {
                                mouse_brush_insert_region (rv, pending_region_position);
                        } else {
@@ -3503,6 +3629,11 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
        region_drag_motion_callback (item, event);
 
+       if (Config->get_edit_mode() == Splice && !pre_drag_region_selection.empty()) {
+               selection->set (pre_drag_region_selection);
+               pre_drag_region_selection.clear ();
+       }
+
        if (drag_info.brushing) {
                /* all changes were made during motion event handlers */
                
@@ -3551,6 +3682,8 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
                /* moved to a different audio track. */
                
+               vector<RegionView*> new_selection;
+               
                for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) {
                        
                        RegionView* rv = (*i);      
@@ -3624,9 +3757,17 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                                copies.push_back (rv);
                        }
 
-                       latest_regionview = 0;
+                       latest_regionviews.clear ();
+                       sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
+                       session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));        
 
                        to_playlist->add_region (new_region, where);
+                       session->add_command (new MementoCommand<Playlist>(*to_playlist, 0, &to_playlist->get_state()));        
+                       c.disconnect ();
+                                                             
+                       if (!latest_regionviews.empty()) {
+                               new_selection.insert (new_selection.end(), latest_regionviews.begin(), latest_regionviews.end());
+                       }
 
                        /* OK, this is where it gets tricky. If the playlist was being used by >1 tracks, and the region
                           was selected in all of them, then removing it from the playlist will have removed all
@@ -3723,12 +3864,16 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
                                /* add it */
 
-                               to_playlist->add_region (newregion, (nframes_t) (where * from_rtv->get_diskstream()->speed()));
-
-                               /* if the original region was locked, we don't care for the new one */
+                               latest_regionviews.clear ();
+                               sigc::connection c = rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
+                               to_playlist->add_region (newregion, (nframes_t) (where * rtv->get_diskstream()->speed()));
+                               c.disconnect ();
                                
-                               newregion->set_locked (false);
-                               copies.push_back (rv);
+                               if (!latest_regionviews.empty()) {
+                                       // XXX why just the first one ? we only expect one
+                                       rtv->reveal_dependent_views (*latest_regionviews.front());
+                                       selection->add (latest_regionviews);
+                               }
                                
                        } else {
 
@@ -3833,7 +3978,7 @@ Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event)
           this is an alignment click (control used)
        */
        
-       if (Keyboard::modifier_state_contains (event->state, Keyboard::Control)) {
+       if (Keyboard::modifier_state_contains (event->state, Keyboard::PrimaryModifier)) {
                TimeAxisView* tv = &rv.get_time_axis_view();
                RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(tv);
                double speed = 1.0;
@@ -3845,11 +3990,11 @@ Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event)
 
                if (where >= 0) {
 
-                       if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
+                       if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
                                
                                align_region (rv.region(), SyncPoint, (nframes_t) (where * speed));
                                
-                       } else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
+                       } else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
                                
                                align_region (rv.region(), End, (nframes_t) (where * speed));
                                
@@ -3988,14 +4133,14 @@ Editor::show_verbose_duration_cursor (nframes_t start, nframes_t end, double off
 void
 Editor::collect_new_region_view (RegionView* rv)
 {
-       latest_regionview = rv;
+       latest_regionviews.push_back (rv);
 }
 
 void
 Editor::collect_and_select_new_region_view (RegionView* rv)
 {
        selection->add(rv);
-       latest_regionview = rv;
+       latest_regionviews.push_back (rv);
 }
 
 void
@@ -4025,7 +4170,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
           set the regionview we want to then drag.
        */
        
-       latest_regionview = 0;
+       latest_regionviews.clear();
        sigc::connection c = clicked_routeview->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
        
        /* A selection grab currently creates two undo/redo operations, one for 
@@ -4045,24 +4190,25 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
        
        c.disconnect ();
        
-       if (latest_regionview == 0) {
+       if (latest_regionviews.empty()) {
                /* something went wrong */
                return;
        }
 
        /* we need to deselect all other regionviews, and select this one
-          i'm ignoring undo stuff, because the region creation will take care of it */
-       //selection->set (latest_regionview);
+          i'm ignoring undo stuff, because the region creation will take care of it 
+       */
+       selection->set (latest_regionviews);
        
-       drag_info.item = latest_regionview->get_canvas_group();
-       drag_info.data = latest_regionview;
+       drag_info.item = latest_regionviews.front()->get_canvas_group();
+       drag_info.data = latest_regionviews.front();
        drag_info.motion_callback = &Editor::region_drag_motion_callback;
        drag_info.finished_callback = &Editor::region_drag_finished_callback;
 
        start_grab (event);
        
        drag_info.last_trackview = clicked_axisview;
-       drag_info.last_frame_position = latest_regionview->region()->position();
+       drag_info.last_frame_position = latest_regionviews.front()->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);
@@ -4074,10 +4220,8 @@ Editor::cancel_selection ()
        for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
                (*i)->hide_selection ();
        }
-       begin_reversible_command (_("cancel selection"));
        selection->clear ();
        clicked_selection = 0;
-       commit_reversible_command ();
 }      
 
 void
@@ -4098,7 +4242,7 @@ Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, Selection
 
        switch (op) {
        case CreateSelection:
-               if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) {
+               if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
                        drag_info.copy = true;
                } else {
                        drag_info.copy = false;
@@ -4313,7 +4457,7 @@ Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event)
 
        start_grab (event, trimmer_cursor);
        
-       if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) {
+       if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
                trim_op = ContentsTrim;
        } else {
                /* These will get overridden for a point trim.*/
@@ -4441,7 +4585,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                {
                        bool swap_direction = false;
 
-                       if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) {
+                       if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
                                swap_direction = true;
                        }
                        
@@ -4582,7 +4726,7 @@ Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
        if (!drag_info.first_move) {
                trim_motion_callback (item, event);
                
-               if (!clicked_regionview->get_selected()) {
+               if (!selection->selected (clicked_regionview)) {
                        thaw_region_after_trim (*clicked_regionview);           
                } else {
                        
@@ -4624,7 +4768,7 @@ Editor::point_trim (GdkEvent* event)
                trim_op = StartTrim;
                begin_reversible_command (_("Start point trim"));
 
-               if (rv->get_selected()) {
+               if (selection->selected (rv)) {
 
                        for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin();
                             i != selection->regions.by_layer().end(); ++i)
@@ -4656,7 +4800,7 @@ Editor::point_trim (GdkEvent* event)
                trim_op = EndTrim;
                begin_reversible_command (_("End point trim"));
 
-               if (rv->get_selected()) {
+               if (selection->selected (rv)) {
                        
                        for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i)
                        {
@@ -4742,8 +4886,9 @@ Editor::start_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event, Ran
        switch (op) {
        case CreateRangeMarker:
        case CreateTransportMarker:
-               
-               if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) {
+       case CreateCDMarker:
+       
+               if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
                        drag_info.copy = true;
                } else {
                        drag_info.copy = false;
@@ -4776,6 +4921,7 @@ Editor::drag_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event)
        switch (range_marker_op) {
        case CreateRangeMarker:
        case CreateTransportMarker:
+       case CreateCDMarker:
                if (drag_info.first_move) {
                        snap_to (drag_info.grab_frame);
                }
@@ -4833,17 +4979,25 @@ Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event)
 {
        Location * newloc = 0;
        string rangename;
+       int flags;
        
        if (!drag_info.first_move) {
                drag_range_markerbar_op (item, event);
 
                switch (range_marker_op) {
                case CreateRangeMarker:
+               case CreateCDMarker:
                    {
                        begin_reversible_command (_("new range marker"));
                        XMLNode &before = session->locations()->get_state();
                        session->locations()->next_available_name(rangename,"unnamed");
-                       newloc = new Location(temp_location->start(), temp_location->end(), rangename, Location::IsRangeMarker);
+                       if (range_marker_op == CreateCDMarker) {
+                               flags =  Location::IsRangeMarker|Location::IsCDMarker;
+                       }
+                       else {
+                               flags =  Location::IsRangeMarker;
+                       }
+                       newloc = new Location(temp_location->start(), temp_location->end(), rangename, (Location::Flags) flags);
                        session->locations()->add (newloc, true);
                        XMLNode &after = session->locations()->get_state();
                        session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
@@ -4863,7 +5017,7 @@ Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event)
        } else {
                /* just a click, no pointer movement. remember that context menu stuff was handled elsewhere */
 
-               if (Keyboard::no_modifier_keys_pressed (&event->button)) {
+               if (Keyboard::no_modifier_keys_pressed (&event->button) && range_marker_op != CreateCDMarker) {
 
                        nframes_t start;
                        nframes_t end;
@@ -5179,11 +5333,20 @@ Editor::end_time_fx (ArdourCanvas::Item* item, GdkEvent* event)
        }
        
        nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region()->position();
+#ifdef USE_RUBBERBAND
+       float percentage = (float) ((double) newlen / (double) clicked_regionview->region()->length());
+#else
        float percentage = (float) ((double) newlen - (double) clicked_regionview->region()->length()) / ((double) newlen) * 100.0f;
-       
+#endif 
+
        begin_reversible_command (_("timestretch"));
 
-       if (run_timestretch (selection->regions, percentage) == 0) {
+       // XXX how do timeFX on multiple regions ?
+
+       RegionSelection rs;
+       rs.add (clicked_regionview);
+
+       if (time_stretch (rs, percentage) == 0) {
                session->commit_reversible_command ();
        }
 }
@@ -5205,9 +5368,7 @@ Editor::mouse_brush_insert_region (RegionView* rv, nframes_t pos)
        }
 
        switch (snap_type) {
-       case SnapToFrame:
        case SnapToMark:
-       case SnapToEditPoint:
                return;
 
        default:
index dd5f2b4599ef70826f53ca7039389e47a6307646..9cee32cebbb3de5e0812e588a7ccadf0ad484e94 100644 (file)
@@ -30,6 +30,7 @@
 #include <pbd/basename.h>
 #include <pbd/pthread_utils.h>
 #include <pbd/memento_command.h>
+#include <pbd/whitespace.h>
 
 #include <gtkmm2ext/utils.h>
 #include <gtkmm2ext/choice.h>
@@ -112,6 +113,10 @@ Editor::split_regions_at (nframes_t where, RegionSelection& regions)
 {
        list <boost::shared_ptr<Playlist > > used_playlists;
 
+       if (regions.empty()) {
+               return;
+       }
+
        begin_reversible_command (_("split"));
 
        // if splitting a single region, and snap-to is using
@@ -336,7 +341,7 @@ Editor::nudge_forward (bool next)
        
        if (!selection->regions.empty()) {
 
-               begin_reversible_command (_("nudge forward"));
+               begin_reversible_command (_("nudge regions forward"));
 
                for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
                        boost::shared_ptr<Region> r ((*i)->region());
@@ -355,6 +360,44 @@ Editor::nudge_forward (bool next)
 
                commit_reversible_command ();
 
+               
+       } else if (!selection->markers.empty()) {
+
+               bool is_start;
+               Location* loc = find_location_from_marker (selection->markers.front(), is_start);
+
+               if (loc) {
+
+                       begin_reversible_command (_("nudge location forward"));
+
+                       XMLNode& before (loc->get_state());
+
+                       if (is_start) {
+                               distance = get_nudge_distance (loc->start(), next_distance);
+                               if (next) {
+                                       distance = next_distance;
+                               }
+                               if (max_frames - distance > loc->start() + loc->length()) {
+                                       loc->set_start (loc->start() + distance);
+                               } else {
+                                       loc->set_start (max_frames - loc->length());
+                               }
+                       } else {
+                               distance = get_nudge_distance (loc->end(), next_distance);
+                               if (next) {
+                                       distance = next_distance;
+                               }
+                               if (max_frames - distance > loc->end()) {
+                                       loc->set_end (loc->end() + distance);
+                               } else {
+                                       loc->set_end (max_frames);
+                               }
+                       }
+                       XMLNode& after (loc->get_state());
+                       session->add_command (new MementoCommand<Location>(*loc, &before, &after));
+                       commit_reversible_command ();
+               }
+               
        } else {
                distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
                session->request_locate (playhead_cursor->current_frame + distance);
@@ -371,7 +414,7 @@ Editor::nudge_backward (bool next)
        
        if (!selection->regions.empty()) {
 
-               begin_reversible_command (_("nudge forward"));
+               begin_reversible_command (_("nudge regions backward"));
 
                for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
                        boost::shared_ptr<Region> r ((*i)->region());
@@ -395,6 +438,44 @@ Editor::nudge_backward (bool next)
 
                commit_reversible_command ();
 
+       } else if (!selection->markers.empty()) {
+
+               bool is_start;
+               Location* loc = find_location_from_marker (selection->markers.front(), is_start);
+
+               if (loc) {
+
+                       begin_reversible_command (_("nudge location forward"));
+                       XMLNode& before (loc->get_state());
+
+                       if (is_start) {
+                               distance = get_nudge_distance (loc->start(), next_distance);
+                               if (next) {
+                                       distance = next_distance;
+                               }
+                               if (distance < loc->start()) {
+                                       loc->set_start (loc->start() - distance);
+                               } else {
+                                       loc->set_start (0);
+                               }
+                       } else {
+                               distance = get_nudge_distance (loc->end(), next_distance);
+
+                               if (next) {
+                                       distance = next_distance;
+                               }
+
+                               if (distance < loc->end() - loc->length()) {
+                                       loc->set_end (loc->end() - distance);
+                               } else {
+                                       loc->set_end (loc->length());
+                               }
+                       }
+
+                       XMLNode& after (loc->get_state());
+                       session->add_command (new MementoCommand<Location>(*loc, &before, &after));
+               }
+               
        } else {
 
                distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
@@ -543,12 +624,15 @@ Editor::build_region_boundary_cache ()
                        case Start:
                                rpos = r->first_frame();
                                break;
+
                        case End:
                                rpos = r->last_frame();
                                break;  
+
                        case SyncPoint:
                                rpos = r->adjust_to_sync (r->first_frame());
                                break;
+
                        default:
                                break;
                        }
@@ -635,6 +719,7 @@ Editor::find_next_region (nframes_t frame, RegionPoint point, int32_t dir, Track
                        rpos = r->adjust_to_sync (r->first_frame());
                        break;
                }
+
                // rpos is a "track frame", converting it to "session frame"
                rpos = track_frame_to_session_frame(rpos, track_speed);
 
@@ -655,6 +740,85 @@ Editor::find_next_region (nframes_t frame, RegionPoint point, int32_t dir, Track
        return ret;
 }
 
+nframes64_t
+Editor::find_next_region_boundary (nframes64_t pos, int32_t dir, const TrackViewList& tracks)
+{
+       nframes64_t distance = max_frames;
+       nframes64_t current_nearest = -1;
+
+       for (TrackViewList::const_iterator i = tracks.begin(); i != tracks.end(); ++i) {
+               nframes64_t contender;
+               nframes64_t d;
+
+               RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
+
+               if (!rtv) {
+                       continue;
+               }
+
+               if ((contender = rtv->find_next_region_boundary (pos, dir)) < 0) {
+                       continue;
+               }
+
+               d = ::llabs (pos - contender);
+
+               if (d < distance) {
+                       current_nearest = contender;
+                       distance = d;
+               }
+       }
+       
+       return current_nearest;
+}
+
+void
+Editor::cursor_to_region_boundary (Cursor* cursor, int32_t dir)
+{
+       nframes64_t pos = cursor->current_frame;
+       nframes64_t target;
+
+       if (!session) {
+               return;
+       }
+
+       // so we don't find the current region again..
+       if (dir > 0 || pos > 0) {
+               pos += dir;
+       }
+
+       if (!selection->tracks.empty()) {
+               
+               target = find_next_region_boundary (pos, dir, selection->tracks);
+               
+       } else {
+               
+               target = find_next_region_boundary (pos, dir, track_views);
+       }
+       
+       if (target < 0) {
+               return;
+       }
+
+
+       if (cursor == playhead_cursor) {
+               session->request_locate (target);
+       } else {
+               cursor->set_position (target);
+       }
+}
+
+void
+Editor::cursor_to_next_region_boundary (Cursor* cursor)
+{
+       cursor_to_region_boundary (cursor, 1);
+}
+
+void
+Editor::cursor_to_previous_region_boundary (Cursor* cursor)
+{
+       cursor_to_region_boundary (cursor, -1);
+}
+
 void
 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
 {
@@ -793,7 +957,68 @@ Editor::cursor_to_selection_end (Cursor *cursor)
 }
 
 void
-Editor::edit_point_to_region_point (RegionPoint point, int32_t dir)
+Editor::selected_marker_to_region_boundary (int32_t dir)
+{
+       nframes64_t target;
+       Location* loc;
+       bool ignored;
+
+       if (!session) {
+               return;
+       }
+
+       if (selection->markers.empty()) {
+               nframes64_t mouse;
+               bool ignored;
+
+               if (!mouse_frame (mouse, ignored)) {
+                       return;
+               }
+               
+               add_location_mark (mouse);
+       }
+
+       if ((loc = find_location_from_marker (selection->markers.front(), ignored)) == 0) {
+               return;
+       }
+
+       nframes64_t pos = loc->start();
+
+       // so we don't find the current region again..
+       if (dir > 0 || pos > 0) {
+               pos += dir;
+       }
+
+       if (!selection->tracks.empty()) {
+               
+               target = find_next_region_boundary (pos, dir, selection->tracks);
+               
+       } else {
+               
+               target = find_next_region_boundary (pos, dir, track_views);
+       }
+       
+       if (target < 0) {
+               return;
+       }
+
+       loc->move_to (target);
+}
+
+void
+Editor::selected_marker_to_next_region_boundary ()
+{
+       selected_marker_to_region_boundary (1);
+}
+
+void
+Editor::selected_marker_to_previous_region_boundary ()
+{
+       selected_marker_to_region_boundary (-1);
+}
+
+void
+Editor::selected_marker_to_region_point (RegionPoint point, int32_t dir)
 {
        boost::shared_ptr<Region> r;
        nframes_t pos;
@@ -858,19 +1083,19 @@ Editor::edit_point_to_region_point (RegionPoint point, int32_t dir)
 }
 
 void
-Editor::edit_point_to_next_region_point (RegionPoint point)
+Editor::selected_marker_to_next_region_point (RegionPoint point)
 {
-       edit_point_to_region_point (point, 1);
+       selected_marker_to_region_point (point, 1);
 }
 
 void
-Editor::edit_point_to_previous_region_point (RegionPoint point)
+Editor::selected_marker_to_previous_region_point (RegionPoint point)
 {
-       edit_point_to_region_point (point, -1);
+       selected_marker_to_region_point (point, -1);
 }
 
 void
-Editor::edit_point_to_selection_start ()
+Editor::selected_marker_to_selection_start ()
 {
        nframes_t pos = 0;
        Location* loc;
@@ -905,7 +1130,7 @@ Editor::edit_point_to_selection_start ()
 }
 
 void
-Editor::edit_point_to_selection_end ()
+Editor::selected_marker_to_selection_end ()
 {
        nframes_t pos = 0;
        Location* loc;
@@ -1282,15 +1507,18 @@ Editor::temporal_zoom (gdouble fpu)
        nframes64_t current_leftmost = leftmost_frame;
        nframes64_t current_rightmost;
        nframes64_t current_center;
-       nframes64_t new_page;
+       nframes64_t new_page_size;
+       nframes64_t half_page_size;
        nframes64_t leftmost_after_zoom = 0;
        nframes64_t where;
        bool in_track_canvas;
        double nfpu;
+       double l;
 
        nfpu = fpu;
        
-       new_page = (nframes_t) floor (canvas_width * nfpu);
+       new_page_size = (nframes_t) floor (canvas_width * nfpu);
+       half_page_size = new_page_size / 2;
 
        switch (zoom_focus) {
        case ZoomFocusLeft:
@@ -1299,28 +1527,35 @@ Editor::temporal_zoom (gdouble fpu)
                
        case ZoomFocusRight:
                current_rightmost = leftmost_frame + current_page;
-               if (current_rightmost > new_page) {
-                       leftmost_after_zoom = current_rightmost - new_page;
-               } else {
+               if (current_rightmost < new_page_size) {
                        leftmost_after_zoom = 0;
+               } else {
+                       leftmost_after_zoom = current_rightmost - new_page_size;
                }
                break;
                
        case ZoomFocusCenter:
                current_center = current_leftmost + (current_page/2); 
-               if (current_center > (new_page/2)) {
-                       leftmost_after_zoom = current_center - (new_page / 2);
-               } else {
+               if (current_center < half_page_size) {
                        leftmost_after_zoom = 0;
+               } else {
+                       leftmost_after_zoom = current_center - half_page_size;
                }
                break;
                
        case ZoomFocusPlayhead:
-               /* try to keep the playhead in the center */
-               if (playhead_cursor->current_frame > new_page/2) {
-                       leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
-               } else {
+               /* try to keep the playhead in the same place */
+
+               where = playhead_cursor->current_frame;
+               
+               l = - ((new_page_size * ((where - current_leftmost)/(double)current_page)) - where);
+               
+               if (l < 0) {
                        leftmost_after_zoom = 0;
+               } else if (l > max_frames) { 
+                       leftmost_after_zoom = max_frames - new_page_size;
+               } else {
+                       leftmost_after_zoom = (nframes64_t) l;
                }
                break;
 
@@ -1331,20 +1566,20 @@ Editor::temporal_zoom (gdouble fpu)
                        /* use playhead instead */
                        where = playhead_cursor->current_frame;
 
-                       if (where > new_page/2) {
-                               leftmost_after_zoom = where - (new_page/2);
-                       } else {
+                       if (where < half_page_size) {
                                leftmost_after_zoom = 0;
+                       } else {
+                               leftmost_after_zoom = where - half_page_size;
                        }
 
                } else {
 
-                       double l = - ((new_page * ((where - current_leftmost)/(double)current_page)) - where);
+                       l = - ((new_page_size * ((where - current_leftmost)/(double)current_page)) - where);
 
                        if (l < 0) {
                                leftmost_after_zoom = 0;
                        } else if (l > max_frames) { 
-                               leftmost_after_zoom = max_frames - new_page;
+                               leftmost_after_zoom = max_frames - new_page_size;
                        } else {
                                leftmost_after_zoom = (nframes64_t) l;
                        }
@@ -1353,11 +1588,24 @@ Editor::temporal_zoom (gdouble fpu)
                break;
 
        case ZoomFocusEdit:
-               /* try to keep the edit point in the center */
-               if (get_preferred_edit_position() > new_page/2) {
-                       leftmost_after_zoom = get_preferred_edit_position() - (new_page/2);
+               /* try to keep the edit point in the same place */
+               where = get_preferred_edit_position ();
+
+               if (where > 0) {
+
+                       double l = - ((new_page_size * ((where - current_leftmost)/(double)current_page)) - where);
+
+                       if (l < 0) {
+                               leftmost_after_zoom = 0;
+                       } else if (l > max_frames) { 
+                               leftmost_after_zoom = max_frames - new_page_size;
+                       } else {
+                               leftmost_after_zoom = (nframes64_t) l;
+                       }
+
                } else {
-                       leftmost_after_zoom = 0;
+                       /* edit point not defined */
+                       return;
                }
                break;
                
@@ -1365,16 +1613,70 @@ Editor::temporal_zoom (gdouble fpu)
  
        // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
 
-//     begin_reversible_command (_("zoom"));
-//     session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
-//     session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
-//     commit_reversible_command ();
-       
-       // cerr << "repos & zoom to " << leftmost_after_zoom << " @ " << nfpu << endl;
-
        reposition_and_zoom (leftmost_after_zoom, nfpu);
 }      
 
+void
+Editor::temporal_zoom_region ()
+{
+
+       nframes64_t start = max_frames;
+       nframes64_t end = 0;
+
+       ensure_entered_region_selected (true);
+
+       if (selection->regions.empty()) {
+               info << _("cannot set loop: no region selected") << endmsg;
+               return;
+       }
+
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+               if ((*i)->region()->position() < start) {
+                       start = (*i)->region()->position();
+               }
+               if ((*i)->region()->last_frame() + 1 > end) {
+                       end = (*i)->region()->last_frame() + 1;
+               }
+       }
+
+       /* now comes an "interesting" hack ... make sure we leave a little space
+          at each end of the editor so that the zoom doesn't fit the region
+          precisely to the screen.
+       */
+
+       GdkScreen* screen = gdk_screen_get_default ();
+       gint pixwidth = gdk_screen_get_width (screen);
+       gint mmwidth = gdk_screen_get_width_mm (screen);
+       double pix_per_mm = (double) pixwidth/ (double) mmwidth;
+       double one_centimeter_in_pixels = pix_per_mm * 10.0;
+       nframes_t extra_samples = unit_to_frame (one_centimeter_in_pixels);
+       
+       if (start > extra_samples) {
+               start -= extra_samples;
+       } else {
+               start = 0;
+       } 
+
+       if (max_frames - extra_samples > end) {
+               end += extra_samples;
+       } else {
+               end = max_frames;
+       }
+
+       temporal_zoom_by_frame (start, end, "zoom to region");
+       zoomed_to_region = true;
+}
+
+void
+Editor::toggle_zoom_region ()
+{
+       if (zoomed_to_region) {
+               swap_visual_state ();
+       } else {
+               temporal_zoom_region ();
+       }
+}
+
 void
 Editor::temporal_zoom_selection ()
 {
@@ -1493,12 +1795,12 @@ Editor::add_location_from_selection ()
 }
 
 void
-Editor::add_location_from_playhead_cursor ()
+Editor::add_location_mark (nframes64_t where)
 {
        string markername;
 
-       nframes_t where = session->audible_frame();
-       
+       select_new_marker = true;
+
        session->locations()->next_available_name(markername,"mark");
        Location *location = new Location (where, where, markername, Location::IsMark);
        session->begin_reversible_command (_("add marker"));
@@ -1509,6 +1811,12 @@ Editor::add_location_from_playhead_cursor ()
        session->commit_reversible_command ();
 }
 
+void
+Editor::add_location_from_playhead_cursor ()
+{
+       add_location_mark (session->audible_frame());
+}
+
 void
 Editor::add_location_from_audio_region ()
 {
@@ -1760,11 +2068,17 @@ Editor::insert_region_list_selection (float times)
        RouteTimeAxisView *tv = 0;
        boost::shared_ptr<Playlist> playlist;
 
-       if (selection->tracks.empty()) {
-               return;
-       }
-
-       if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
+       if (clicked_routeview != 0) {
+               tv = clicked_routeview;
+       } else if (!selection->tracks.empty()) {
+               if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
+                       return;
+               }
+       } else if (entered_track != 0) {
+               if ((tv = dynamic_cast<RouteTimeAxisView*>(entered_track)) == 0) {
+                       return;
+               }
+       } else {
                return;
        }
 
@@ -1881,23 +2195,32 @@ Editor::play_from_edit_point ()
 }
 
 void
-Editor::play_selection ()
+Editor::play_from_edit_point_and_return ()
 {
-       if (selection->time.empty()) {
-               return;
+       nframes64_t start_frame;
+       nframes64_t return_frame;
+
+       /* don't reset the return frame if its already set */
+
+       if ((return_frame = session->requested_return_frame()) < 0) {
+               return_frame = session->audible_frame();
        }
 
-       session->request_play_range (true);
+       start_frame = get_preferred_edit_position (true);
+
+       if (start_frame >= 0) {
+               session->request_roll_at_and_return (start_frame, return_frame);
+       }
 }
 
 void
-Editor::play_selected_region ()
+Editor::play_selection ()
 {
-       if (!selection->regions.empty()) {
-               RegionView *rv = *(selection->regions.begin());
-
-               session->request_bounded_roll (rv->region()->position(), rv->region()->last_frame());   
+       if (selection->time.empty()) {
+               return;
        }
+
+       session->request_play_range (true);
 }
 
 void
@@ -1948,12 +2271,24 @@ Editor::loop_location (Location& location)
        }
 }
 
+void
+Editor::raise_region ()
+{
+       selection->foreach_region (&Region::raise);
+}
+
 void
 Editor::raise_region_to_top ()
 {
        selection->foreach_region (&Region::raise_to_top);
 }
 
+void
+Editor::lower_region ()
+{
+       selection->foreach_region (&Region::lower);
+}
+
 void
 Editor::lower_region_to_bottom ()
 {
@@ -1968,58 +2303,54 @@ Editor::edit_region ()
 }
 
 void
-Editor::rename_region ()
+Editor::rename_region()
 {
-       Dialog dialog;
-       Entry  entry;
-       Button ok_button (_("OK"));
-       Button cancel_button (_("Cancel"));
-
        if (selection->regions.empty()) {
                return;
        }
 
-       WindowTitle title(Glib::get_application_name());
+       WindowTitle title (Glib::get_application_name());
        title += _("Rename Region");
 
-       dialog.set_title (title.get_string());
-       dialog.set_name ("RegionRenameWindow");
-       dialog.set_size_request (300, -1);
-       dialog.set_position (Gtk::WIN_POS_MOUSE);
-       dialog.set_modal (true);
+       ArdourDialog d (*this, title.get_string(), true, false);
+       Entry entry;
+       Label label (_("New name:"));
+       HBox hbox;
 
-       dialog.get_vbox()->set_border_width (10);
-       dialog.get_vbox()->pack_start (entry);
-       dialog.get_action_area()->pack_start (ok_button);
-       dialog.get_action_area()->pack_start (cancel_button);
+       hbox.set_spacing (6);
+       hbox.pack_start (label, false, false);
+       hbox.pack_start (entry, true, true);
 
-       entry.set_name ("RegionNameDisplay");
-       ok_button.set_name ("EditorGTKButton");
-       cancel_button.set_name ("EditorGTKButton");
+       d.get_vbox()->set_border_width (12);
+       d.get_vbox()->pack_start (hbox, false, false);
 
-       region_renamed = false;
+       d.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
+       d.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
 
-       entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
-       ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
-       cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
+       d.set_size_request (300, -1);
+       d.set_position (Gtk::WIN_POS_MOUSE);
 
-       /* recurse */
+       entry.set_text (selection->regions.front()->region()->name());
+       entry.select_region (0, -1);
 
-       dialog.show_all ();
-       Main::run ();
+       entry.signal_activate().connect (bind (mem_fun (d, &Dialog::response), RESPONSE_OK));
+       
+       d.show_all ();
+       
+       entry.grab_focus();
 
-       if (region_renamed) {
-               (*selection->regions.begin())->region()->set_name (entry.get_text());
-               redisplay_regions ();
-       }
-}
+       int ret = d.run();
 
-void
-Editor::rename_region_finished (bool status)
+       d.hide ();
 
-{
-       region_renamed = status;
-       Main::quit ();
+       if (ret == RESPONSE_OK) {
+               std::string str = entry.get_text();
+               strip_whitespace_edges (str);
+               if (!str.empty()) {
+                       selection->regions.front()->region()->set_name (str);
+                       redisplay_regions ();
+               }
+       }
 }
 
 void
@@ -2043,24 +2374,49 @@ Editor::audition_playlist_region_via_route (boost::shared_ptr<Region> region, Ro
 
 /** Start an audition of the first selected region */
 void
-Editor::audition_selected_region ()
+Editor::play_edit_range ()
 {
-       if (!selection->regions.empty()) {
-               RegionView* rv = *(selection->regions.begin());
-               session->audition_region (rv->region());
+       nframes64_t start, end;
+
+       if (get_edit_op_range (start, end)) {
+               session->request_bounded_roll (start, end);
        }
 }
 
 void
-Editor::audition_playlist_region_standalone (boost::shared_ptr<Region> region)
+Editor::play_selected_region ()
 {
-       session->audition_region (region);
-}
+       nframes64_t start = max_frames;
+       nframes64_t end = 0;
 
-void
-Editor::build_interthread_progress_window ()
-{
-       interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
+       ensure_entered_region_selected (true);
+
+       if (selection->regions.empty()) {
+               return;
+       }
+
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+               if ((*i)->region()->position() < start) {
+                       start = (*i)->region()->position();
+               }
+               if ((*i)->region()->last_frame() + 1 > end) {
+                       end = (*i)->region()->last_frame() + 1;
+               }
+       }
+
+       session->request_bounded_roll (start, end);
+}
+
+void
+Editor::audition_playlist_region_standalone (boost::shared_ptr<Region> region)
+{
+       session->audition_region (region);
+}
+
+void
+Editor::build_interthread_progress_window ()
+{
+       interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
 
        interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
        
@@ -2194,18 +2550,23 @@ Editor::new_region_from_selection ()
        cancel_selection ();
 }
 
-void
-Editor::separate_region_from_selection ()
+static void
+add_if_covered (RegionView* rv, const AudioRange* ar, RegionSelection* rs)
 {
-       // FIXME: TYPE
-       
-       bool doing_undo = false;
-
-       if (selection->time.empty()) {
-               return;
+       switch (rv->region()->coverage (ar->start, ar->end - 1)) {
+       case OverlapNone:
+               break;
+       default:
+               rs->push_back (rv);
        }
+}
 
+void
+Editor::separate_regions_between (const TimeSelection& ts)
+{
+       bool in_command = false;
        boost::shared_ptr<Playlist> playlist;
+       RegionSelection new_selection;
                
        sort_track_selection ();
 
@@ -2220,99 +2581,112 @@ Editor::separate_region_from_selection ()
                        if (t != 0 && ! t->diskstream()->destructive()) {
                                
                                if ((playlist = rtv->playlist()) != 0) {
-                                       if (!doing_undo) {
-                                               begin_reversible_command (_("separate"));
-                                               doing_undo = true;
-                                       }
+
+                                       XMLNode *before = &(playlist->get_state());
+                                       bool got_some = false;  
                                        
-                                       XMLNode *before;
-                                       if (doing_undo)
-                                               before = &(playlist->get_state());
-                       
                                        /* XXX need to consider musical time selections here at some point */
 
                                        double speed = t->diskstream()->speed();
 
-                                       for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
+
+                                       for (list<AudioRange>::const_iterator t = ts.begin(); t != ts.end(); ++t) {
+
+                                               sigc::connection c = rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
+                                               latest_regionviews.clear ();
+
                                                playlist->partition ((nframes_t)((*t).start * speed), (nframes_t)((*t).end * speed), true);
+
+                                               c.disconnect ();
+
+                                               if (!latest_regionviews.empty()) {
+                                                       
+                                                       got_some = true;
+
+                                                       rtv->view()->foreach_regionview (bind (sigc::ptr_fun (add_if_covered), &(*t), &new_selection));
+                                                       
+                                                       if (!in_command) {
+                                                               begin_reversible_command (_("separate"));
+                                                               in_command = true;
+                                                       }
+                                                       
+                                                       session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
+                                                       
+                                               } 
                                        }
 
-                                       if (doing_undo)
-                                               session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
+                                       if (!got_some) {
+                                               delete before;
+                                       }
                                }
                        }
                }
        }
 
-       if (doing_undo) commit_reversible_command ();
+       if (in_command) {
+               selection->set (new_selection);
+               set_mouse_mode (MouseObject);
+
+               commit_reversible_command ();
+       }
 }
 
 void
-Editor::separate_regions_using_location (Location& loc)
+Editor::separate_region_from_selection ()
 {
-       // FIXME: TYPE
-       
-       bool doing_undo = false;
-
-       if (loc.is_mark()) {
-               return;
-       }
-
-       boost::shared_ptr<Playlist> playlist;
-
-       /* XXX i'm unsure as to whether this should operate on selected tracks only 
-          or the entire enchillada. uncomment the below line to correct the behaviour 
-          (currently set for all tracks)
+       /* preferentially use *all* ranges in the time selection if we're in range mode
+          to allow discontiguous operation, since get_edit_op_range() currently
+          returns a single range.
        */
+       if (mouse_mode == MouseRange && !selection->time.empty()) {
 
-       for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {    
-       //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+               separate_regions_between (selection->time);
 
-               RouteTimeAxisView* rtv;
+       } else {
+
+               nframes64_t start;
+               nframes64_t end;
                
-               if ((rtv = dynamic_cast<RouteTimeAxisView*> ((*i))) != 0) {
+               if (get_edit_op_range (start, end)) {
+                       
+                       AudioRange ar (start, end, 1);
+                       TimeSelection ts;
+                       ts.push_back (ar);
 
-                       boost::shared_ptr<Track> t = rtv->track();
+                       /* force track selection */
 
-                       if (t != 0 && ! t->diskstream()->destructive()) {
-                               
-                               if ((playlist = rtv->playlist()) != 0) {
-                                       
-                                       XMLNode *before;
-                                       if (!doing_undo) {
-                                               begin_reversible_command (_("separate"));
-                                               doing_undo = true;
-                                       }
-                                       if (doing_undo)
-                                               before = &(playlist->get_state());
-                                            
+                       ensure_entered_region_selected ();
                        
-                                       /* XXX need to consider musical time selections here at some point */
+                       separate_regions_between (ts);
+               }
+       }
+}
 
-                                       double speed = rtv->get_diskstream()->speed();
+void
+Editor::separate_regions_using_location (Location& loc)
+{
+       if (loc.is_mark()) {
+               return;
+       }
 
+       AudioRange ar (loc.start(), loc.end(), 1);
+       TimeSelection ts;
 
-                                       playlist->partition ((nframes_t)(loc.start() * speed), (nframes_t)(loc.end() * speed), true);
-                                       if (doing_undo) 
-                                            session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
-                               }
-                       }
-               }
-       }
+       ts.push_back (ar);
 
-       if (doing_undo) commit_reversible_command ();
+       separate_regions_between (ts);
 }
 
 void
 Editor::crop_region_to_selection ()
 {
-       ensure_entered_selected ();
+       ensure_entered_region_selected (true);
 
        if (!selection->time.empty()) {
 
                crop_region_to (selection->time.start(), selection->time.end_frame());
 
-       } else if (_edit_point != EditAtPlayhead) {
+       } else {
 
                nframes64_t start;
                nframes64_t end;
@@ -2331,8 +2705,6 @@ Editor::crop_region_to (nframes_t start, nframes_t end)
        boost::shared_ptr<Playlist> playlist;
        TrackSelection* ts;
 
-       ensure_entered_selected ();
-
        if (selection->tracks.empty()) {
                ts = &track_views;
        } else {
@@ -2490,49 +2862,40 @@ Editor::region_fill_selection ()
 }
 
 void
-Editor::set_a_regions_sync_position (boost::shared_ptr<Region> region, nframes_t position)
+Editor::set_region_sync_from_edit_point ()
 {
-
-       if (!region->covers (position)) {
-         error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
-               return;
-       }
-       begin_reversible_command (_("set region sync position"));
-        XMLNode &before = region->playlist()->get_state();
-       region->set_sync_position (position);
-        XMLNode &after = region->playlist()->get_state();
-       session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
-       commit_reversible_command ();
+       nframes64_t where = get_preferred_edit_position ();
+       ensure_entered_region_selected (true);
+       set_sync_point (where, selection->regions);
 }
 
-/** Set the sync position of the selection using the position of the edit cursor */
 void
-Editor::set_region_sync_from_edit_point ()
+Editor::set_sync_point (nframes64_t where, const RegionSelection& rs)
 {
-       /* Check that at the edit cursor is in at least one of the selected regions */
-       RegionSelection::const_iterator i = selection->regions.begin();
+       bool in_command = false;
 
-       while (i != selection->regions.end() && !(*i)->region()->covers (get_preferred_edit_position())) {
-               ++i;
-       }
+       for (RegionSelection::const_iterator r = rs.begin(); r != rs.end(); ++r) {
+               
+               if (!(*r)->region()->covers (where)) {
+                       continue;
+               }
 
-       /* Give the user a hint if not */
-       if (i == selection->regions.end()) {
-               error << _("Place the edit point at the desired sync point") << endmsg;
-               return;
-       }
+               boost::shared_ptr<Region> region ((*r)->region());
 
-       begin_reversible_command (_("set sync from edit point"));
-       
-       for (RegionSelection::iterator j = selection->regions.begin(); j != selection->regions.end(); ++j) {
-               boost::shared_ptr<Region> r = (*j)->region();
-               XMLNode &before = r->playlist()->get_state();
-               r->set_sync_position (get_preferred_edit_position());
-               XMLNode &after = r->playlist()->get_state();
-               session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
+               if (!in_command) {
+                       begin_reversible_command (_("set sync point"));
+                       in_command = true;
+               }
+
+               XMLNode &before = region->playlist()->get_state();
+               region->set_sync_position (get_preferred_edit_position());
+               XMLNode &after = region->playlist()->get_state();
+               session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
        }
 
-       commit_reversible_command ();
+       if (in_command) {
+               commit_reversible_command ();
+       }
 }
 
 /** Remove the sync positions of the selection */
@@ -2571,7 +2934,7 @@ Editor::naturalize ()
 void
 Editor::align (RegionPoint what)
 {
-       ensure_entered_selected ();
+       ensure_entered_region_selected ();
 
        nframes64_t where = get_preferred_edit_position();
 
@@ -2737,7 +3100,7 @@ Editor::trim_region_to_punch ()
 void
 Editor::trim_region_to_location (const Location& loc, const char* str)
 {
-       ensure_entered_selected ();
+       ensure_entered_region_selected ();
 
        RegionSelection& rs (get_regions_for_action ());
 
@@ -3082,12 +3445,13 @@ Editor::cut_copy (CutCopyOp op)
 
        switch (current_mouse_mode()) {
        case MouseObject: 
+               cerr << "cutting in object mode\n";
                if (!selection->regions.empty() || !selection->points.empty()) {
 
                        begin_reversible_command (opname + _(" objects"));
 
                        if (!selection->regions.empty()) {
-                               
+                               cerr << "have regions to cut" << endl;
                                cut_copy_regions (op);
                                
                                if (op == Cut) {
@@ -3106,6 +3470,7 @@ Editor::cut_copy (CutCopyOp op)
                        commit_reversible_command ();   
                        break; // terminate case statement here
                } 
+               cerr << "nope, now cutting time range" << endl;
                if (!selection->time.empty()) {
                        /* don't cause suprises */
                        break;
@@ -3115,10 +3480,12 @@ Editor::cut_copy (CutCopyOp op)
        case MouseRange:
                if (selection->time.empty()) {
                        nframes64_t start, end;
+                       cerr << "no time selection, get edit op range" << endl;
                        if (!get_edit_op_range (start, end)) {
+                               cerr << "no edit op range" << endl;
                                return;
                        }
-                       selection->set (0, start, end);
+                       selection->set ((TimeAxisView*) 0, start, end);
                }
                        
                begin_reversible_command (opname + _(" range"));
@@ -3347,7 +3714,7 @@ Editor::paste_internal (nframes_t position, float times)
 {
        bool commit = false;
 
-       if (cut_buffer->empty() || selection->tracks.empty()) {
+       if (cut_buffer->empty()) {
                return;
        }
 
@@ -3357,14 +3724,21 @@ Editor::paste_internal (nframes_t position, float times)
 
        begin_reversible_command (_("paste"));
 
+       TrackSelection ts;
        TrackSelection::iterator i;
        size_t nth;
 
        /* get everything in the correct order */
 
-       sort_track_selection ();
 
-       for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
+       if (!selection->tracks.empty()) {
+               sort_track_selection ();
+               ts = selection->tracks;
+       } else if (entered_track) {
+               ts.push_back (entered_track);
+       }
+
+       for (nth = 0, i = ts.begin(); i != ts.end(); ++i, ++nth) {
 
                /* undo/redo is handled by individual tracks */
 
@@ -3438,8 +3812,9 @@ void
 Editor::duplicate_some_regions (RegionSelection& regions, float times)
 {
        boost::shared_ptr<Playlist> playlist; 
-       RegionSelection sel = regions; // clear (below) will clear the argument list
-               
+       RegionSelection sel = regions; // clear (below) may  clear the argument list if its the current region selection
+       RegionSelection foo;
+
        begin_reversible_command (_("duplicate region"));
 
        selection->clear_regions ();
@@ -3450,6 +3825,7 @@ Editor::duplicate_some_regions (RegionSelection& regions, float times)
 
                TimeAxisView& tv = (*i)->get_time_axis_view();
                RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&tv);
+               latest_regionviews.clear ();
                sigc::connection c = rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
                
                playlist = (*i)->region()->playlist();
@@ -3458,14 +3834,15 @@ Editor::duplicate_some_regions (RegionSelection& regions, float times)
                session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
 
                c.disconnect ();
-
-               if (latest_regionview) {
-                       selection->add (latest_regionview);
-               }
-       }
                
+               foo.insert (foo.end(), latest_regionviews.begin(), latest_regionviews.end());
+       }
 
        commit_reversible_command ();
+
+       if (!foo.empty()) {
+               selection->set (foo);
+       }
 }
 
 void
@@ -3915,7 +4292,7 @@ Editor::toggle_region_opaque ()
 void
 Editor::set_fade_length (bool in)
 {
-       ensure_entered_selected ();
+       ensure_entered_region_selected (true);
 
        /* we need a region to measure the offset from the start */
 
@@ -3976,6 +4353,51 @@ Editor::set_fade_length (bool in)
        commit_reversible_command ();
 }
 
+
+void
+Editor::toggle_fade_active (bool in)
+{
+       ensure_entered_region_selected (true);
+
+       if (selection->regions.empty()) {
+               return;
+       }
+
+       const char* cmd = (in ? _("toggle fade in active") : _("toggle fade out active"));
+       bool have_switch = false;
+       bool yn;
+       bool in_command = false;
+
+       begin_reversible_command (cmd);
+
+       for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
+               AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
+               
+               if (!tmp) {
+                       return;
+               }
+
+               boost::shared_ptr<AudioRegion> region (tmp->audio_region());
+
+               /* make the behaviour consistent across all regions */
+               
+               if (!have_switch) {
+                       yn = region->fade_in_active();
+                       have_switch = true;
+               }
+
+               XMLNode &before = region->get_state();
+               region->set_fade_in_active (!yn);
+               XMLNode &after = region->get_state();
+               session->add_command(new MementoCommand<AudioRegion>(*region.get(), &before, &after));
+               in_command = true;
+       }
+
+       if (in_command) {
+               commit_reversible_command ();
+       }
+}
+
 void
 Editor::set_fade_in_shape (AudioRegion::FadeShape shape)
 {
@@ -4141,8 +4563,8 @@ Editor::set_playhead_cursor ()
 void
 Editor::split ()
 {
-       ensure_entered_selected ();
-
+       ensure_entered_region_selected ();
+       
        nframes64_t where = get_preferred_edit_position();
 
        if (!selection->regions.empty()) {
@@ -4158,11 +4580,253 @@ Editor::split ()
 }
 
 void
-Editor::ensure_entered_selected ()
+Editor::ensure_entered_track_selected (bool op_really_wants_one_track_if_none_are_selected)
 {
-       if (entered_regionview) {
-               if (find (selection->regions.begin(), selection->regions.end(), entered_regionview) == selection->regions.end()) {
-                       selection->set (entered_regionview);
+       if (entered_track && mouse_mode == MouseObject) {
+               if (!selection->tracks.empty()) {
+                       if (!selection->selected (entered_track)) {
+                               selection->add (entered_track);
+                       }
+               } else {
+                       /* there is no selection, but this operation requires/prefers selected objects */
+
+                       if (op_really_wants_one_track_if_none_are_selected) {
+                               selection->set (entered_track);
+                       }
+               }
+       }
+}
+
+void
+Editor::ensure_entered_region_selected (bool op_really_wants_one_region_if_none_are_selected)
+{
+       if (entered_regionview && mouse_mode == MouseObject) {
+
+               /* heuristic:
+
+                  - if there is no existing selection, don't change it. the operation will thus apply to "all"
+
+                  - if there is an existing selection, but the entered regionview isn't in it, add it. this
+                      avoids key-mouse ops on unselected regions from interfering with an existing selection,
+                      but also means that the operation will apply to the pointed-at region.
+               */
+
+               if (!selection->regions.empty()) {
+                       if (find (selection->regions.begin(), selection->regions.end(), entered_regionview) != selection->regions.end()) {
+                               selection->add (entered_regionview);
+                       }
+               } else {
+                       /* there is no selection, but this operation requires/prefers selected objects */
+
+                       if (op_really_wants_one_region_if_none_are_selected) {
+                               selection->set (entered_regionview, false);
+                       }
                }
        }
 }
+
+void
+Editor::trim_region_front ()
+{
+       trim_region (true);
+}
+
+void
+Editor::trim_region_back ()
+{
+       trim_region (false);
+}
+
+void
+Editor::trim_region (bool front)
+{
+       nframes64_t where = get_preferred_edit_position();
+       RegionSelection& rs = get_regions_for_action ();
+
+       if (rs.empty()) {
+               return;
+       }
+
+       begin_reversible_command (front ? _("trim front") : _("trim back"));
+
+       for (list<RegionView*>::const_iterator i = rs.by_layer().begin(); i != rs.by_layer().end(); ++i) {
+               if (!(*i)->region()->locked()) {
+                       boost::shared_ptr<Playlist> pl = (*i)->region()->playlist();
+                       XMLNode &before = pl->get_state();
+                       if (front) {
+                               (*i)->region()->trim_front (where, this);       
+                       } else {
+                               (*i)->region()->trim_end (where, this); 
+                       }
+                       XMLNode &after = pl->get_state();
+                       session->add_command(new MementoCommand<Playlist>(*pl.get(), &before, &after));
+               }
+       }
+       commit_reversible_command ();
+}
+
+struct EditorOrderRouteSorter {
+    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");
+    }
+};
+
+void
+Editor::select_next_route()
+{
+       if (selection->tracks.empty()) {
+               selection->set (track_views.front());
+               return;
+       }
+
+       TimeAxisView* current = selection->tracks.front();
+
+       for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+               if (*i == current) {
+                       ++i;
+                       if (i != track_views.end()) {
+                               selection->set (*i);
+                       } else {
+                               selection->set (*(track_views.begin()));
+                       }
+                       break;
+               }
+       }
+}
+
+void
+Editor::select_prev_route()
+{
+       if (selection->tracks.empty()) {
+               selection->set (track_views.front());
+               return;
+       }
+
+       TimeAxisView* current = selection->tracks.front();
+
+       for (TrackViewList::reverse_iterator i = track_views.rbegin(); i != track_views.rend(); ++i) {
+               if (*i == current) {
+                       ++i;
+                       if (i != track_views.rend()) {
+                               selection->set (*i);
+                       } else {
+                               selection->set (*(track_views.rbegin()));
+                       }
+                       break;
+               }
+       }
+}
+
+void
+Editor::set_loop_from_selection (bool play)
+{
+       if (session == 0 || selection->time.empty()) {
+               return;
+       }
+
+       nframes_t start = selection->time[clicked_selection].start;
+       nframes_t end = selection->time[clicked_selection].end;
+       
+       set_loop_range (start, end,  _("set loop range from selection"));
+
+       if (play) {
+               session->request_play_loop (true);
+               session->request_locate (start, true);
+       }
+}
+
+void
+Editor::set_loop_from_edit_range (bool play)
+{
+       if (session == 0) {
+               return;
+       }
+
+       nframes64_t start;
+       nframes64_t end;
+       
+       if (!get_edit_op_range (start, end)) {
+               return;
+       }
+
+       set_loop_range (start, end,  _("set loop range from edit range"));
+
+       if (play) {
+               session->request_play_loop (true);
+               session->request_locate (start, true);
+       }
+}
+
+void
+Editor::set_loop_from_region (bool play)
+{
+       nframes64_t start = max_frames;
+       nframes64_t end = 0;
+
+       ensure_entered_region_selected (true);
+
+       if (selection->regions.empty()) {
+               info << _("cannot set loop: no region selected") << endmsg;
+               return;
+       }
+
+       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+               if ((*i)->region()->position() < start) {
+                       start = (*i)->region()->position();
+               }
+               if ((*i)->region()->last_frame() + 1 > end) {
+                       end = (*i)->region()->last_frame() + 1;
+               }
+       }
+
+       set_loop_range (start, end, _("set loop range from region"));
+
+       if (play) {
+               session->request_play_loop (true);
+               session->request_locate (start, true);
+       }
+}
+
+void
+Editor::set_punch_from_selection ()
+{
+       if (session == 0 || selection->time.empty()) {
+               return;
+       }
+
+       nframes_t start = selection->time[clicked_selection].start;
+       nframes_t end = selection->time[clicked_selection].end;
+       
+       set_punch_range (start, end,  _("set punch range from selection"));
+}
+
+void
+Editor::set_punch_from_edit_range ()
+{
+       if (session == 0) {
+               return;
+       }
+
+       nframes64_t start;
+       nframes64_t end;
+       
+       if (!get_edit_op_range (start, end)) {
+               return;
+       }
+
+       set_punch_range (start, end,  _("set punch range from edit range"));
+}
+
+void
+Editor::pitch_shift_regions ()
+{
+       ensure_entered_region_selected (true);
+       
+       if (selection->regions.empty()) {
+               return;
+       }
+
+       pitch_shift (selection->regions, 1.2);
+}
+       
index 3e47d26cd6b7e2e0cdbbc670ba568bfc7fd68eda..e15ee6448c3b00e6b12e036659fcc49546725949 100644 (file)
@@ -38,6 +38,7 @@
 #include "ardour_ui.h"
 #include "gui_thread.h"
 #include "actions.h"
+#include "region_view.h"
 #include "utils.h"
 
 #include "i18n.h"
@@ -89,10 +90,6 @@ Editor::add_region_to_region_display (boost::shared_ptr<Region> region)
        Gdk::Color c;
        bool missing_source;
 
-       region_state_changed_connections.push_back (
-               region->StateChanged.connect (bind (mem_fun (*this, &Editor::region_list_region_changed), boost::weak_ptr<Region> (region)))
-               );
-
        missing_source = boost::dynamic_pointer_cast<SilentFileSource>(region->source());
 
        if (!show_automatic_regions_in_region_list && region->automatic()) {
@@ -309,13 +306,6 @@ Editor::redisplay_regions ()
 {
        if (session) {
 
-               for (std::list<connection>::iterator i = region_state_changed_connections.begin();
-                    i != region_state_changed_connections.end();
-                    ++i)
-               {
-                       i->disconnect ();
-               }
-
                region_list_display.set_model (Glib::RefPtr<Gtk::TreeStore>(0));
                region_list_model->clear ();
 
@@ -419,6 +409,8 @@ Editor::region_list_display_button_press (GdkEventButton *ev)
        int cellx;
        int celly;
 
+       cerr << "Button press release, button = " << ev->button << endl;
+
        if (region_list_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) {
                if ((iter = region_list_model->get_iter (path))) {
                        region = (*iter)[region_list_columns.region];
@@ -427,27 +419,25 @@ Editor::region_list_display_button_press (GdkEventButton *ev)
 
        if (Keyboard::is_context_menu_event (ev)) {
                show_region_list_display_context_menu (ev->button, ev->time);
+               cerr << "\tcontext menu event, event handled\n";
                return true;
        }
 
        if (region == 0) {
+               cerr << "\tno region, event not handled\n";
                return false;
        }
 
        switch (ev->button) {
        case 1:
-               /* audition on double click */
-               if (ev->type == GDK_2BUTTON_PRESS) {
-                       consider_auditioning (region);
-                       return true;
-               }
-               return false;
                break;
 
        case 2:
-               if (!Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+               // audition on middle click (stop audition too)
+               if (!Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
                        consider_auditioning (region);
                }
+               cerr << "\taudition, event handled\n";
                return true;
                break;
 
@@ -455,6 +445,7 @@ Editor::region_list_display_button_press (GdkEventButton *ev)
                break; 
        }
 
+       cerr << "\tnot handled\n";
        return false;
 }      
 
@@ -674,6 +665,12 @@ Editor::region_list_display_drag_data_received (const RefPtr<Gdk::DragContext>&
 {
        vector<ustring> paths;
 
+       if (data.get_target() == "GTK_TREE_MODEL_ROW") {
+               cerr << "Delete drag data drop to treeview\n";
+               region_list_display.on_drag_data_received (context, x, y, data, info, time);
+               return;
+       }
+
        if (convert_drop_to_paths (paths, context, x, y, data, info, time) == 0) {
                nframes64_t pos = 0;
                do_embed (paths, Editing::ImportDistinctFiles, ImportAsRegion, pos);
@@ -697,3 +694,30 @@ Editor::region_list_selection_filter (const RefPtr<TreeModel>& model, const Tree
 
        return true;
 }
+
+void
+Editor::region_name_edit (const Glib::ustring& path, const Glib::ustring& new_text)
+{
+       boost::shared_ptr<Region> region;
+       TreeIter iter;
+       
+       if ((iter = region_list_model->get_iter (path))) {
+               region = (*iter)[region_list_columns.region];
+               (*iter)[region_list_columns.name] = new_text;
+       }
+       
+       /* now mapover everything */
+
+       if (region) {
+               vector<RegionView*> equivalents;
+               get_regions_corresponding_to (region, equivalents);
+
+               for (vector<RegionView*>::iterator i = equivalents.begin(); i != equivalents.end(); ++i) {
+                       if (new_text != (*i)->region()->name()) {
+                               (*i)->region()->set_name (new_text);
+                       }
+               }
+       }
+
+}
+
index b700f9e4697b5ded979ddd67677a3168ddbfa7b1..c422a43859702572f6cf239c6d62d8f0306d3e3e 100644 (file)
@@ -41,6 +41,7 @@ using namespace sigc;
 using namespace ARDOUR;
 using namespace PBD;
 using namespace Gtk;
+using namespace Glib;
 
 
 void
@@ -70,7 +71,7 @@ Editor::handle_new_route (Session::RouteList& routes)
                        tv = new MidiTimeAxisView (*this, *session, route, track_canvas);
                else
                        throw unknown_type();
-               
+               //cerr << "Editor::handle_new_route() called on " << route->name() << endl;//DEBUG
 #if 0
                if (route_display_model->children().size() == 0) {
                        
@@ -155,42 +156,10 @@ Editor::remove_route (TimeAxisView *tv)
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::remove_route), tv));
 
+       TrackViewList::iterator i;
        TreeModel::Children rows = route_display_model->children();
        TreeModel::Children::iterator ri;
 
-       /* find the track view that's being deleted */
-       TrackViewList::iterator i = find (track_views.begin(), track_views.end(), tv);
-
-       /* set up `nearby' to be a suitable nearby track to select once
-          this one has gone */
-       TrackViewList::iterator nearby = track_views.end ();
-       if (i != track_views.end()) {
-
-               nearby = i;
-
-               if (nearby != track_views.begin()) {
-                       /* go to the previous track if there is one */
-                       nearby--;
-               } else {
-                       /* otherwise the next track */
-                       nearby++;
-               }
-
-               /* and remove the track view that's going */
-               track_views.erase (i);
-
-               if (nearby != track_views.end()) {
-                       /* we've got another track to select, so select it */
-                       set_selected_track (**nearby, Selection::Set);
-               } else {
-                       /* we've got no other track, so the editor mixer will disappear */
-                       editor_mixer_button.set_active (false);
-                       ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
-                       editor_mixer_button.set_sensitive (false);
-                       editor_list_button.set_sensitive (false);
-               }
-       }
-
        /* Decrement old order keys for tracks `above' the one that is being removed */
        for (ri = rows.begin(); ri != rows.end(); ++ri) {
                TimeAxisView* v = (*ri)[route_display_columns.tv];
@@ -205,6 +174,23 @@ Editor::remove_route (TimeAxisView *tv)
                        break;
                }
        }
+
+       if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
+               track_views.erase (i);
+       }
+
+       /* since the editor mixer goes away when you remove a route, set the
+        * button to inactive and untick the menu option
+        */
+
+       editor_mixer_button.set_active(false);
+       ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
+
+       /* and disable if all tracks and/or routes are gone */
+
+       if (track_views.size() == 0) {
+               editor_mixer_button.set_sensitive(false);
+       }
 }
 
 void
@@ -609,3 +595,21 @@ Editor::route_list_delete (const Gtk::TreeModel::Path& path)
        session->set_remote_control_ids();
        redisplay_route_list ();
 }
+
+
+void  
+Editor::route_list_display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
+                                               int x, int y, 
+                                               const SelectionData& data,
+                                               guint info, guint time)
+{
+       cerr << "RouteLD::dddr target = " << data.get_target() << endl;
+       
+       if (data.get_target() == "GTK_TREE_MODEL_ROW") {
+               cerr << "Delete drag data drop to treeview\n";
+               route_list_display.on_drag_data_received (context, x, y, data, info, time);
+               return;
+       }
+       cerr << "some other kind of drag\n";
+       context->drag_finish (true, false, time);
+}
index 4eb684c48ab5bebc5bf6c6158a47b6e5bf037e0b..f0624ccbb2bdb414cad4fb7bbc940d60152db552 100644 (file)
@@ -23,6 +23,7 @@
 #include <string>
 
 #include <ardour/tempo.h>
+#include <ardour/profile.h>
 #include <gtkmm2ext/gtk_ui.h>
 
 #include "editor.h"
@@ -91,33 +92,64 @@ Editor::initialize_rulers ()
        ruler_shown[ruler_time_marker] = true;
        ruler_shown[ruler_time_range_marker] = true;
        ruler_shown[ruler_time_transport_marker] = true;
+       if (Profile->get_sae()) {
+               ruler_shown[ruler_time_cd_marker] = false;
+       } else {
+               ruler_shown[ruler_time_cd_marker] = true;
+       }
        ruler_shown[ruler_metric_frames] = false;
        ruler_shown[ruler_metric_minsec] = false;
        
-       smpte_ruler->set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
-       bbt_ruler->set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
-       frames_ruler->set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
-       minsec_ruler->set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
-
-       smpte_ruler->signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_button_release));
-       bbt_ruler->signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_button_release));
-       frames_ruler->signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_button_release));
-       minsec_ruler->signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_button_release));
-
-       smpte_ruler->signal_button_press_event().connect (mem_fun(*this, &Editor::ruler_button_press));
-       bbt_ruler->signal_button_press_event().connect (mem_fun(*this, &Editor::ruler_button_press));
-       frames_ruler->signal_button_press_event().connect (mem_fun(*this, &Editor::ruler_button_press));
-       minsec_ruler->signal_button_press_event().connect (mem_fun(*this, &Editor::ruler_button_press));
-       
-       smpte_ruler->signal_motion_notify_event().connect (mem_fun(*this, &Editor::ruler_mouse_motion));
-       bbt_ruler->signal_motion_notify_event().connect (mem_fun(*this, &Editor::ruler_mouse_motion));
-       frames_ruler->signal_motion_notify_event().connect (mem_fun(*this, &Editor::ruler_mouse_motion));
-       minsec_ruler->signal_motion_notify_event().connect (mem_fun(*this, &Editor::ruler_mouse_motion));
-       
        visible_timebars = 7; /* 4 here, 3 in time_canvas */
        ruler_pressed_button = 0;
 }
 
+bool
+Editor::ruler_scroll (GdkEventScroll* event)
+{
+       nframes_t xdelta;
+       int direction = event->direction;
+       bool handled = false;
+
+       switch (direction) {
+       case GDK_SCROLL_UP:
+               temporal_zoom_step (true);
+               handled = true;
+               break;
+
+       case GDK_SCROLL_DOWN:
+               temporal_zoom_step (false);
+               handled = true;
+               break;
+
+       case GDK_SCROLL_LEFT:
+               xdelta = (current_page_frames() / 2);
+               if (leftmost_frame > xdelta) {
+                       reset_x_origin (leftmost_frame - xdelta);
+               } else {
+                       reset_x_origin (0);
+               }
+               handled = true;
+               break;
+
+       case GDK_SCROLL_RIGHT:
+               xdelta = (current_page_frames() / 2);
+               if (max_frames - xdelta > leftmost_frame) {
+                       reset_x_origin (leftmost_frame + xdelta);
+               } else {
+                       reset_x_origin (max_frames - current_page_frames());
+               }
+               handled = true;
+               break;
+
+       default:
+               /* what? */
+               break;
+       }
+
+       return handled;
+}
+
 
 gint
 Editor::ruler_button_press (GdkEventButton* ev)
@@ -165,9 +197,7 @@ Editor::ruler_button_press (GdkEventButton* ev)
 
        case 2:
                /* edit point */
-               if (snap_type != Editing::SnapToEditPoint) {
-                       snap_to (where);
-               }
+               snap_to (where);
                break;
 
        default:
@@ -206,9 +236,7 @@ Editor::ruler_button_release (GdkEventButton* ev)
 
        case 2:
                /* edit point */
-               if (snap_type != Editing::SnapToEditPoint) {
-                       snap_to (where);
-               }
+               snap_to (where);
                break;
 
        case 3:
@@ -338,7 +366,7 @@ Editor::popup_ruler_menu (nframes_t where, ItemType t)
 
        switch (t) {
        case MarkerBarItem:
-               ruler_items.push_back (MenuElem (_("New location marker"), bind ( mem_fun(*this, &Editor::mouse_add_new_marker), where)));
+               ruler_items.push_back (MenuElem (_("New location marker"), bind ( mem_fun(*this, &Editor::mouse_add_new_marker), where, false)));
                ruler_items.push_back (MenuElem (_("Clear all locations"), mem_fun(*this, &Editor::clear_markers)));
                ruler_items.push_back (MenuElem (_("Unhide locations"), mem_fun(*this, &Editor::unhide_markers)));
                ruler_items.push_back (SeparatorElem ());
@@ -353,7 +381,13 @@ Editor::popup_ruler_menu (nframes_t where, ItemType t)
        case TransportMarkerBarItem:
 
                break;
+       
+       case CdMarkerBarItem:
+               // TODO
+               ruler_items.push_back (MenuElem (_("New CD track marker"), bind ( mem_fun(*this, &Editor::mouse_add_new_marker), where, true)));
+               break;
                
+       
        case TempoBarItem:
                ruler_items.push_back (MenuElem (_("New Tempo"), bind ( mem_fun(*this, &Editor::mouse_add_new_tempo_event), where)));
                ruler_items.push_back (MenuElem (_("Clear tempo")));
@@ -382,7 +416,7 @@ Editor::popup_ruler_menu (nframes_t where, ItemType t)
                mitem->set_active(true);
        }
 
-       ruler_items.push_back (CheckMenuElem (_("Frames"), bind (mem_fun(*this, &Editor::ruler_toggled), (int)ruler_metric_frames)));
+       ruler_items.push_back (CheckMenuElem (_("Samples"), bind (mem_fun(*this, &Editor::ruler_toggled), (int)ruler_metric_frames)));
        mitem = (CheckMenuItem *) &ruler_items.back(); 
        if (ruler_shown[ruler_metric_frames]) {
                mitem->set_active(true);
@@ -414,9 +448,17 @@ Editor::popup_ruler_menu (nframes_t where, ItemType t)
                mitem->set_active(true);
        }
 
-       ruler_items.push_back (CheckMenuElem (_("Range Markers"), bind (mem_fun(*this, &Editor::ruler_toggled), (int)ruler_time_range_marker)));
+       if (!Profile->get_sae()) {
+               ruler_items.push_back (CheckMenuElem (_("Range Markers"), bind (mem_fun(*this, &Editor::ruler_toggled), (int)ruler_time_range_marker)));
+               mitem = (CheckMenuItem *) &ruler_items.back(); 
+               if (ruler_shown[ruler_time_range_marker]) {
+                       mitem->set_active(true);
+               }
+       }
+
+       ruler_items.push_back (CheckMenuElem (_("CD Markers"), bind (mem_fun(*this, &Editor::ruler_toggled), (int)ruler_time_cd_marker)));
        mitem = (CheckMenuItem *) &ruler_items.back(); 
-       if (ruler_shown[ruler_time_range_marker]) {
+       if (ruler_shown[ruler_time_cd_marker]) {
                mitem->set_active(true);
        }
 
@@ -468,6 +510,7 @@ Editor::store_ruler_visibility ()
        node->add_property (X_("marker"), ruler_shown[ruler_time_marker] ? "yes": "no");
        node->add_property (X_("rangemarker"), ruler_shown[ruler_time_range_marker] ? "yes": "no");
        node->add_property (X_("transportmarker"), ruler_shown[ruler_time_transport_marker] ? "yes": "no");
+       node->add_property (X_("cdmarker"), ruler_shown[ruler_time_cd_marker] ? "yes": "no");
 
        session->add_extra_xml (*node);
        session->set_dirty ();
@@ -528,6 +571,7 @@ Editor::restore_ruler_visibility ()
                        else 
                                ruler_shown[ruler_time_range_marker] = false;
                }
+
                if ((prop = node->property ("transportmarker")) != 0) {
                        if (prop->value() == "yes") 
                                ruler_shown[ruler_time_transport_marker] = true;
@@ -535,6 +579,29 @@ Editor::restore_ruler_visibility ()
                                ruler_shown[ruler_time_transport_marker] = false;
                }
 
+               if ((prop = node->property ("cdmarker")) != 0) {
+                       if (prop->value() == "yes") 
+                               ruler_shown[ruler_time_cd_marker] = true;
+                       else 
+                               ruler_shown[ruler_time_cd_marker] = false;
+
+                       cerr << "cd marker ruler set to " << ruler_shown[ruler_time_cd_marker] << endl;
+
+               } else {
+                       // this session doesn't yet know about the cdmarker ruler
+                       // as a benefit to the user who doesn't know the feature exists, show the ruler if 
+                       // any cd marks exist
+                       ruler_shown[ruler_time_cd_marker] = false;
+                       const Locations::LocationList & locs = session->locations()->list();
+                       for (Locations::LocationList::const_iterator i = locs.begin(); i != locs.end(); ++i) {
+                               if ((*i)->is_cd_marker()) {
+                                       ruler_shown[ruler_time_cd_marker] = true;
+                                       break;
+                               }
+                       }
+                       cerr << "cd marker ruler default to " << ruler_shown[ruler_time_cd_marker] << endl;
+               }
+
        }
 
        update_ruler_visibility ();
@@ -583,11 +650,10 @@ Editor::update_ruler_visibility ()
        minsec_ruler->set_size_request (-1, (int)timebar_height);
        gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_minsec_ruler), &ruler_metrics[ruler_metric_minsec]);
 
-       
-       smpte_ruler->set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
-       bbt_ruler->set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
-       frames_ruler->set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
-       minsec_ruler->set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
+       smpte_ruler->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
+       bbt_ruler->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
+       frames_ruler->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
+       minsec_ruler->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
 
        smpte_ruler->signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_button_release));
        bbt_ruler->signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_button_release));
@@ -606,6 +672,13 @@ Editor::update_ruler_visibility ()
        
        ruler_children.insert (canvaspos, Element(*_ruler_separator, PACK_SHRINK, PACK_START));
 
+       smpte_ruler->signal_scroll_event().connect (mem_fun(*this, &Editor::ruler_scroll));
+       bbt_ruler->signal_scroll_event().connect (mem_fun(*this, &Editor::ruler_scroll));
+       frames_ruler->signal_scroll_event().connect (mem_fun(*this, &Editor::ruler_scroll));
+       minsec_ruler->signal_scroll_event().connect (mem_fun(*this, &Editor::ruler_scroll));
+
+       ruler_children.insert (canvaspos, Element(*_ruler_separator, PACK_SHRINK, PACK_START));
+       
        if (ruler_shown[ruler_metric_minsec]) {
                lab_children.push_back (Element(minsec_label, PACK_SHRINK, PACK_START));
                ruler_children.insert (canvaspos, Element(*minsec_ruler, PACK_SHRINK, PACK_START));
@@ -662,7 +735,7 @@ Editor::update_ruler_visibility ()
                tempo_group->hide();
        }
        
-       if (ruler_shown[ruler_time_range_marker]) {
+       if (!Profile->get_sae() && ruler_shown[ruler_time_range_marker]) {
                lab_children.push_back (Element(range_mark_label, PACK_SHRINK, PACK_START));
                old_unit_pos = range_marker_group->property_y();
                if (tbpos != old_unit_pos) {
@@ -671,8 +744,7 @@ Editor::update_ruler_visibility ()
                range_marker_group->show();
                tbpos += timebar_height;
                visible_timebars++;
-       }
-       else {
+       } else {
                range_marker_group->hide();
        }
 
@@ -689,6 +761,24 @@ Editor::update_ruler_visibility ()
        else {
                transport_marker_group->hide();
        }
+
+       if (ruler_shown[ruler_time_cd_marker]) {
+               lab_children.push_back (Element(cd_mark_label, PACK_SHRINK, PACK_START));
+               old_unit_pos = cd_marker_group->property_y();
+               if (tbpos != old_unit_pos) {
+                       cd_marker_group->move (0.0, tbpos - old_unit_pos);
+               }
+               cd_marker_group->show();
+               tbpos += timebar_height;
+               visible_timebars++;
+               // make sure all cd markers show up in their respective places
+               update_cd_marker_display();
+       }
+       else {
+               cd_marker_group->hide();
+               // make sure all cd markers show up in their respective places
+               update_cd_marker_display();
+       }
        
        if (ruler_shown[ruler_time_marker]) {
                lab_children.push_back (Element(mark_label, PACK_SHRINK, PACK_START));
index 554f5c341d4372fadc1d7cff8a9587726fb27ad7..5fcdb8ef327a83129c083653fafd16a571353dda 100644 (file)
@@ -17,6 +17,9 @@
 
 */
 
+#include <algorithm>
+#include <stdlib.h>
+
 #include <pbd/stacktrace.h>
 
 #include <ardour/diskstream.h>
@@ -160,36 +163,47 @@ Editor::select_all_tracks ()
        selection->set (track_views);
 }
 
-bool
+void
+Editor::set_selected_track_as_side_effect (bool force)
+{
+       if (!clicked_routeview) {
+               return;
+       }
+
+       if (!selection->tracks.empty()) {
+               if (!selection->selected (clicked_routeview)) {
+                       selection->add (clicked_routeview);
+               }
+
+       } else if (force) {
+               selection->set (clicked_routeview);
+       }
+}
+
+void
 Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove)
 {
-       bool commit = false;
 
        switch (op) {
        case Selection::Toggle:
                if (selection->selected (&view)) {
                        if (!no_remove) {
                                selection->remove (&view);
-                               commit = true;
                        }
                } else {
                        selection->add (&view);
-                       commit = false;
                }
                break;
 
        case Selection::Add:
                if (!selection->selected (&view)) {
                        selection->add (&view);
-                       commit = true;
                }
                break;
 
        case Selection::Set:
-               if (selection->selected (&view) && selection->tracks.size() == 1) {
-                       /* no commit necessary */
-               } else {
-                       
+               if (selection->selected (&view) && selection->tracks.size() > 1) {
+
                        /* reset track selection if there is only 1 other track
                           selected OR if no_remove is not set (its there to 
                           prevent deselecting a multi-track selection
@@ -199,34 +213,30 @@ Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no
 
                        if (selection->tracks.empty()) {
                                selection->set (&view);
-                               commit = true;
                        } else if (selection->tracks.size() == 1 || !no_remove) {
                                selection->set (&view);
-                               commit = true;
                        }
                }
                break;
                
        case Selection::Extend:
-               commit = extend_selection_to_track (view);
+               extend_selection_to_track (view);
                break;
        }
-
-       return commit;
 }
 
-bool
+void
 Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool no_remove)
 {
        if (!clicked_routeview) {
-               return false;
+               return;
        }
        
        if (!press) {
-               return false;
+               return;
        }
 
-       return set_selected_track (*clicked_routeview, op, no_remove);
+       set_selected_track (*clicked_routeview, op, no_remove);
 }
 
 bool
@@ -386,7 +396,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
                switch (op) {
                case Selection::Toggle:
                        
-                       if (clicked_regionview->get_selected()) {
+                       if (selection->selected (clicked_regionview)) {
                                if (press) {
 
                                        /* whatever was clicked was selected already; do nothing here but allow
@@ -436,7 +446,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
                        break;
                        
                case Selection::Set:
-                       if (!clicked_regionview->get_selected()) {
+                       if (!selection->selected (clicked_regionview)) {
                                selection->set (clicked_regionview);
                                commit = true;
                        } else {
@@ -455,6 +465,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
                list<Selectable*> results;
                nframes_t last_frame;
                nframes_t first_frame;
+               bool same_track = false;
 
                /* 1. find the last selected regionview in the track that was clicked in */
 
@@ -471,63 +482,183 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
                                if ((*x)->region()->first_frame() < first_frame) {
                                        first_frame = (*x)->region()->first_frame();
                                }
+
+                               same_track = true;
                        }
                }
 
-               /* 2. figure out the boundaries for our search for new objects */
+               if (same_track) {
 
-               switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
-               case OverlapNone:
-                       if (last_frame < clicked_regionview->region()->first_frame()) {
-                               first_frame = last_frame;
-                               last_frame = clicked_regionview->region()->last_frame();
-                       } else {
-                               last_frame = first_frame;
-                               first_frame = clicked_regionview->region()->first_frame();
+                       /* 2. figure out the boundaries for our search for new objects */
+                       
+                       switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
+                       case OverlapNone:
+                               if (last_frame < clicked_regionview->region()->first_frame()) {
+                                       first_frame = last_frame;
+                                       last_frame = clicked_regionview->region()->last_frame();
+                               } else {
+                                       last_frame = first_frame;
+                                       first_frame = clicked_regionview->region()->first_frame();
+                               }
+                               break;
+                               
+                       case OverlapExternal:
+                               if (last_frame < clicked_regionview->region()->first_frame()) {
+                                       first_frame = last_frame;
+                                       last_frame = clicked_regionview->region()->last_frame();
+                               } else {
+                                       last_frame = first_frame;
+                                       first_frame = clicked_regionview->region()->first_frame();
+                               }
+                               break;
+                               
+                       case OverlapInternal:
+                               if (last_frame < clicked_regionview->region()->first_frame()) {
+                                       first_frame = last_frame;
+                                       last_frame = clicked_regionview->region()->last_frame();
+                               } else {
+                                       last_frame = first_frame;
+                                       first_frame = clicked_regionview->region()->first_frame();
+                               }
+                               break;
+                               
+                       case OverlapStart:
+                       case OverlapEnd:
+                               /* nothing to do except add clicked region to selection, since it
+                                  overlaps with the existing selection in this track.
+                               */
+                               break;
                        }
-                       break;
 
-               case OverlapExternal:
-                       if (last_frame < clicked_regionview->region()->first_frame()) {
-                               first_frame = last_frame;
-                               last_frame = clicked_regionview->region()->last_frame();
-                       } else {
-                               last_frame = first_frame;
-                               first_frame = clicked_regionview->region()->first_frame();
-                       }
-                       break;
+               } else {
 
-               case OverlapInternal:
-                       if (last_frame < clicked_regionview->region()->first_frame()) {
-                               first_frame = last_frame;
-                               last_frame = clicked_regionview->region()->last_frame();
-                       } else {
-                               last_frame = first_frame;
-                               first_frame = clicked_regionview->region()->first_frame();
+                       /* click in a track that has no regions selected, so extend vertically
+                          to pick out all regions that are defined by the existing selection
+                          plus this one.
+                       */
+                       
+                       
+                       first_frame = entered_regionview->region()->position();
+                       last_frame = entered_regionview->region()->last_frame();
+                       
+                       for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+                               if ((*i)->region()->position() < first_frame) {
+                                       first_frame = (*i)->region()->position();
+                               }
+                               if ((*i)->region()->last_frame() + 1 > last_frame) {
+                                       last_frame = (*i)->region()->last_frame();
+                               }
                        }
-                       break;
+               }
+
+               /* 2. find all the tracks we should select in */
+
+               set<RouteTimeAxisView*> relevant_tracks;
+               set<RouteTimeAxisView*> already_in_selection;
+
+               get_relevant_tracks (relevant_tracks);
+
+               if (relevant_tracks.empty()) {
 
-               case OverlapStart:
-               case OverlapEnd:
-                       /* nothing to do except add clicked region to selection, since it
-                          overlaps with the existing selection in this track.
+                       /* no relevant tracks -> no tracks selected .. thus .. if
+                          the regionview we're in isn't selected (i.e. we're
+                          about to extend to it), then find all tracks between
+                          the this one and any selected ones.
                        */
-                       break;
+
+                       if (!selection->selected (entered_regionview)) {
+
+                               RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&entered_regionview->get_time_axis_view());
+
+                               if (rtv) {
+
+                                       /* add this track to the ones we will search */
+
+                                       relevant_tracks.insert (rtv);
+
+                                       /* find the track closest to this one that
+                                          already a selected region.
+                                       */
+
+                                       RouteTimeAxisView* closest = 0;
+                                       int distance = INT_MAX;
+                                       int key = rtv->route()->order_key ("editor");
+
+                                       for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
+
+                                               RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(&(*x)->get_time_axis_view());
+
+                                               if (artv && artv != rtv) {
+
+                                                       pair<set<RouteTimeAxisView*>::iterator,bool> result;
+
+                                                       result = already_in_selection.insert (artv);
+
+                                                       if (result.second) {
+                                                               /* newly added to already_in_selection */
+                                                       
+
+                                                               int d = artv->route()->order_key ("editor");
+                                                               
+                                                               d -= key;
+                                                               
+                                                               if (abs (d) < distance) {
+                                                                       distance = abs (d);
+                                                                       closest = artv;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       
+                                       if (closest) {
+
+                                               /* now add all tracks between that one and this one */
+                                               
+                                               int okey = closest->route()->order_key ("editor");
+                                               
+                                               if (okey > key) {
+                                                       swap (okey, key);
+                                               }
+                                               
+                                               for (TrackViewList::iterator x = track_views.begin(); x != track_views.end(); ++x) {
+                                                       RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(*x);
+                                                       if (artv && artv != rtv) {
+
+                                                               int k = artv->route()->order_key ("editor");
+
+                                                               if (k >= okey && k <= key) {
+
+                                                                       /* in range but don't add it if
+                                                                          it already has tracks selected.
+                                                                          this avoids odd selection
+                                                                          behaviour that feels wrong.
+                                                                       */
+
+                                                                       if (find (already_in_selection.begin(),
+                                                                                 already_in_selection.end(),
+                                                                                 artv) == already_in_selection.end()) {
+
+                                                                               relevant_tracks.insert (artv);
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
                }
 
-               /* 2. find all selectable objects (regionviews in this case) between that one and the end of the
-                     one that was clicked.
+               /* 3. find all selectable objects (regionviews in this case) between that one and the end of the
+                          one that was clicked.
                */
 
-               set<RouteTimeAxisView*> relevant_tracks;
-               
                get_relevant_tracks (relevant_tracks);
 
                for (set<RouteTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
                        (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
                }
                
-               /* 3. convert to a vector of audio regions */
+               /* 4. convert to a vector of regions */
 
                vector<RegionView*> regions;
                
@@ -549,40 +680,18 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
        return commit;
 }
 
+
 void
 Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> region, Selection::Operation op)
 {
        vector<RegionView*> all_equivalent_regions;
 
-       for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
-               
-               RouteTimeAxisView* tatv;
-               
-               if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
-                       
-                       boost::shared_ptr<Playlist> pl;
-                       vector<boost::shared_ptr<Region> > results;
-                       RegionView* marv;
-                       boost::shared_ptr<Diskstream> ds;
-                       
-                       if ((ds = tatv->get_diskstream()) == 0) {
-                               /* bus */
-                               continue;
-                       }
-                       
-                       if ((pl = (ds->playlist())) != 0) {
-                               pl->get_region_list_equivalent_regions (region, results);
-                       }
-                       
-                       for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
-                               if ((marv = tatv->view()->find_view (*ir)) != 0) {
-                                       all_equivalent_regions.push_back (marv);
-                               }
-                       }
-                       
-               }
+       get_regions_corresponding_to (region, all_equivalent_regions);
+
+       if (all_equivalent_regions.empty()) {
+               return;
        }
-       
+
        begin_reversible_command (_("set selected regions"));
        
        switch (op) {
@@ -655,6 +764,8 @@ Editor::region_selection_changed ()
        for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
                (*i)->set_selected_regionviews (selection->regions);
        }
+       
+       zoomed_to_region = false;
 }
 
 void
@@ -1031,7 +1142,7 @@ Editor::select_range_between ()
        }
 
        set_mouse_mode (MouseRange);
-       selection->set (0, start, end);
+       selection->set ((TimeAxisView*) 0, start, end);
 }
 
 bool
@@ -1077,10 +1188,36 @@ Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
                        break;
                        
                case EditAtMouse:
+                       /* use mouse + selected marker */
+                       if (selection->markers.empty()) {
+                               start = m;
+                               end = session->audible_frame();
+                       } else {
+                               start = selection->markers.front()->position();
+                               end = m;
+                       }
+                       break;
+                       
                case EditAtSelectedMarker:
                        /* use mouse + selected marker */
                        if (selection->markers.empty()) {
-                               return false;
+                               
+                               MessageDialog win (_("No edit range defined"),
+                                                  false,
+                                                  MESSAGE_INFO,
+                                                  BUTTONS_OK);
+
+                               win.set_secondary_text (
+                                       _("the edit point is Selected Marker\nbut there is no selected marker."));
+                               
+
+                               win.set_default_response (RESPONSE_CLOSE);
+                               win.set_position (Gtk::WIN_POS_MOUSE);
+                               win.show_all();
+                               
+                               win.run ();
+                               
+                               return false; // NO RANGE
                        }
                        start = selection->markers.front()->position();
                        end = m;
@@ -1098,3 +1235,9 @@ Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
 
        return true;
 }
+
+void
+Editor::deselect_all ()
+{
+       selection->clear ();
+}
index 831fe3b727deb2a82e1ba75e0f064b270cfad56c..f18392ce38c37dd0299a661f6b47a528efc225e4 100644 (file)
@@ -235,13 +235,14 @@ Editor::mouse_add_new_tempo_event (nframes_t frame)
        BBT_Time requested;
        
        bpm = tempo_dialog.get_bpm ();
+       double nt = tempo_dialog.get_note_type();
        bpm = max (0.01, bpm);
        
        tempo_dialog.get_bbt_time (requested);
        
        begin_reversible_command (_("add tempo mark"));
         XMLNode &before = map.get_state();
-       map.add_tempo (Tempo (bpm), requested);
+       map.add_tempo (Tempo (bpm,nt), requested);
         XMLNode &after = map.get_state();
        session->add_command(new MementoCommand<TempoMap>(map, &before, &after));
        commit_reversible_command ();
@@ -356,13 +357,14 @@ Editor::edit_tempo_section (TempoSection* section)
        }
 
        double bpm = tempo_dialog.get_bpm ();
+       double nt = tempo_dialog.get_note_type ();
        BBT_Time when;
        tempo_dialog.get_bbt_time(when);
        bpm = max (0.01, bpm);
        
        begin_reversible_command (_("replace tempo mark"));
         XMLNode &before = session->tempo_map().get_state();
-       session->tempo_map().replace_tempo (*section, Tempo (bpm));
+       session->tempo_map().replace_tempo (*section, Tempo (bpm,nt));
        session->tempo_map().move_tempo (*section, when);
         XMLNode &after = session->tempo_map().get_state();
        session->add_command (new MementoCommand<TempoMap>(session->tempo_map(), &before, &after));
index df0a73c9652b119f52f218dafe3738cee223b544..015a265a9bd608b13afeaf85f4e48666a92e3f64 100644 (file)
@@ -40,6 +40,7 @@
 #include <ardour/audioregion.h>
 #include <ardour/audio_diskstream.h>
 #include <ardour/stretch.h>
+#include <ardour/pitch.h>
 
 #include "i18n.h"
 
@@ -49,50 +50,88 @@ using namespace sigc;
 using namespace Gtk;
 using namespace Gtkmm2ext;
 
-Editor::TimeStretchDialog::TimeStretchDialog (Editor& e)
-       : ArdourDialog ("time stretch dialog"),
+Editor::TimeFXDialog::TimeFXDialog (Editor& e, bool pitch)
+       : ArdourDialog (X_("time fx dialog")),
          editor (e),
+         pitching (pitch),
+         pitch_octave_adjustment (0.0, 0.0, 4.0, 1, 2.0),
+         pitch_semitone_adjustment (0.0, 0.0, 12.0, 1.0, 4.0),
+         pitch_cent_adjustment (0.0, 0.0, 150.0, 5.0, 15.0),
+         pitch_octave_spinner (pitch_octave_adjustment),
+         pitch_semitone_spinner (pitch_semitone_adjustment),
+         pitch_cent_spinner (pitch_cent_adjustment),
          quick_button (_("Quick but Ugly")),
          antialias_button (_("Skip Anti-aliasing"))
 {
        set_modal (true);
        set_position (Gtk::WIN_POS_MOUSE);
-       set_name (N_("TimeStretchDialog"));
+       set_name (N_("TimeFXDialog"));
 
        WindowTitle title(Glib::get_application_name());
-       title += _("Timestretch");
+       if (pitching) {
+               title += _("Pitch Shift");
+       } else {
+               title += _("Time Stretch");
+       }
        set_title(title.get_string());
 
+       cancel_button = add_button (_("Cancel"), Gtk::RESPONSE_CANCEL);
+
        get_vbox()->set_spacing (5);
-       get_vbox()->set_border_width (5);
-       get_vbox()->pack_start (upper_button_box);
+       get_vbox()->set_border_width (12);
+       get_vbox()->pack_start (upper_button_box, false, false);
        get_vbox()->pack_start (progress_bar);
 
-       upper_button_box.set_homogeneous (true);
-       upper_button_box.set_spacing (5);
-       upper_button_box.set_border_width (5);
-       upper_button_box.pack_start (quick_button, true, true);
-       upper_button_box.pack_start (antialias_button, true, true);
+       if (pitching) {
 
-       action_button = add_button (_("Stretch/Shrink it"), Gtk::RESPONSE_ACCEPT);
-       cancel_button = add_button (_("Cancel"), Gtk::RESPONSE_CANCEL);
+               upper_button_box.set_spacing (5);
+               upper_button_box.set_border_width (5);
+               
+               Gtk::Label* l;
+
+               l = manage (new Label (_("Octaves")));
+               upper_button_box.pack_start (*l, false, false);
+               upper_button_box.pack_start (pitch_octave_spinner, false, false);
 
-       quick_button.set_name (N_("TimeStretchButton"));
-       antialias_button.set_name (N_("TimeStretchButton"));
-       progress_bar.set_name (N_("TimeStretchProgress"));
+               l = manage (new Label (_("Semitones (12TET)")));
+               upper_button_box.pack_start (*l, false, false);
+               upper_button_box.pack_start (pitch_semitone_spinner, false, false);
+
+               l = manage (new Label (_("Cents")));
+               upper_button_box.pack_start (*l, false, false);
+               upper_button_box.pack_start (pitch_cent_spinner, false, false);
+
+               pitch_cent_spinner.set_digits (1);
+
+               add_button (_("Shift"), Gtk::RESPONSE_ACCEPT);
+
+       } else {
+
+               upper_button_box.set_homogeneous (true);
+               upper_button_box.set_spacing (5);
+               upper_button_box.set_border_width (5);
+               upper_button_box.pack_start (quick_button, true, true);
+               upper_button_box.pack_start (antialias_button, true, true);
+       
+               add_button (_("Stretch/Shrink"), Gtk::RESPONSE_ACCEPT);
+       }
+
+       quick_button.set_name (N_("TimeFXButton"));
+       antialias_button.set_name (N_("TimeFXButton"));
+       progress_bar.set_name (N_("TimeFXProgress"));
 
        show_all_children ();
 }
 
 gint
-Editor::TimeStretchDialog::update_progress ()
+Editor::TimeFXDialog::update_progress ()
 {
        progress_bar.set_fraction (request.progress);
        return !request.done;
 }
 
 void
-Editor::TimeStretchDialog::cancel_timestretch_in_progress ()
+Editor::TimeFXDialog::cancel_in_progress ()
 {
        status = -2;
        request.cancel = true;
@@ -100,7 +139,7 @@ Editor::TimeStretchDialog::cancel_timestretch_in_progress ()
 }
 
 gint
-Editor::TimeStretchDialog::delete_timestretch_in_progress (GdkEventAny* ev)
+Editor::TimeFXDialog::delete_in_progress (GdkEventAny* ev)
 {
        status = -2;
        request.cancel = true;
@@ -109,72 +148,121 @@ Editor::TimeStretchDialog::delete_timestretch_in_progress (GdkEventAny* ev)
 }
 
 int
-Editor::run_timestretch (RegionSelection& regions, float fraction)
+Editor::time_stretch (RegionSelection& regions, float fraction)
+{
+       return time_fx (regions, fraction, false);
+}
+
+int
+Editor::pitch_shift (RegionSelection& regions, float fraction)
 {
-       if (current_timestretch == 0) {
-               current_timestretch = new TimeStretchDialog (*this);
+       return time_fx (regions, fraction, true);
+}
+
+int
+Editor::time_fx (RegionSelection& regions, float val, bool pitching)
+{
+       if (current_timefx != 0) {
+               delete current_timefx;
        }
 
-       current_timestretch->progress_bar.set_fraction (0.0f);
+       current_timefx = new TimeFXDialog (*this, pitching);
+
+       current_timefx->progress_bar.set_fraction (0.0f);
 
-       switch (current_timestretch->run ()) {
+       switch (current_timefx->run ()) {
        case RESPONSE_ACCEPT:
                break;
        default:
-               current_timestretch->hide ();
+               current_timefx->hide ();
                return 1;
        }
 
-       current_timestretch->status = 0;
-       current_timestretch->regions = regions;
-       current_timestretch->request.fraction = fraction;
-       current_timestretch->request.quick_seek = current_timestretch->quick_button.get_active();
-       current_timestretch->request.antialias = !current_timestretch->antialias_button.get_active();
-       current_timestretch->request.progress = 0.0f;
-       current_timestretch->request.done = false;
-       current_timestretch->request.cancel = false;
+       current_timefx->status = 0;
+       current_timefx->regions = regions;
+
+       if (pitching) {
+
+               float cents = current_timefx->pitch_octave_adjustment.get_value() * 1200.0;
+               cents += current_timefx->pitch_semitone_adjustment.get_value() * 100.0;
+               cents += current_timefx->pitch_cent_adjustment.get_value();
+
+               if (cents == 0.0) {
+                       // user didn't change anything
+                       current_timefx->hide ();
+                       return 0;
+               }
+
+               // we now have the pitch shift in cents. divide by 1200 to get octaves
+               // then multiply by 2.0 because 1 octave == doubling the frequency
+               
+               cents /= 1200.0;
+               cents /= 2.0;
+
+               // add 1.0 to convert to RB scale
+
+               cents += 1.0;
+
+               current_timefx->request.time_fraction = 1.0;
+               current_timefx->request.pitch_fraction = cents;
+
+       } else {
+
+               current_timefx->request.time_fraction = val;
+               current_timefx->request.pitch_fraction = 1.0;
+
+       }
+
+       current_timefx->request.quick_seek = current_timefx->quick_button.get_active();
+       current_timefx->request.antialias = !current_timefx->antialias_button.get_active();
+       current_timefx->request.progress = 0.0f;
+       current_timefx->request.done = false;
+       current_timefx->request.cancel = false;
        
        /* re-connect the cancel button and delete events */
        
-       current_timestretch->first_cancel.disconnect();
-       current_timestretch->first_delete.disconnect();
+       current_timefx->first_cancel.disconnect();
+       current_timefx->first_delete.disconnect();
        
-       current_timestretch->first_cancel = current_timestretch->cancel_button->signal_clicked().connect 
-               (mem_fun (current_timestretch, &TimeStretchDialog::cancel_timestretch_in_progress));
-       current_timestretch->first_delete = current_timestretch->signal_delete_event().connect 
-               (mem_fun (current_timestretch, &TimeStretchDialog::delete_timestretch_in_progress));
-
-       if (pthread_create_and_store ("timestretch", &current_timestretch->request.thread, 0, timestretch_thread, current_timestretch)) {
-               current_timestretch->hide ();
-               error << _("timestretch cannot be started - thread creation error") << endmsg;
+       current_timefx->first_cancel = current_timefx->cancel_button->signal_clicked().connect 
+               (mem_fun (current_timefx, &TimeFXDialog::cancel_in_progress));
+       current_timefx->first_delete = current_timefx->signal_delete_event().connect 
+               (mem_fun (current_timefx, &TimeFXDialog::delete_in_progress));
+
+       if (pthread_create_and_store ("timefx", &current_timefx->request.thread, 0, timefx_thread, current_timefx)) {
+               current_timefx->hide ();
+               error << _("timefx cannot be started - thread creation error") << endmsg;
                return -1;
        }
 
-       pthread_detach (current_timestretch->request.thread);
+       pthread_detach (current_timefx->request.thread);
 
-       sigc::connection c = Glib::signal_timeout().connect (mem_fun (current_timestretch, &TimeStretchDialog::update_progress), 100);
+       sigc::connection c = Glib::signal_timeout().connect (mem_fun (current_timefx, &TimeFXDialog::update_progress), 100);
 
-       while (!current_timestretch->request.done) {
+       while (!current_timefx->request.done) {
                gtk_main_iteration ();
        }
 
        c.disconnect ();
        
-       current_timestretch->hide ();
-       return current_timestretch->status;
+       current_timefx->hide ();
+       return current_timefx->status;
 }
 
 void
-Editor::do_timestretch (TimeStretchDialog& dialog)
+Editor::do_timefx (TimeFXDialog& dialog)
 {
        Track*    t;
        boost::shared_ptr<Playlist> playlist;
        boost::shared_ptr<Region>   new_region;
-
+       bool in_command = false;
+       
        for (RegionSelection::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ) {
                AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*i);
-               if (!arv)
+
+               if (!arv) {
                        continue;
+               }
 
                boost::shared_ptr<AudioRegion> region (arv->audio_region());
                TimeAxisView* tv = &(arv->get_time_axis_view());
@@ -205,16 +293,28 @@ Editor::do_timestretch (TimeStretchDialog& dialog)
                        return;
                }
 
-               Stretch stretch (*session, dialog.request);
+               Filter* fx;
 
-               if (stretch.run (region)) {
+               if (dialog.pitching) {
+                       fx = new Pitch (*session, dialog.request);
+               } else {
+                       fx = new Stretch (*session, dialog.request);
+               }
+
+               if (fx->run (region)) {
                        dialog.status = -1;
                        dialog.request.done = true;
+                       delete fx;
                        return;
                }
 
-               if (!stretch.results.empty()) {
-                       new_region = stretch.results.front();
+               if (!fx->results.empty()) {
+                       new_region = fx->results.front();
+
+                       if (!in_command) {
+                               begin_reversible_command (dialog.pitching ? _("pitch shift") : _("time stretch"));
+                               in_command = true;
+                       }
 
                        XMLNode &before = playlist->get_state();
                        playlist->replace_region (region, new_region, region->position());
@@ -223,6 +323,11 @@ Editor::do_timestretch (TimeStretchDialog& dialog)
                }
 
                i = tmp;
+               delete fx;
+       }
+
+       if (in_command) {
+               commit_reversible_command ();
        }
 
        dialog.status = 0;
@@ -230,15 +335,15 @@ Editor::do_timestretch (TimeStretchDialog& dialog)
 }
 
 void*
-Editor::timestretch_thread (void *arg)
+Editor::timefx_thread (void *arg)
 {
        PBD::ThreadCreated (pthread_self(), X_("TimeFX"));
 
-       TimeStretchDialog* tsd = static_cast<TimeStretchDialog*>(arg);
+       TimeFXDialog* tsd = static_cast<TimeFXDialog*>(arg);
 
        pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
 
-       tsd->editor.do_timestretch (*tsd);
+       tsd->editor.do_timefx (*tsd);
 
        return 0;
 }
diff --git a/gtk2_ardour/evtest.cc b/gtk2_ardour/evtest.cc
new file mode 100644 (file)
index 0000000..db8d502
--- /dev/null
@@ -0,0 +1,91 @@
+#include <gtkmm.h>
+#include <iostream>
+
+using namespace std;
+
+bool
+print_event (GdkEvent* event)
+{
+       cerr << hex;
+       cerr << "Event: type = " << event->type << ' ';
+
+       switch (event->type) {
+       case GDK_BUTTON_PRESS:
+               cerr << "Button press, button = " 
+                    << event->button.button
+                    << " state "
+                    << event->button.state 
+                    << endl;
+               break;
+
+       case GDK_BUTTON_RELEASE:
+               cerr << "Button release, button = " 
+                    << event->button.button
+                    << " state "
+                    << event->button.state 
+                    << endl;
+               break;
+
+       case GDK_SCROLL:
+               cerr << "Scroll: direction = "
+                    << event->scroll.direction
+                    << " state = "
+                    << event->scroll.state
+                    << endl;
+               break;
+
+       case GDK_KEY_PRESS:
+               cerr << "Key press, keycode = "
+                    << event->key.keyval
+                    << " name " 
+                    << gdk_keyval_name (event->key.keyval)
+                    << " state = "
+                    << event->key.state
+                    << " hw keycode = "
+                    << event->key.hardware_keycode
+                    << " string = "
+                    << (event->key.string ? event->key.string : "not defined")
+                    << endl;
+               break;
+
+       case GDK_KEY_RELEASE:
+               cerr << "Key release, keycode = "
+                    << event->key.keyval
+                    << " name " 
+                    << gdk_keyval_name (event->key.keyval)
+                    << " state = "
+                    << event->key.state
+                    << " hw keycode = "
+                    << event->key.hardware_keycode
+                    << " string = "
+                    << (event->key.string ? event->key.string : "not defined")
+                    << endl;
+               break;
+
+       default:
+               cerr << endl;
+               break;
+       }
+       cerr << dec;
+
+       return false;
+}
+
+int
+main (int argc, char* argv[])
+{
+       Gtk::Main app (&argc, &argv);
+       Gtk::Window window;
+       Gtk::EventBox eventbox;
+       
+       window.add (eventbox);
+       window.set_size_request (250, 250);
+
+       eventbox.signal_event().connect (sigc::ptr_fun (print_event));
+       eventbox.add_events (Gdk::SCROLL_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
+       eventbox.set_flags (Gtk::CAN_FOCUS);
+
+       eventbox.show ();
+       window.show ();
+       app.run();
+}
index cbaee3d6d2bc766843c2c292378a9915b09e41fb..97e545bddd91190bf6757611278693bc9f974aeb 100644 (file)
@@ -24,7 +24,6 @@
 #include <fstream>
 
 #include <samplerate.h>
-
 #include <pbd/convert.h>
 #include <pbd/xml++.h>
 
@@ -40,6 +39,7 @@
 #include <ardour/audiofilesource.h>
 #include <ardour/gdither.h>
 #include <ardour/utils.h>
+#include <ardour/profile.h>
 
 #include "export_dialog.h"
 #include "ardour_ui.h"
@@ -338,8 +338,12 @@ ExportDialog::ExportDialog(PublicEditor& e)
        format_table.set_col_spacings (5);
        format_table.set_row_spacings (5);
 
-       format_table.attach (channel_count_label, 0, 1, 0, 1, FILL, FILL);
-       format_table.attach (channel_count_combo, 1, 2, 0, 1, FILL, FILL);
+       int row = 0;
+
+       format_table.attach (channel_count_label, 0, 1, row, row+1);
+       format_table.attach (channel_count_combo, 1, 2, row, row+1);
+
+       row++;
        
        format_table.attach (header_format_label, 0, 1, 1, 2, FILL, FILL);
        format_table.attach (header_format_combo, 1, 2, 1, 2, FILL, FILL);
@@ -347,21 +351,42 @@ ExportDialog::ExportDialog(PublicEditor& e)
        format_table.attach (bitdepth_format_label, 0, 1, 2, 3, FILL, FILL);
        format_table.attach (bitdepth_format_combo, 1, 2, 2, 3, FILL, FILL);
 
-       format_table.attach (endian_format_label, 0, 1, 3, 4, FILL, FILL);
-       format_table.attach (endian_format_combo, 1, 2, 3, 4, FILL, FILL);
+       format_table.attach (bitdepth_format_label, 0, 1, row, row+1);
+       format_table.attach (bitdepth_format_combo, 1, 2, row, row+1);
+       
+       row++;
+       
+       if (!Profile->get_sae()) {
+               format_table.attach (endian_format_label, 0, 1, row, row+1);
+               format_table.attach (endian_format_combo, 1, 2, row, row+1);
+               row++;
+       }
+
+       format_table.attach (sample_rate_label, 0, 1, row, row+1);
+       format_table.attach (sample_rate_combo, 1, 2, row, row+1);
+
+       row++;
+
+       if (!Profile->get_sae()) {
+               format_table.attach (src_quality_label, 0, 1, row, row+1);
+               format_table.attach (src_quality_combo, 1, 2, row, row+1);
+               row++;
+       }
 
-       format_table.attach (sample_rate_label, 0, 1, 4, 5, FILL, FILL);
-       format_table.attach (sample_rate_combo, 1, 2, 4, 5, FILL, FILL);
+       format_table.attach (dither_type_label, 0, 1, row, row+1);
+       format_table.attach (dither_type_combo, 1, 2, row, row+1);
 
-       format_table.attach (src_quality_label, 0, 1, 5, 6, FILL, FILL);
-       format_table.attach (src_quality_combo, 1, 2, 5, 6, FILL, FILL);
+       row++;
 
-       format_table.attach (dither_type_label, 0, 1, 6, 7, FILL, FILL);
-       format_table.attach (dither_type_combo, 1, 2, 6, 7, FILL, FILL);
+       if (!Profile->get_sae()) {
+               format_table.attach (cue_file_label, 0, 1, row, row+1);
+               format_table.attach (cue_file_combo, 1, 2, row, row+1);
+               row++;
+       
+               format_table.attach (cuefile_only_checkbox, 0, 2, row, row+1);
+       }
 
-       format_table.attach (cue_file_label, 0, 1, 7, 8, FILL, FILL);
-       format_table.attach (cue_file_combo, 1, 2, 7, 8, FILL, FILL);
-       format_table.attach (cuefile_only_checkbox, 0, 2, 8, 9, FILL, FILL);
+       file_entry.set_name ("ExportFileDisplay");
 
        signal_delete_event().connect (mem_fun(*this, &ExportDialog::window_closed));
 
@@ -651,10 +676,9 @@ ExportDialog::export_toc_file (Locations::LocationList& locations, const string&
                return;
        }
        
-    string filepath = path + ".toc";
+       string filepath = path + ".toc";
        ofstream out (filepath.c_str());
        long unsigned int last_end_time = spec.start_frame, last_start_time = spec.start_frame;
-       int numtracks = 0;
        gchar buf[18];
 
        if (!out) {
@@ -669,102 +693,110 @@ ExportDialog::export_toc_file (Locations::LocationList& locations, const string&
        Locations::LocationList temp;
 
        for (i = locations.begin(); i != locations.end(); ++i) {
-         if ((*i)->start() >= spec.start_frame && (*i)->end() <= spec.end_frame && (*i)->is_cd_marker() && !(*i)->is_end()) {
-           temp.push_back (*i);
-           if (!(*i)->is_mark()) {
-             numtracks ++;
-           }
-         }
+               if ((*i)->start() >= spec.start_frame && (*i)->end() <= spec.end_frame && (*i)->is_cd_marker() && !(*i)->is_end()) {
+                       temp.push_back (*i);
+               }
        }
 
-       if (numtracks == 0 ) {
-                   /* the user supplied no track markers.
-                      we now treat the session as one track.*/
-
-                   out << endl << "TRACK AUDIO" << endl;
-                  
-                   out << "COPY" << endl;
-
-                   out << "NO PRE_EMPHASIS" << endl;
-   
-                   /* XXX add session properties for catalog etc.
-                      (so far only the session name is used) */
-                   
-                   out << "CD_TEXT {" << endl << "  LANGUAGE 0 {" << endl << "     TITLE \"" << session->name() << "\"" << endl;
-                   out << "  }" << endl << "}" << endl;
-
-                   out << "FILE \"" << path << "\" ";
-                   out << "00:00:00 " ;
-                   frames_to_cd_frames_string (buf, spec.end_frame - spec.start_frame, session->frame_rate());
-                   out << buf << endl;
-                   out << "START 00:00:00" << endl;
-
-                   last_start_time = spec.start_frame;
-                   last_end_time = spec.end_frame;
-       } 
-
-       if (temp.size()) {
+       if (temp.size() > 0) {
                LocationSortByStart cmp;
                temp.sort (cmp);
+               Location * curr_range = 0;
+               Locations::LocationList::iterator nexti;
 
                for (i = temp.begin(); i != temp.end(); ++i) {
-       
-                     if (!(*i)->is_mark()) {
-                       /*this is a track */
-                       out << endl << "TRACK AUDIO" << endl;
-
-                       if ((*i)->cd_info.find("scms") != (*i)->cd_info.end())  {
-                         out << "NO ";
-                       }
-                       out << "COPY" << endl;
 
-                       if ((*i)->cd_info.find("preemph") != (*i)->cd_info.end())  {
-                         out << "PRE_EMPHASIS" << endl;
-                       } else {
-                         out << "NO PRE_EMPHASIS" << endl;
-                       }
-
-                       if ((*i)->cd_info.find("isrc") != (*i)->cd_info.end())  {
-                         out << "ISRC \"" << (*i)->cd_info["isrc"] << "\"" << endl;
-                       }
+                       if ((*i)->start() >= last_end_time)
+                       {
+                               /* this is a track, defined by a cd range marker or a cd location marker outside of a cd range */
+                               out << endl << "TRACK AUDIO" << endl;
+                               
+                               if ((*i)->cd_info.find("scms") != (*i)->cd_info.end())  {
+                                       out << "NO ";
+                               }
+                               out << "COPY" << endl;
+                               
+                               if ((*i)->cd_info.find("preemph") != (*i)->cd_info.end())  {
+                                       out << "PRE_EMPHASIS" << endl;
+                               } else {
+                                       out << "NO PRE_EMPHASIS" << endl;
+                               }
+                               
+                               if ((*i)->cd_info.find("isrc") != (*i)->cd_info.end())  {
+                                       out << "ISRC \"" << (*i)->cd_info["isrc"] << "\"" << endl;
+                               }
+                               
+                               out << "CD_TEXT {" << endl << "  LANGUAGE 0 {" << endl << "     TITLE \"" << (*i)->name() << "\"" << endl;
+                               if ((*i)->cd_info.find("performer") != (*i)->cd_info.end()) {
+                                       out << "     PERFORMER \"" << (*i)->cd_info["performer"]  << "\"" << endl;
+                               }
+                               if ((*i)->cd_info.find("string_composer") != (*i)->cd_info.end()) {
+                                       out  << "     COMPOSER \"" << (*i)->cd_info["string_composer"] << "\"" << endl;
+                               }
+                               
+                               if ((*i)->cd_info.find("isrc") != (*i)->cd_info.end()) {                          
+                                       out  << "     ISRC \"";
+                                       out << (*i)->cd_info["isrc"].substr(0,2) << "-";
+                                       out << (*i)->cd_info["isrc"].substr(2,3) << "-";
+                                       out << (*i)->cd_info["isrc"].substr(5,2) << "-";
+                                       out << (*i)->cd_info["isrc"].substr(7,5) << "\"" << endl;
+                               }
+                               
+                               out << "  }" << endl << "}" << endl;
+                               
+                               frames_to_cd_frames_string (buf, last_end_time - spec.start_frame, session->frame_rate());
+                               out << "FILE \"" << path << "\" " << buf;
+                               
+                               if ((*i)->is_mark()) {
+                                       // a mark track location needs to look ahead to the next marker's start to determine length
+                                       nexti = i;
+                                       ++nexti;
+                                       if (nexti != temp.end()) {
+                                               frames_to_cd_frames_string (buf, (*nexti)->start() - last_end_time, session->frame_rate());
+                                               out << buf << endl;
+                                               
+                                               frames_to_cd_frames_string (buf, (*i)->start() - last_end_time, session->frame_rate());
+                                               out << "START" << buf << endl;
+                                               
+                                               last_start_time = (*i)->start();
+                                               last_end_time = (*nexti)->start();
+                                       }
+                                       else {
+                                               // this was the last marker, use session end
+                                               frames_to_cd_frames_string (buf, spec.end_frame - last_end_time, session->frame_rate());
+                                               out << buf << endl;
+                                               
+                                               frames_to_cd_frames_string (buf, (*i)->start() - last_end_time, session->frame_rate());
+                                               out << "START" << buf << endl;
+                                               
+                                               last_start_time = (*i)->start();
+                                               last_end_time = spec.end_frame;
+                                       }
 
-                       out << "CD_TEXT {" << endl << "  LANGUAGE 0 {" << endl << "     TITLE \"" << (*i)->name() << "\"" << endl;
-                       if ((*i)->cd_info.find("performer") != (*i)->cd_info.end()) {
-                         out << "     PERFORMER \"" << (*i)->cd_info["performer"]  << "\"" << endl;
-                       }
-                       if ((*i)->cd_info.find("string_composer") != (*i)->cd_info.end()) {
-                         out  << "     COMPOSER \"" << (*i)->cd_info["string_composer"] << "\"" << endl;
+                                       curr_range = 0;
+                               }
+                               else {
+                                       // range
+                                       frames_to_cd_frames_string (buf, (*i)->end() - last_end_time, session->frame_rate());
+                                       out << buf << endl;
+                                       
+                                       frames_to_cd_frames_string (buf, (*i)->start() - last_end_time, session->frame_rate());
+                                       out << "START" << buf << endl;
+                                       
+                                       last_start_time = (*i)->start();
+                                       last_end_time = (*i)->end();
+
+                                       curr_range = (*i);
+                               }
+                               
                        }
-
-                       if ((*i)->cd_info.find("isrc") != (*i)->cd_info.end()) {                          
-                         out  << "     ISRC \"";
-                         out << (*i)->cd_info["isrc"].substr(0,2) << "-";
-                         out << (*i)->cd_info["isrc"].substr(2,3) << "-";
-                         out << (*i)->cd_info["isrc"].substr(5,2) << "-";
-                         out << (*i)->cd_info["isrc"].substr(7,5) << "\"" << endl;
+                       else if ((*i)->is_mark()) 
+                       {
+                               /* this is an index within a track */
+                               
+                               frames_to_cd_frames_string (buf, (*i)->start() - last_start_time, session->frame_rate());
+                               out << "INDEX" << buf << endl;
                        }
-
-                       out << "  }" << endl << "}" << endl;
-
-                       frames_to_cd_frames_string (buf, last_end_time - spec.start_frame, session->frame_rate());
-                       out << "FILE \"" << path << "\" " << buf;
-
-                       frames_to_cd_frames_string (buf, (*i)->end() - last_end_time, session->frame_rate());
-                       out << buf << endl;
-
-                       frames_to_cd_frames_string (buf, (*i)->start() - last_end_time, session->frame_rate());
-                       out << "START" << buf << endl;
-                       
-                       last_start_time = (*i)->start();
-                       last_end_time = (*i)->end();
-                
-
-                     } else  if ((*i)->start() < last_end_time) {
-                       /* this is an index within a track */
-                       
-                       frames_to_cd_frames_string (buf, (*i)->start() - last_start_time, session->frame_rate());
-                       out << "INDEX" << buf << endl;
-                     }
                }
        }
        
@@ -809,7 +841,7 @@ ExportDialog::export_cue_file (Locations::LocationList& locations, const string&
                  out << "FILE " << path  << ' ' << (header_format_combo.get_active_text()) << endl;
        }
 
-       if (numtracks == 0) {
+       if (false && numtracks == 0) {
                    /* the user has supplied no track markers.
                       the entire export is treated as one track. 
                    */
@@ -840,58 +872,78 @@ ExportDialog::export_cue_file (Locations::LocationList& locations, const string&
        if (temp.size()) {
                LocationSortByStart cmp;
                temp.sort (cmp);
+               Location * curr_range = 0;
+               Locations::LocationList::iterator nexti;
 
                for ( i = temp.begin(); i != temp.end(); ++i) {
 
-                   if (!(*i)->is_mark() && ((*i)->start() >= last_track_end)) {
-                     /* this is a track and it doesn't start inside another one*/
-                     
-                     tracknum++;
-                     indexnum = 0;
-                     out << endl << "TRACK " << tracknum << " AUDIO" << endl;
-                     out << "FLAGS " ;
-                     
-                     if ((*i)->cd_info.find("scms") != (*i)->cd_info.end())  {
-                       out << "SCMS ";
-                     } else {
-                       out << "DCP ";
-                     }
-                     
-                     if ((*i)->cd_info.find("preemph") != (*i)->cd_info.end())  {
-                       out << "PRE";
-                     }
-                     out << endl;
-                     
-                     if ((*i)->cd_info.find("isrc") != (*i)->cd_info.end())  {
-                       out << "ISRC " << (*i)->cd_info["isrc"] << endl;
-                       
-                     }
-                     if ((*i)->name() != "") {
-                       out << "TITLE \"" << (*i)->name() << "\"" << endl;
-                     }       
-                     
-                     if ((*i)->cd_info.find("performer") != (*i)->cd_info.end()) {
-                       out << "PERFORMER \"" <<  (*i)->cd_info["performer"] << "\"" << endl;
-                     }
-                     
-                     if ((*i)->cd_info.find("string_composer") != (*i)->cd_info.end()) {
-                       out << "SONGWRITER \"" << (*i)->cd_info["string_composer"]  << "\"" << endl;
-                     }
-                       snprintf (buf, sizeof(buf), "INDEX %02d", indexnum);
-                       out << buf;
-                       frames_to_cd_frames_string (buf, last_track_end - spec.start_frame, session->frame_rate());
-                       out << buf << endl;
-                       indexnum++;
-                       last_track_end = (*i)->end();
-                   } 
-                   if ((tracknum > 0) && ((*i)->start() < last_track_end)) {
-                     /*this is an index and it lies within a track*/
-                     snprintf (buf, sizeof(buf), "INDEX %02d", indexnum);
-                     out << buf;
-                     frames_to_cd_frames_string (buf,(*i)->start() - spec.start_frame, session->frame_rate());
-                     out << buf << endl;
-                     indexnum++;
-                   }
+                       if ((*i)->start() >= last_track_end)
+                       {
+                               /* this is a track and it doesn't start inside another one*/
+                               
+                               tracknum++;
+                               indexnum = 0;
+                               out << endl << "TRACK " << tracknum << " AUDIO" << endl;
+                               out << "FLAGS " ;
+                               
+                               if ((*i)->cd_info.find("scms") != (*i)->cd_info.end())  {
+                                       out << "SCMS ";
+                               } else {
+                                       out << "DCP ";
+                               }
+                               
+                               if ((*i)->cd_info.find("preemph") != (*i)->cd_info.end())  {
+                                       out << "PRE";
+                               }
+                               out << endl;
+                               
+                               if ((*i)->cd_info.find("isrc") != (*i)->cd_info.end())  {
+                                       out << "ISRC " << (*i)->cd_info["isrc"] << endl;
+                                       
+                               }
+                               if ((*i)->name() != "") {
+                                       out << "TITLE \"" << (*i)->name() << "\"" << endl;
+                               }             
+                               
+                               if ((*i)->cd_info.find("performer") != (*i)->cd_info.end()) {
+                                       out << "PERFORMER \"" <<  (*i)->cd_info["performer"] << "\"" << endl;
+                               }
+                               
+                               if ((*i)->cd_info.find("string_composer") != (*i)->cd_info.end()) {
+                                       out << "SONGWRITER \"" << (*i)->cd_info["string_composer"]  << "\"" << endl;
+                               }
+                               snprintf (buf, sizeof(buf), "INDEX %02d", indexnum);
+                               out << buf;
+                               frames_to_cd_frames_string (buf, last_track_end - spec.start_frame, session->frame_rate());
+                               out << buf << endl;
+                               indexnum++;
+
+                               if ((*i)->is_mark()) {
+                                       // need to find the next start to define the end
+                                       nexti = i;
+                                       ++nexti;
+                                       if (nexti != temp.end()) {
+                                               last_track_end = (*nexti)->start();
+                                       }
+                                       else {
+                                               last_track_end = spec.end_frame;
+                                       }
+                                       curr_range = 0;
+                               }
+                               else {
+                                       last_track_end = (*i)->end();
+                                       curr_range = (*i);
+                               }
+                       } 
+       
+                       if ((tracknum > 0) && ((*i)->start() < last_track_end)) {
+                               /*this is an index and it lies within a track*/
+                               snprintf (buf, sizeof(buf), "INDEX %02d", indexnum);
+                               out << buf;
+                               frames_to_cd_frames_string (buf,(*i)->start() - spec.start_frame, session->frame_rate());
+                               out << buf << endl;
+                               indexnum++;
+                       }
                }
        }
        
@@ -912,12 +964,24 @@ void
 ExportDialog::do_export ()
 {
        string filepath = file_chooser.get_filename();
-       
+
+       if (!ARDOUR_UI::instance()->the_engine().connected()) {
+               MessageDialog msg (*this, 
+                                  _("Not connected to audioengine"),
+                                  true,
+                                  MESSAGE_ERROR,
+                                  BUTTONS_OK);
+               msg.set_secondary_text (_("Ardour cannot export audio when disconnected"));
+               msg.present ();
+               msg.run ();
+               return;
+       }
+               
        if(!is_filepath_valid(filepath)){
                return;
        }
 
-       if (export_cd_markers_allowed) {
+       if (!Profile->get_sae() && export_cd_markers_allowed) {
                if (cue_file_combo.get_active_text () != _("None")) {
                        do_export_cd_markers (file_chooser.get_filename(), cue_file_combo.get_active_text ());
                }
@@ -1303,10 +1367,12 @@ ExportDialog::initSpec(string &filepath)
        spec.format = 0;
 
        spec.format |= sndfile_header_format_from_string (header_format_combo.get_active_text ());
-       
-       if ((spec.format & SF_FORMAT_WAV) == 0) {
-               /* RIFF/WAV specifies endianess */
-               spec.format |= sndfile_endian_format_from_string (endian_format_combo.get_active_text ());
+
+       if (!Profile->get_sae()) {
+               if ((spec.format & SF_FORMAT_WAV) == 0) {
+                       /* RIFF/WAV specifies endianess */
+                       spec.format |= sndfile_endian_format_from_string (endian_format_combo.get_active_text ());
+               }
        }
 
        spec.format |= sndfile_bitdepth_format_from_string (bitdepth_format_combo.get_active_text ());
@@ -1328,17 +1394,21 @@ ExportDialog::initSpec(string &filepath)
                spec.sample_rate = session->frame_rate();
        }
        
-       string src_str = src_quality_combo.get_active_text();
-       if (src_str == _("fastest")) {
-               spec.src_quality = SRC_ZERO_ORDER_HOLD;
-       } else if (src_str == _("linear")) {
-               spec.src_quality = SRC_LINEAR;
-       } else if (src_str == _("better")) {
-               spec.src_quality = SRC_SINC_FASTEST;
-       } else if (src_str == _("intermediate")) {
-               spec.src_quality = SRC_SINC_MEDIUM_QUALITY;
-       } else {
+       if (Profile->get_sae()) {
                spec.src_quality = SRC_SINC_BEST_QUALITY;
+       } else {
+               string src_str = src_quality_combo.get_active_text();
+               if (src_str == _("fastest")) {
+                       spec.src_quality = SRC_ZERO_ORDER_HOLD;
+               } else if (src_str == _("linear")) {
+                       spec.src_quality = SRC_LINEAR;
+               } else if (src_str == _("better")) {
+                       spec.src_quality = SRC_SINC_FASTEST;
+               } else if (src_str == _("intermediate")) {
+                       spec.src_quality = SRC_SINC_MEDIUM_QUALITY;
+               } else {
+                       spec.src_quality = SRC_SINC_BEST_QUALITY;
+               }
        }
 
        string dither_str = dither_type_combo.get_active_text();
index dae51935ec16cbb7b0006fcd978b980c2fafbe80..a20d8b90198fc8d69fb755b6c17f92ff19260903 100644 (file)
@@ -156,12 +156,11 @@ GainMeter::GainMeter (boost::shared_ptr<IO> io, Session& s)
        if ((r = dynamic_cast<Route*> (_io.get())) != 0) {
 
                /* 
-                  if we have a route (ie. we're not the click), 
+                  if we have a non-hidden route (ie. we're not the click or the auditioner), 
                   pack some route-dependent stuff.
                */
 
                gain_display_box.pack_end (peak_display, true, true);
-
                hbox.pack_end (meter_packer, true, true);
 
                using namespace Menu_Helpers;
@@ -218,35 +217,14 @@ GainMeter::GainMeter (boost::shared_ptr<IO> io, Session& s)
        ResetGroupPeakDisplays.connect (mem_fun(*this, &GainMeter::reset_group_peak_display));
 
        UI::instance()->theme_changed.connect (mem_fun(*this, &GainMeter::on_theme_changed));
-
-       fader_centering_box->show();
-       fader_vbox->show();
-       gain_slider->show();
-
-       hbox.show();
-       meter_packer.show();
-       gain_display.show();
-       peak_display.show();
-       gain_display_box.show();
-       fader_box.show();
-       meter_metric_area.show();
-       gain_automation_style_button.show();
-       gain_automation_state_button.show();
-       show();
+       
+       ColorsChanged.connect (mem_fun (*this, &GainMeter::color_handler));
+       //hide_all();
 }
 
 void
 GainMeter::set_width (Width w, int len)
 {
-       switch (w) {
-       case Wide:
-               peak_display.show();
-               break;
-       case Narrow:
-               peak_display.hide();
-               break;
-       }
-
        _width = w;
        setup_meters (len);
 }
@@ -478,15 +456,21 @@ GainMeter::setup_meters (int len)
 
        /* pack them backwards */
 
-       if (_width == Wide) {
-               meter_packer.pack_end (meter_metric_area, false, false);
-               meter_metric_area.show_all ();
-       }
+       meter_packer.pack_end (meter_metric_area, false, false);
+       meter_metric_area.show_all ();
+
+       int b = ARDOUR_UI::config()->canvasvar_MeterColorBase.get();
+       int m = ARDOUR_UI::config()->canvasvar_MeterColorMid.get();
+       int t = ARDOUR_UI::config()->canvasvar_MeterColorTop.get();
+       int c = ARDOUR_UI::config()->canvasvar_MeterColorClip.get();
+
+       //cerr << "GainMeter::setup_meters() called color_changed = " << color_changed << " colors: " << hex << b << " " << m << " " << t << " " << c << endl;//DEBUG
 
        for (int32_t n = nmeters-1; nmeters && n >= 0 ; --n) {
-               if (meters[n].width != width || meters[n].length != len) {
+               if (meters[n].width != width || meters[n].length != len || color_changed) {
                        delete meters[n].meter;
-                       meters[n].meter = new FastMeter ((uint32_t) floor (Config->get_meter_hold()), width, FastMeter::Vertical, len);
+                       meters[n].meter = new FastMeter ((uint32_t) floor (Config->get_meter_hold()), width, FastMeter::Vertical, len, b, m, t, c);
+                       //cerr << "GainMeter::setup_meters() w:l = " << width << ":" << len << endl;//DEBUG
                        meters[n].width = width;
                        meters[n].length = len;
                        meters[n].meter->add_events (Gdk::BUTTON_RELEASE_MASK);
@@ -497,6 +481,7 @@ GainMeter::setup_meters (int len)
                meters[n].meter->show_all ();
                meters[n].packed = true;
        }
+       color_changed = false;
 }      
 
 int
@@ -522,9 +507,9 @@ GainMeter::peak_button_release (GdkEventButton* ev)
 {
        /* reset peak label */
 
-       if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control|Keyboard::Shift)) {
+       if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier|Keyboard::TertiaryModifier)) {
                ResetAllPeakDisplays ();
-       } else if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+       } else if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
                Route* r;
                if ((r = dynamic_cast<Route*> (_io.get())) != 0) {
                        ResetGroupPeakDisplays (r->mix_group());
@@ -733,10 +718,10 @@ GainMeter::meter_press(GdkEventButton* ev)
 
                        if (ev->button == 2) {
 
-                               // ctrl-button2 click is the midi binding click
+                               // Primary-button2 click is the midi binding click
                                // button2-click is "momentary"
                                
-                               if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
+                               if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
                                        wait_for_release = true;
                                        old_meter_point = _route->meter_point ();
                                }
@@ -744,9 +729,9 @@ GainMeter::meter_press(GdkEventButton* ev)
 
                        if (ev->button == 1 || ev->button == 2) {
 
-                               if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
+                               if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
 
-                                       /* ctrl-shift-click applies change to all routes */
+                                       /* Primary+Tertiary-click applies change to all routes */
 
                                        _session.begin_reversible_command (_("meter point change"));
                                         Session::GlobalMeteringStateCommand *cmd = new Session::GlobalMeteringStateCommand (_session, this);
@@ -756,10 +741,10 @@ GainMeter::meter_press(GdkEventButton* ev)
                                        _session.commit_reversible_command ();
                                        
                                        
-                               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+                               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
 
-                                       /* ctrl-click: solo mix group.
-                                          ctrl-button2 is MIDI learn.
+                                       /* Primary-click: solo mix group.
+                                          NOTE: Primary-button2 is MIDI learn.
                                        */
                                        
                                        if (ev->button == 1) {
@@ -985,3 +970,32 @@ GainMeter::gain_automation_state_changed ()
                gain_watching = ARDOUR_UI::RapidScreenUpdate.connect (mem_fun (*this, &GainMeter::effective_gain_display));
        }
 }
+
+void GainMeter::setup_atv_meter (int len)
+{
+       set_no_show_all();
+       regular_meter_width = 3;
+       set_width(Narrow, len);
+       hide_all();
+
+       //cerr << "Config->get_show_track_meters() = " << Config->get_show_track_meters() << endl;//DEBUG
+
+       if (Config->get_show_track_meters()) {
+               meter_packer.show_all();
+               hbox.show();            
+               show();
+       }
+}
+
+void GainMeter::clear_meters ()
+{
+       for (vector<MeterInfo>::iterator i = meters.begin(); i < meters.end(); i++) {
+               (*i).meter->clear();
+       }
+}
+
+void GainMeter::color_handler()
+{
+       color_changed = true;
+       setup_meters();
+}
index 969757313c2e76145a67485e94655e915adac513..669ed50906d54726d27f6d0a63256f514f98e05d 100644 (file)
@@ -75,6 +75,9 @@ class GainMeter : public Gtk::VBox
        void set_meter_strip_name (const char * name);
        void set_fader_name (const char * name);
 
+       void setup_atv_meter (int);
+       void clear_meters ();
+
   private:
 
        friend class MixerStrip;
@@ -129,9 +132,9 @@ class GainMeter : public Gtk::VBox
 
        struct MeterInfo {
            Gtkmm2ext::FastMeter *meter;
-           gint16          width;
-               int                             length;
-           bool            packed;
+           gint16                width;
+               int                   length;
+           bool                  packed;
            
            MeterInfo() { 
                    meter = 0;
@@ -191,6 +194,8 @@ class GainMeter : public Gtk::VBox
 
        void on_theme_changed ();
        bool style_changed;
+       bool color_changed;
+       void color_handler();
 };
 
 #endif /* __ardour_gtk_gain_meter_h__ */
diff --git a/gtk2_ardour/generic_pluginui.cc b/gtk2_ardour/generic_pluginui.cc
new file mode 100644 (file)
index 0000000..7ae3f45
--- /dev/null
@@ -0,0 +1,759 @@
+/*
+    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.
+
+*/
+
+#include <climits>
+#include <cerrno>
+#include <cmath>
+#include <string>
+
+#include <pbd/stl_delete.h>
+#include <pbd/xml++.h>
+#include <pbd/failed_constructor.h>
+
+#include <gtkmm2ext/click_box.h>
+#include <gtkmm2ext/fastmeter.h>
+#include <gtkmm2ext/barcontroller.h>
+#include <gtkmm2ext/utils.h>
+#include <gtkmm2ext/doi.h>
+#include <gtkmm2ext/slider_controller.h>
+
+#include <midi++/manager.h>
+
+#include <ardour/plugin.h>
+#include <ardour/plugin_insert.h>
+#include <ardour/ladspa_plugin.h>
+
+#include <lrdf.h>
+
+#include "ardour_ui.h"
+#include "prompter.h"
+#include "plugin_ui.h"
+#include "utils.h"
+#include "gui_thread.h"
+#include "automation_controller.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+using namespace Gtkmm2ext;
+using namespace Gtk;
+using namespace sigc;
+
+GenericPluginUI::GenericPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrollable)
+       : PlugUIBase (pi),
+         button_table (initial_button_rows, initial_button_cols),
+         output_table (initial_output_rows, initial_output_cols),
+         hAdjustment(0.0, 0.0, 0.0),
+         vAdjustment(0.0, 0.0, 0.0),
+         scroller_view(hAdjustment, vAdjustment),
+         automation_menu (0),
+         is_scrollable(scrollable)
+{
+       set_name ("PluginEditor");
+       set_border_width (10);
+       set_homogeneous (false);
+
+       settings_box.set_homogeneous (false);
+
+       HBox* constraint_hbox = manage (new HBox);
+       HBox* smaller_hbox = manage (new HBox);
+       Label* combo_label = manage (new Label (_("<span size=\"large\">Presets</span>")));
+       combo_label->set_use_markup (true);
+
+       Label* latency_label = manage (new Label (_("<span size=\"large\">Latency</span>")));
+       latency_label->set_use_markup (true);
+
+       smaller_hbox->pack_start (*latency_label, false, false, 10);
+       smaller_hbox->pack_start (latency_gui, false, false, 10);
+       smaller_hbox->pack_start (combo, false, false);
+       smaller_hbox->pack_start (save_button, false, false);
+
+       constraint_hbox->set_spacing (5);
+       constraint_hbox->pack_start (*smaller_hbox, true, false);
+       constraint_hbox->pack_end (bypass_button, false, false);
+
+       settings_box.pack_end (*constraint_hbox, false, false);
+
+       pack_start (settings_box, false, false);
+
+       if ( is_scrollable ) {
+               scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+               scroller.set_name ("PluginEditor");
+               scroller_view.set_name("PluginEditor");
+               scroller_view.add (hpacker);
+               scroller.add (scroller_view);
+               
+               pack_start (scroller, true, true);
+
+       }
+       else {
+               pack_start (hpacker, false, false);
+       }
+
+       pi->ActiveChanged.connect (bind(mem_fun(*this, &GenericPluginUI::processor_active_changed),
+                               boost::weak_ptr<Processor>(pi)));
+       bypass_button.set_active (!pi->active());
+       
+       build ();
+}
+
+GenericPluginUI::~GenericPluginUI ()
+{
+       if (output_controls.size() > 0) {
+               screen_update_connection.disconnect();
+       }
+}
+
+void
+GenericPluginUI::build ()
+
+{
+       guint32 i = 0;
+       guint32 x = 0;
+       Frame* frame;
+       Frame* bt_frame;
+       VBox* box;
+       int output_row, output_col;
+       int button_row, button_col;
+       int output_rows, output_cols;
+       int button_rows, button_cols;
+
+       prefheight = 30;
+       hpacker.set_spacing (10);
+
+       output_rows = initial_output_rows;
+       output_cols = initial_output_cols;
+       button_rows = initial_button_rows;
+       button_cols = initial_button_cols;
+       output_row = 0;
+       button_row = 0;
+       output_col = 0;
+       button_col = 0;
+
+       button_table.set_homogeneous (false);
+       button_table.set_row_spacings (2);
+       button_table.set_col_spacings (2);
+       output_table.set_homogeneous (true);
+       output_table.set_row_spacings (2);
+       output_table.set_col_spacings (2);
+       button_table.set_border_width (5);
+       output_table.set_border_width (5);
+
+       hpacker.set_border_width (10);
+
+       bt_frame = manage (new Frame);
+       bt_frame->set_name ("BaseFrame");
+       bt_frame->add (button_table);
+       hpacker.pack_start(*bt_frame, true, true);
+
+       box = manage (new VBox);
+       box->set_border_width (5);
+       box->set_spacing (1);
+
+       frame = manage (new Frame);
+       frame->set_name ("BaseFrame");
+       frame->set_label (_("Controls"));
+       frame->add (*box);
+       hpacker.pack_start(*frame, true, true);
+
+       /* find all ports. build control elements for all appropriate control ports */
+
+       for (i = 0; i < plugin->parameter_count(); ++i) {
+
+               if (plugin->parameter_is_control (i)) {
+                       
+                       /* Don't show latency control ports */
+
+                       if (plugin->describe_parameter (Parameter(PluginAutomation, i)) == X_("latency")) {
+                               continue;
+                       }
+
+                       ControlUI* cui;
+       
+                       /* if we are scrollable, just use one long column */
+
+                       if (!is_scrollable) {
+                               if (x++ > 7){
+                                       frame = manage (new Frame);
+                                       frame->set_name ("BaseFrame");
+                                       box = manage (new VBox);
+                                       
+                                       box->set_border_width (5);
+                                       box->set_spacing (1);
+
+                                       frame->add (*box);
+                                       hpacker.pack_start(*frame,true,true);
+
+                                       x = 1;
+                               }
+                       }
+
+                       if ((cui = build_control_ui (i, insert->control(Parameter(PluginAutomation, i)))) == 0) {
+                               error << string_compose(_("Plugin Editor: could not build control element for port %1"), i) << endmsg;
+                               continue;
+                       }
+                               
+                       if (cui->control || cui->clickbox || cui->combo) {
+
+                               box->pack_start (*cui, false, false);
+
+                       } else if (cui->button) {
+
+                               if (button_row == button_rows) {
+                                       button_row = 0;
+                                       if (++button_col == button_cols) {
+                                               button_cols += 2;
+                                               button_table.resize (button_rows, button_cols);
+                                       }
+                               }
+
+                               button_table.attach (*cui, button_col, button_col + 1, button_row, button_row+1, 
+                                                    FILL|EXPAND, FILL);
+                               button_row++;
+
+                       } else if (cui->display) {
+
+                               output_table.attach (*cui, output_col, output_col + 1, output_row, output_row+1, 
+                                                    FILL|EXPAND, FILL);
+                               
+                               // TODO: The meters should be divided into multiple rows 
+                               
+                               if (++output_col == output_cols) {
+                                       output_cols ++;
+                                       output_table.resize (output_rows, output_cols);
+                               }
+                               
+                               /* old code, which divides meters into
+                                * columns first, rows later. New code divides into one row
+                                
+                               if (output_row == output_rows) {
+                                       output_row = 0;
+                                       if (++output_col == output_cols) {
+                                               output_cols += 2;
+                                               output_table.resize (output_rows, output_cols);
+                                       }
+                               }
+                               
+                               output_table.attach (*cui, output_col, output_col + 1, output_row, output_row+1, 
+                                                    FILL|EXPAND, FILL);
+                               output_row++;
+                               */
+                       }
+                               
+                       /* HACK: ideally the preferred height would be queried from
+                          the complete hpacker, but I can't seem to get that
+                          information in time, so this is an estimation 
+                       */
+
+                       prefheight += 30;
+
+               } 
+       }
+
+       if (box->children().empty()) {
+               hpacker.remove (*frame);
+       }
+
+       if (button_table.children().empty()) {
+               hpacker.remove (*bt_frame);
+       }
+
+       if (!output_table.children().empty()) {
+               frame = manage (new Frame);
+               frame->set_name ("BaseFrame");
+               frame->add (output_table);
+               hpacker.pack_end (*frame, true, true);
+       }
+
+       output_update ();
+
+       output_table.show_all ();
+       button_table.show_all ();
+}
+
+GenericPluginUI::ControlUI::ControlUI ()
+       : automate_button (X_("")) // force creation of a label 
+{
+       automate_button.set_name ("PluginAutomateButton");
+       ARDOUR_UI::instance()->tooltips().set_tip (automate_button, _("Automation control"));
+
+       /* XXX translators: use a string here that will be at least as long
+          as the longest automation label (see ::automation_state_changed()
+          below). be sure to include a descender.
+       */
+
+       set_size_request_to_display_given_text (*automate_button.get_child(), _("Mgnual"), 5, 5);
+
+       ignore_change = 0;
+       display = 0;
+       button = 0;
+       clickbox = 0;
+       meterinfo = 0;
+}
+
+GenericPluginUI::ControlUI::~ControlUI() 
+{
+       if (meterinfo) {
+               delete meterinfo->meter;
+               delete meterinfo;
+       }
+}
+
+void
+GenericPluginUI::automation_state_changed (ControlUI* cui)
+{
+       /* update button label */
+
+       // don't lock to avoid deadlock because we're triggered by
+       // AutomationControl::Changed() while the automation lock is taken
+       switch (insert->get_parameter_automation_state (cui->parameter(), false)
+                       & (Off|Play|Touch|Write)) {
+       case Off:
+               cui->automate_button.set_label (_("Manual"));
+               break;
+       case Play:
+               cui->automate_button.set_label (_("Play"));
+               break;
+       case Write:
+               cui->automate_button.set_label (_("Write"));
+               break;
+       case Touch:
+               cui->automate_button.set_label (_("Touch"));
+               break;
+       default:
+               cui->automate_button.set_label (_("???"));
+               break;
+       }
+}
+
+
+static void integer_printer (char buf[32], Adjustment &adj, void *arg)
+{
+       snprintf (buf, 32, "%.0f", adj.get_value());
+}
+
+void
+GenericPluginUI::print_parameter (char *buf, uint32_t len, uint32_t param)
+{
+       plugin->print_parameter (param, buf, len);
+}
+
+GenericPluginUI::ControlUI*
+GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<AutomationControl> mcontrol)
+{
+       ControlUI* control_ui = NULL;
+       if (!mcontrol)
+               return control_ui;
+
+       Plugin::ParameterDescriptor desc;
+
+       plugin->get_parameter_descriptor (port_index, desc);
+
+       control_ui = manage (new ControlUI ());
+       control_ui->combo = 0;
+       control_ui->combo_map = 0;
+       control_ui->control = mcontrol;
+       control_ui->update_pending = false;
+       control_ui->label.set_text (desc.label);
+       control_ui->label.set_alignment (0.0, 0.5);
+       control_ui->label.set_name ("PluginParameterLabel");
+
+       control_ui->set_spacing (5);
+
+       Gtk::Requisition req (control_ui->automate_button.size_request());
+
+       if (plugin->parameter_is_input (port_index)) {
+
+               boost::shared_ptr<LadspaPlugin> lp;
+
+               if ((lp = boost::dynamic_pointer_cast<LadspaPlugin>(plugin)) != 0) {
+                       
+                       // FIXME: not all plugins have a numeric unique ID
+                       uint32_t id = atol (lp->unique_id().c_str());
+                       lrdf_defaults* defaults = lrdf_get_scale_values(id, port_index);
+                       
+                       if (defaults && defaults->count > 0)    {
+                               
+                               control_ui->combo = new Gtk::ComboBoxText;
+                               //control_ui->combo->set_value_in_list(true, false);
+                               set_popdown_strings (*control_ui->combo, setup_scale_values(port_index, control_ui));
+                               control_ui->combo->signal_changed().connect (bind (mem_fun(*this, &GenericPluginUI::control_combo_changed), control_ui));
+                               mcontrol->Changed.connect (bind (mem_fun (*this, &GenericPluginUI::parameter_changed), control_ui));
+                               control_ui->pack_start(control_ui->label, true, true);
+                               control_ui->pack_start(*control_ui->combo, false, true);
+                               
+                               update_control_display(control_ui);
+                               
+                               lrdf_free_setting_values(defaults);
+                               return control_ui;
+                       }
+               }
+                       
+               if (desc.toggled) {
+
+                       /* Build a button */
+               
+                       control_ui->button = manage (new ToggleButton ());
+                       control_ui->button->set_name ("PluginEditorButton");
+                       control_ui->button->set_size_request (20, 20);
+
+                       control_ui->pack_start (control_ui->label, true, true);
+                       control_ui->pack_start (*control_ui->button, false, true);
+                       control_ui->pack_start (control_ui->automate_button, false, false);
+
+                       control_ui->button->signal_clicked().connect (bind (mem_fun(*this, &GenericPluginUI::control_port_toggled), control_ui));
+               
+                       if(plugin->get_parameter (port_index) == 1){
+                               control_ui->button->set_active(true);
+                       }
+
+                       return control_ui;
+               }
+
+               /* create the controller */
+       
+               control_ui->controller = AutomationController::create(insert, mcontrol->list(), mcontrol);
+
+               /* XXX this code is not right yet, because it doesn't handle
+                  the absence of bounds in any sensible fashion.
+               */
+
+#if 0
+               control_ui->controller->adjustment()->set_lower (desc.lower);
+               control_ui->controller->adjustment()->set_upper (desc.upper);
+
+               control_ui->logarithmic = desc.logarithmic;
+               if (control_ui->logarithmic) {
+                       if (control_ui->controller->adjustment()->get_lower() == 0.0) {
+                               control_ui->controller->adjustment()->set_lower (control_ui->controller->adjustment()->get_upper()/10000);
+                       }
+                       control_ui->controller->adjustment()->set_upper (log(control_ui->controller->adjustment()->get_upper()));
+                       control_ui->controller->adjustment()->set_lower (log(control_ui->controller->adjustment()->get_lower()));
+               }
+               
+       
+               float delta = desc.upper - desc.lower;
+
+               control_ui->controller->adjustment()->set_page_size (delta/100.0);
+               control_ui->controller->adjustment()->set_step_increment (desc.step);
+               control_ui->controller->adjustment()->set_page_increment (desc.largestep);
+#endif
+
+               if (desc.integer_step) {
+                       control_ui->clickbox = new ClickBox (control_ui->controller->adjustment(), "PluginUIClickBox");
+                       Gtkmm2ext::set_size_request_to_display_given_text (*control_ui->clickbox, "g9999999", 2, 2);
+                       control_ui->clickbox->set_print_func (integer_printer, 0);
+               } else {
+                       //sigc::slot<void,char*,uint32_t> pslot = sigc::bind (mem_fun(*this, &GenericPluginUI::print_parameter), (uint32_t) port_index);
+
+                       control_ui->controller->set_size_request (200, req.height);
+                       control_ui->controller->set_name (X_("PluginSlider"));
+                       control_ui->controller->set_style (BarController::LeftToRight);
+                       control_ui->controller->set_use_parent (true);
+
+                       control_ui->controller->StartGesture.connect (bind (mem_fun(*this, &GenericPluginUI::start_touch), control_ui));
+                       control_ui->controller->StopGesture.connect (bind (mem_fun(*this, &GenericPluginUI::stop_touch), control_ui));
+                       
+               }
+
+               if (control_ui->logarithmic) {
+                       control_ui->controller->adjustment()->set_value(log(plugin->get_parameter(port_index)));
+               } else{
+                       control_ui->controller->adjustment()->set_value(plugin->get_parameter(port_index));
+               }
+
+               /* XXX memory leak: SliderController not destroyed by ControlUI
+                  destructor, and manage() reports object hierarchy
+                  ambiguity.
+               */
+
+               control_ui->pack_start (control_ui->label, true, true);
+               if (desc.integer_step) {
+                       control_ui->pack_start (*control_ui->clickbox, false, false);
+               } else {
+                       control_ui->pack_start (*control_ui->controller, false, false);
+               }
+
+               control_ui->pack_start (control_ui->automate_button, false, false);
+               control_ui->automate_button.signal_clicked().connect (bind (mem_fun(*this, &GenericPluginUI::astate_clicked), control_ui, (uint32_t) port_index));
+
+               automation_state_changed (control_ui);
+
+               mcontrol->Changed.connect (bind (mem_fun (*this, &GenericPluginUI::parameter_changed), control_ui));
+               mcontrol->list()->automation_state_changed.connect 
+                       (bind (mem_fun(*this, &GenericPluginUI::automation_state_changed), control_ui));
+
+       } else if (plugin->parameter_is_output (port_index)) {
+
+               control_ui->display = manage (new EventBox);
+               control_ui->display->set_name ("ParameterValueDisplay");
+
+               control_ui->display_label = manage (new Label);
+
+               control_ui->display_label->set_name ("ParameterValueDisplay");
+
+               control_ui->display->add (*control_ui->display_label);
+               Gtkmm2ext::set_size_request_to_display_given_text (*control_ui->display, "-99,99", 2, 2);
+
+               control_ui->display->show_all ();
+
+               /* set up a meter */
+               /* TODO: only make a meter if the port is Hinted for it */
+
+               MeterInfo * info = new MeterInfo(port_index);
+               control_ui->meterinfo = info;
+               
+               info->meter = new FastMeter (5, 5, FastMeter::Vertical);
+
+               info->min_unbound = desc.min_unbound;
+               info->max_unbound = desc.max_unbound;
+
+               info->min = desc.lower;
+               info->max = desc.upper;
+
+               control_ui->vbox = manage (new VBox);
+               control_ui->hbox = manage (new HBox);
+               
+               control_ui->label.set_angle(90);
+               control_ui->hbox->pack_start (control_ui->label, false, false);
+               control_ui->hbox->pack_start (*info->meter, false, false);
+
+               control_ui->vbox->pack_start (*control_ui->hbox, false, false);
+               
+               control_ui->vbox->pack_start (*control_ui->display, false, false);
+
+               control_ui->pack_start (*control_ui->vbox);
+
+               control_ui->meterinfo->meter->show_all();
+               control_ui->meterinfo->packed = true;
+               
+               output_controls.push_back (control_ui);
+       }
+       
+       mcontrol->Changed.connect (bind (mem_fun (*this, &GenericPluginUI::parameter_changed), control_ui));
+       
+       return control_ui;
+}
+
+void
+GenericPluginUI::start_touch (GenericPluginUI::ControlUI* cui)
+{
+       cui->control->list()->start_touch ();
+}
+
+void
+GenericPluginUI::stop_touch (GenericPluginUI::ControlUI* cui)
+{
+       cui->control->list()->stop_touch ();
+}
+
+void
+GenericPluginUI::astate_clicked (ControlUI* cui, uint32_t port)
+{
+       using namespace Menu_Helpers;
+
+       if (automation_menu == 0) {
+               automation_menu = manage (new Menu);
+               automation_menu->set_name ("ArdourContextMenu");
+       } 
+
+       MenuList& items (automation_menu->items());
+
+       items.clear ();
+       items.push_back (MenuElem (_("Manual"), 
+                                  bind (mem_fun(*this, &GenericPluginUI::set_automation_state), (AutoState) Off, cui)));
+       items.push_back (MenuElem (_("Play"),
+                                  bind (mem_fun(*this, &GenericPluginUI::set_automation_state), (AutoState) Play, cui)));
+       items.push_back (MenuElem (_("Write"),
+                                  bind (mem_fun(*this, &GenericPluginUI::set_automation_state), (AutoState) Write, cui)));
+       items.push_back (MenuElem (_("Touch"),
+                                  bind (mem_fun(*this, &GenericPluginUI::set_automation_state), (AutoState) Touch, cui)));
+
+       automation_menu->popup (1, gtk_get_current_event_time());
+}
+
+void
+GenericPluginUI::set_automation_state (AutoState state, ControlUI* cui)
+{
+       insert->set_parameter_automation_state (cui->parameter(), state);
+}
+
+void
+GenericPluginUI::parameter_changed (ControlUI* cui)
+{
+       if (!cui->update_pending) {
+               cui->update_pending = true;
+               Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &GenericPluginUI::update_control_display), cui));
+       }
+}
+
+void
+GenericPluginUI::update_control_display (ControlUI* cui)       
+{
+       /* XXX how do we handle logarithmic stuff here ? */
+       
+       cui->update_pending = false;
+
+       float val = cui->control->get_value();
+
+       cui->ignore_change++;
+       if (cui->combo) {
+               std::map<string,float>::iterator it;
+               for (it = cui->combo_map->begin(); it != cui->combo_map->end(); ++it) {
+                       if (it->second == val) {
+                               cui->combo->set_active_text(it->first);
+                               break;
+                       }
+               }
+       } else if (cui->button) {
+
+               if (val > 0.5) {
+                       cui->button->set_active (true);
+               } else {
+                       cui->button->set_active (false);
+               }
+       }
+
+       cui->controller->display_effective_value();
+
+
+       /*} else {
+               if (cui->logarithmic) {
+                       val = log(val);
+               }
+               if (val != cui->adjustment->get_value()) {
+                       cui->adjustment->set_value (val);
+               }
+       }*/
+       cui->ignore_change--;
+}
+
+void
+GenericPluginUI::control_port_toggled (ControlUI* cui)
+{
+       if (!cui->ignore_change) {
+               insert->set_parameter (cui->parameter(), cui->button->get_active());
+       }
+}
+
+void
+GenericPluginUI::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->parameter(), mapping[value]);
+       }
+
+}
+
+void
+GenericPluginUI::processor_active_changed (boost::weak_ptr<Processor> weak_processor)
+{
+       ENSURE_GUI_THREAD(bind (mem_fun(*this, &GenericPluginUI::processor_active_changed), weak_processor));
+       
+       boost::shared_ptr<Processor> processor = weak_processor.lock();
+
+       bypass_button.set_active (!processor || !processor->active());
+}
+
+bool
+GenericPluginUI::start_updating (GdkEventAny* ignored)
+{
+       if (output_controls.size() > 0 ) {
+               screen_update_connection.disconnect();
+               screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect 
+                       (mem_fun(*this, &GenericPluginUI::output_update));
+       }
+       return false;
+}
+
+bool
+GenericPluginUI::stop_updating (GdkEventAny* ignored)
+{
+       if (output_controls.size() > 0 ) {
+               screen_update_connection.disconnect();
+       }
+       return false;
+}
+
+void
+GenericPluginUI::output_update ()
+{
+       for (vector<ControlUI*>::iterator i = output_controls.begin(); i != output_controls.end(); ++i) {
+               float val = plugin->get_parameter ((*i)->parameter().id());
+               char buf[32];
+               snprintf (buf, sizeof(buf), "%.2f", val);
+               (*i)->display_label->set_text (buf);
+
+               /* autoscaling for the meter */
+               if ((*i)->meterinfo && (*i)->meterinfo->packed) {
+                       
+                       if (val < (*i)->meterinfo->min) {
+                               if ((*i)->meterinfo->min_unbound)
+                                       (*i)->meterinfo->min = val;
+                               else
+                                       val = (*i)->meterinfo->min;
+                       }
+
+                       if (val > (*i)->meterinfo->max) {
+                               if ((*i)->meterinfo->max_unbound)
+                                       (*i)->meterinfo->max = val;
+                               else
+                                       val = (*i)->meterinfo->max;
+                       }
+                       
+                       if ((*i)->meterinfo->max > (*i)->meterinfo->min ) {
+                               float lval = (val - (*i)->meterinfo->min) / ((*i)->meterinfo->max - (*i)->meterinfo->min) ;
+                               (*i)->meterinfo->meter->set (lval );
+                       }
+               }
+       }
+}
+
+vector<string> 
+GenericPluginUI::setup_scale_values(guint32 port_index, ControlUI* cui)
+{
+       vector<string> enums;
+       boost::shared_ptr<LadspaPlugin> lp = boost::dynamic_pointer_cast<LadspaPlugin> (plugin);
+
+       cui->combo_map = new std::map<string, float>;
+                       
+       // FIXME: not all plugins have a numeric unique ID
+       uint32_t id = atol (lp->unique_id().c_str());
+       lrdf_defaults* defaults = lrdf_get_scale_values(id, port_index);
+
+       if (defaults)   {
+               for (uint32_t i = 0; i < defaults->count; ++i) {
+                       enums.push_back(defaults->items[i].label);
+                       pair<string, float> newpair;
+                       newpair.first = defaults->items[i].label;
+                       newpair.second = defaults->items[i].value;
+                       cui->combo_map->insert(newpair);
+               }
+
+               lrdf_free_setting_values(defaults);
+       }
+
+       return enums;
+}
+
diff --git a/gtk2_ardour/icons/sae.png b/gtk2_ardour/icons/sae.png
new file mode 100644 (file)
index 0000000..69af495
Binary files /dev/null and b/gtk2_ardour/icons/sae.png differ
index e6eaffefcbfd0e1fc6807410802991bd9a027418..83b301d92eac0cb80a8c44c12ae57a3b4c86b932 100644 (file)
@@ -43,10 +43,19 @@ guint Keyboard::delete_but = 3;
 guint Keyboard::delete_mod = GDK_SHIFT_MASK;
 guint Keyboard::snap_mod = GDK_MOD3_MASK;
 
-uint32_t Keyboard::Control = GDK_CONTROL_MASK;
-uint32_t Keyboard::Shift = GDK_SHIFT_MASK;
-uint32_t Keyboard::Alt = GDK_MOD1_MASK;
-uint32_t Keyboard::Meta;
+#ifdef GTKOSX
+guint Keyboard::PrimaryModifier = GDK_MOD1_MASK;   // Command
+guint Keyboard::SecondaryModifier = GDK_MOD5_MASK; // Alt/Option
+guint Keyboard::TertiaryModifier = GDK_SHIFT_MASK; // Shift
+guint Keyboard::CopyModifier = GDK_MOD5_MASK;      // Alt/Option
+guint Keyboard::RangeSelectModifier = GDK_SHIFT_MASK;   
+#else
+guint Keyboard::PrimaryModifier = GDK_CONTROL_MASK; // Control
+guint Keyboard::SecondaryModifier = GDK_MOD1_MASK;  // Alt/Option
+guint Keyboard::TertiaryModifier = GDK_SHIFT_MASK;  // Shift
+guint Keyboard::CopyModifier = GDK_CONTROL_MASK;    
+guint Keyboard::RangeSelectModifier = GDK_SHIFT_MASK;   
+#endif
 
 Keyboard*    Keyboard::_the_keyboard = 0;
 Gtk::Window* Keyboard::current_window = 0;
@@ -82,17 +91,11 @@ Keyboard::Keyboard ()
 
        RelevantModifierKeyMask = (GdkModifierType) gtk_accelerator_get_default_mod_mask ();
 
-       /* figure out Meta */
-
-       uint32_t possible_meta[] = { GDK_MOD2_MASK, GDK_MOD3_MASK, GDK_MOD4_MASK, GDK_MOD5_MASK, 0};
-       int i;
-
-       for (i = 0; possible_meta[i]; ++i) {
-               if (!(RelevantModifierKeyMask & possible_meta[i])) {
-                       break;
-               }
-       }
-       Meta = possible_meta[i];
+       RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | PrimaryModifier);
+       RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | SecondaryModifier);
+       RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | TertiaryModifier);
+       RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | CopyModifier);
+       RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | RangeSelectModifier);
 
        snooper_id = gtk_key_snooper_install (_snooper, (gpointer) this);
 
@@ -164,6 +167,12 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event)
 {
        uint32_t keyval;
 
+#if 0
+       cerr << "snoop widget " << widget << " key " << event->keyval << " type: " << event->type 
+            << " state " << std::hex << event->state << std::dec
+            << endl;
+#endif
+
 #if KBD_DEBUG
        if (debug_keyboard) {
                cerr << "snoop widget " << widget << " key " << event->keyval << " type: " << event->type 
@@ -186,7 +195,7 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event)
                if (find (state.begin(), state.end(), keyval) == state.end()) {
                        state.push_back (keyval);
                        sort (state.begin(), state.end());
-               }
+               } 
 
        } else if (event->type == GDK_KEY_RELEASE) {
 
@@ -199,7 +208,7 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event)
 
        }
 
-       if (event->type == GDK_KEY_RELEASE && event->keyval == GDK_w && modifier_state_equals (event->state, Control)) {
+       if (event->type == GDK_KEY_RELEASE && event->keyval == GDK_w && modifier_state_equals (event->state, PrimaryModifier)) {
                if (current_window) {
                        current_window->hide ();
                        current_window = 0;
@@ -279,15 +288,11 @@ Keyboard::set_delete_modifier (guint mod)
 }
 
 void
-Keyboard::set_meta_modifier (guint mod)
+Keyboard::set_modifier (uint32_t newval, uint32_t& var)
 {
-       /* we don't include Meta in the RelevantModifierKeyMask because its not used
-          in the same way as snap_mod, delete_mod etc. the only reason we allow it to be
-          set at all is that X Window has no convention for the keyboard modifier
-          that Meta should use. Some Linux distributions bind NumLock to Mod2, which
-          is our default Meta modifier, and this causes severe problems.
-       */
-       Meta = mod;
+       RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~var);
+       var = newval;
+       RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | var);
 }
 
 void
@@ -346,9 +351,9 @@ Keyboard::selection_type (guint state)
 {
        /* note that there is no modifier for "Add" */
 
-       if (modifier_state_equals (state, Shift)) {
+       if (modifier_state_equals (state, RangeSelectModifier)) {
                return Selection::Extend;
-       } else if (modifier_state_equals (state, Control)) {
+       } else if (modifier_state_equals (state, PrimaryModifier)) {
                return Selection::Toggle;
        } else {
                return Selection::Set;
index fb22f2eca9d9bef1868ee893ba876f483948d489..7c163245e75688993772385beb4fc0182732bd09 100644 (file)
@@ -46,10 +46,27 @@ class Keyboard : public sigc::trackable, PBD::Stateful
        typedef vector<uint32_t> State;
        typedef uint32_t ModifierMask;
 
-       static uint32_t Control;
-       static uint32_t Shift;
-       static uint32_t Alt;
-       static uint32_t Meta;
+       static uint32_t PrimaryModifier;
+       static uint32_t SecondaryModifier;
+       static uint32_t TertiaryModifier;
+       static uint32_t CopyModifier;
+       static uint32_t RangeSelectModifier;
+
+       static void set_primary_modifier (uint32_t newval) {
+               set_modifier (newval, PrimaryModifier);
+       }
+       static void set_secondary_modifier (uint32_t newval) {
+               set_modifier (newval, SecondaryModifier);
+       }
+       static void set_tertiary_modifier (uint32_t newval) {
+               set_modifier (newval, TertiaryModifier);
+       }
+       static void set_copy_modifier (uint32_t newval) {
+               set_modifier (newval, CopyModifier);
+       }
+       static void set_range_select_modifier (uint32_t newval) {
+               set_modifier (newval, RangeSelectModifier);
+       }
 
        bool key_is_down (uint32_t keyval);
 
@@ -69,8 +86,6 @@ class Keyboard : public sigc::trackable, PBD::Stateful
 
        static bool no_modifiers_active (guint state);
 
-       static void set_meta_modifier (guint);
-
        static void set_snap_modifier (guint);
        static ModifierMask snap_modifier () { return ModifierMask (snap_mod); }
 
@@ -110,6 +125,8 @@ class Keyboard : public sigc::trackable, PBD::Stateful
        static gint _snooper (GtkWidget*, GdkEventKey*, gpointer);
        gint snooper (GtkWidget*, GdkEventKey*);
 
+       static void set_modifier (uint32_t newval, uint32_t& variable);
+
        static bool _some_magic_widget_has_focus;
 };
 
index f3ae77865d1db9b653b72bb4aca9adeb0307fa2a..4f378d2dbc71151c0152e74f03a1da309372de8b 100644 (file)
@@ -1,11 +1,14 @@
 #include <map>
 
+#include <ardour/profile.h>
+
 #include <gtkmm/stock.h>
 #include <gtkmm/accelkey.h>
 #include <gtkmm/accelmap.h>
 #include <gtkmm/uimanager.h>
 
 #include <pbd/strsplit.h>
+#include <pbd/replace_all.h>
 
 #include "actions.h"
 #include "keyboard.h"
@@ -16,6 +19,7 @@
 using namespace std;
 using namespace Gtk;
 using namespace Gdk;
+using namespace PBD;
 
 KeyEditor::KeyEditor ()
        : ArdourDialog (_("Keybinding Editor"), false)
@@ -31,11 +35,11 @@ KeyEditor::KeyEditor ()
        view.set_headers_visible (true);
        view.get_selection()->set_mode (SELECTION_SINGLE);
        view.set_reorderable (false);
-       view.set_size_request (300,200);
+       view.set_size_request (500,300);
        view.set_enable_search (false);
        view.set_rules_hint (true);
        view.set_name (X_("KeyEditorTree"));
-
+       
        view.get_selection()->signal_changed().connect (mem_fun (*this, &KeyEditor::action_selected));
        
        scroller.add (view);
@@ -78,7 +82,7 @@ KeyEditor::on_key_press_event (GdkEventKey* ev)
 bool
 KeyEditor::on_key_release_event (GdkEventKey* ev)
 {
-       if (!can_bind || ev->state != last_state) {
+       if (ARDOUR::Profile->get_sae() || !can_bind || ev->state != last_state) {
                return false;
        }
 
@@ -137,7 +141,7 @@ KeyEditor::populate ()
        model->clear ();
 
        for (l = labels.begin(), k = keys.begin(), p = paths.begin(); l != labels.end(); ++k, ++p, ++l) {
-               
+
                TreeModel::Row row;
                vector<string> parts;
                
@@ -178,7 +182,16 @@ KeyEditor::populate ()
                if (*k == ActionManager::unbound_string) {
                        row[columns.binding] = string();
                } else {
+
+#ifdef GTKOSX
+                       string label = (*k);
+                       replace_all (label, "<Mod5>", _("Command-"));
+                       replace_all (label, "<Alt>", _("Option-"));
+                       replace_all (label, "<Shift>", _("Shift-"));
+                       row[columns.binding] = label;
+#else          
                        row[columns.binding] = (*k);
+#endif
                }
        }
 }
diff --git a/gtk2_ardour/ladspa_pluginui.cc b/gtk2_ardour/ladspa_pluginui.cc
deleted file mode 100644 (file)
index b5d7838..0000000
+++ /dev/null
@@ -1,753 +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.
-
-*/
-
-#include <climits>
-#include <cerrno>
-#include <cmath>
-#include <string>
-
-#include <pbd/stl_delete.h>
-#include <pbd/xml++.h>
-#include <pbd/failed_constructor.h>
-
-#include <gtkmm2ext/click_box.h>
-#include <gtkmm2ext/fastmeter.h>
-#include <gtkmm2ext/barcontroller.h>
-#include <gtkmm2ext/utils.h>
-#include <gtkmm2ext/doi.h>
-#include <gtkmm2ext/slider_controller.h>
-
-#include <midi++/manager.h>
-
-#include <ardour/plugin.h>
-#include <ardour/plugin_insert.h>
-#include <ardour/ladspa_plugin.h>
-
-#include <lrdf.h>
-
-#include "ardour_ui.h"
-#include "prompter.h"
-#include "plugin_ui.h"
-#include "utils.h"
-#include "gui_thread.h"
-#include "automation_controller.h"
-
-#include "i18n.h"
-
-using namespace std;
-using namespace ARDOUR;
-using namespace PBD;
-using namespace Gtkmm2ext;
-using namespace Gtk;
-using namespace sigc;
-
-LadspaPluginUI::LadspaPluginUI (boost::shared_ptr<PluginInsert> pi, nframes64_t sample_rate, nframes64_t period_size, bool scrollable)
-       : PlugUIBase (pi, sample_rate, period_size),
-         button_table (initial_button_rows, initial_button_cols),
-         output_table (initial_output_rows, initial_output_cols),
-         hAdjustment(0.0, 0.0, 0.0),
-         vAdjustment(0.0, 0.0, 0.0),
-         scroller_view(hAdjustment, vAdjustment),
-         automation_menu (0),
-         is_scrollable(scrollable)
-{
-       set_name ("PluginEditor");
-       set_border_width (10);
-       set_homogeneous (false);
-
-       settings_box.set_homogeneous (false);
-
-       HBox* constraint_hbox = manage (new HBox);
-       HBox* smaller_hbox = manage (new HBox);
-       Label* combo_label = manage (new Label (_("<span size=\"large\">Presets</span>")));
-       combo_label->set_use_markup (true);
-
-       Label* latency_label = manage (new Label (_("<span size=\"large\">Latency</span>")));
-       latency_label->set_use_markup (true);
-
-       smaller_hbox->pack_start (*latency_label, false, false, 10);
-       smaller_hbox->pack_start (latency_gui, false, false, 10);
-       smaller_hbox->pack_start (combo, false, false);
-       smaller_hbox->pack_start (save_button, false, false);
-
-       constraint_hbox->set_spacing (5);
-       constraint_hbox->pack_start (*smaller_hbox, true, false);
-       constraint_hbox->pack_end (bypass_button, false, false);
-
-       settings_box.pack_end (*constraint_hbox, false, false);
-
-       pack_start (settings_box, false, false);
-
-       if ( is_scrollable ) {
-               scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
-               scroller.set_name ("PluginEditor");
-               scroller_view.set_name("PluginEditor");
-               scroller_view.add (hpacker);
-               scroller.add (scroller_view);
-               
-               pack_start (scroller, true, true);
-
-       }
-       else {
-               pack_start (hpacker, false, false);
-       }
-
-       pi->ActiveChanged.connect (bind(mem_fun(*this, &LadspaPluginUI::processor_active_changed),
-                               boost::weak_ptr<Processor>(pi)));
-       bypass_button.set_active (!pi->active());
-       
-       build ();
-}
-
-LadspaPluginUI::~LadspaPluginUI ()
-{
-       if (output_controls.size() > 0) {
-               screen_update_connection.disconnect();
-       }
-}
-
-void
-LadspaPluginUI::build ()
-
-{
-       guint32 i = 0;
-       guint32 x = 0;
-       Frame* frame;
-       Frame* bt_frame;
-       VBox* box;
-       int output_row, output_col;
-       int button_row, button_col;
-       int output_rows, output_cols;
-       int button_rows, button_cols;
-
-       prefheight = 30;
-       hpacker.set_spacing (10);
-
-       output_rows = initial_output_rows;
-       output_cols = initial_output_cols;
-       button_rows = initial_button_rows;
-       button_cols = initial_button_cols;
-       output_row = 0;
-       button_row = 0;
-       output_col = 0;
-       button_col = 0;
-
-       button_table.set_homogeneous (false);
-       button_table.set_row_spacings (2);
-       button_table.set_col_spacings (2);
-       output_table.set_homogeneous (true);
-       output_table.set_row_spacings (2);
-       output_table.set_col_spacings (2);
-       button_table.set_border_width (5);
-       output_table.set_border_width (5);
-
-       hpacker.set_border_width (10);
-
-       bt_frame = manage (new Frame);
-       bt_frame->set_name ("BaseFrame");
-       bt_frame->add (button_table);
-       hpacker.pack_start(*bt_frame, true, true);
-
-       box = manage (new VBox);
-       box->set_border_width (5);
-       box->set_spacing (1);
-
-       frame = manage (new Frame);
-       frame->set_name ("BaseFrame");
-       frame->set_label (_("Controls"));
-       frame->add (*box);
-       hpacker.pack_start(*frame, true, true);
-
-       /* find all ports. build control elements for all appropriate control ports */
-
-       for (i = 0; i < plugin->parameter_count(); ++i) {
-
-               if (plugin->parameter_is_control (i)) {
-                       
-                       /* Don't show latency control ports */
-
-                       if (plugin->describe_parameter (Parameter(PluginAutomation, i)) == X_("latency")) {
-                               continue;
-                       }
-
-                       ControlUI* cui;
-       
-                       /* if we are scrollable, just use one long column */
-
-                       if (!is_scrollable) {
-                               if (x++ > 7){
-                                       frame = manage (new Frame);
-                                       frame->set_name ("BaseFrame");
-                                       box = manage (new VBox);
-                                       
-                                       box->set_border_width (5);
-                                       box->set_spacing (1);
-
-                                       frame->add (*box);
-                                       hpacker.pack_start(*frame,true,true);
-
-                                       x = 1;
-                               }
-                       }
-
-                       if ((cui = build_control_ui (i, insert->control(Parameter(PluginAutomation, i)))) == 0) {
-                               error << string_compose(_("Plugin Editor: could not build control element for port %1"), i) << endmsg;
-                               continue;
-                       }
-                               
-                       if (cui->control || cui->clickbox || cui->combo) {
-
-                               box->pack_start (*cui, false, false);
-
-                       } else if (cui->button) {
-
-                               if (button_row == button_rows) {
-                                       button_row = 0;
-                                       if (++button_col == button_cols) {
-                                               button_cols += 2;
-                                               button_table.resize (button_rows, button_cols);
-                                       }
-                               }
-
-                               button_table.attach (*cui, button_col, button_col + 1, button_row, button_row+1, 
-                                                    FILL|EXPAND, FILL);
-                               button_row++;
-
-                       } else if (cui->display) {
-
-                               output_table.attach (*cui, output_col, output_col + 1, output_row, output_row+1, 
-                                                    FILL|EXPAND, FILL);
-                               
-                               // TODO: The meters should be divided into multiple rows 
-                               
-                               if (++output_col == output_cols) {
-                                       output_cols ++;
-                                       output_table.resize (output_rows, output_cols);
-                               }
-                               
-                               /* old code, which divides meters into
-                                * columns first, rows later. New code divides into one row
-                                
-                               if (output_row == output_rows) {
-                                       output_row = 0;
-                                       if (++output_col == output_cols) {
-                                               output_cols += 2;
-                                               output_table.resize (output_rows, output_cols);
-                                       }
-                               }
-                               
-                               output_table.attach (*cui, output_col, output_col + 1, output_row, output_row+1, 
-                                                    FILL|EXPAND, FILL);
-                               output_row++;
-                               */
-                       }
-                               
-                       /* HACK: ideally the preferred height would be queried from
-                          the complete hpacker, but I can't seem to get that
-                          information in time, so this is an estimation 
-                       */
-
-                       prefheight += 30;
-
-               } 
-       }
-
-       if (box->children().empty()) {
-               hpacker.remove (*frame);
-       }
-
-       if (button_table.children().empty()) {
-               hpacker.remove (*bt_frame);
-       }
-
-       if (!output_table.children().empty()) {
-               frame = manage (new Frame);
-               frame->set_name ("BaseFrame");
-               frame->add (output_table);
-               hpacker.pack_end (*frame, true, true);
-       }
-
-       output_update ();
-
-       output_table.show_all ();
-       button_table.show_all ();
-}
-
-LadspaPluginUI::ControlUI::ControlUI ()
-       : automate_button (X_("")) // force creation of a label 
-{
-       automate_button.set_name ("PluginAutomateButton");
-       ARDOUR_UI::instance()->tooltips().set_tip (automate_button, _("Automation control"));
-
-       /* XXX translators: use a string here that will be at least as long
-          as the longest automation label (see ::automation_state_changed()
-          below). be sure to include a descender.
-       */
-
-       set_size_request_to_display_given_text (*automate_button.get_child(), _("Mgnual"), 5, 5);
-
-       ignore_change = 0;
-       display = 0;
-       button = 0;
-       clickbox = 0;
-       meterinfo = 0;
-}
-
-LadspaPluginUI::ControlUI::~ControlUI() 
-{
-       if (meterinfo) {
-               delete meterinfo->meter;
-               delete meterinfo;
-       }
-}
-
-void
-LadspaPluginUI::automation_state_changed (ControlUI* cui)
-{
-       /* update button label */
-
-       // don't lock to avoid deadlock because we're triggered by
-       // AutomationControl::Changed() while the automation lock is taken
-       switch (insert->get_parameter_automation_state (cui->parameter(), false)
-                       & (Off|Play|Touch|Write)) {
-       case Off:
-               cui->automate_button.set_label (_("Manual"));
-               break;
-       case Play:
-               cui->automate_button.set_label (_("Play"));
-               break;
-       case Write:
-               cui->automate_button.set_label (_("Write"));
-               break;
-       case Touch:
-               cui->automate_button.set_label (_("Touch"));
-               break;
-       default:
-               cui->automate_button.set_label (_("???"));
-               break;
-       }
-}
-
-
-static void integer_printer (char buf[32], Adjustment &adj, void *arg)
-{
-       snprintf (buf, 32, "%.0f", adj.get_value());
-}
-
-void
-LadspaPluginUI::print_parameter (char *buf, uint32_t len, uint32_t param)
-{
-       plugin->print_parameter (param, buf, len);
-}
-
-LadspaPluginUI::ControlUI*
-LadspaPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<AutomationControl> mcontrol)
-{
-       ControlUI* control_ui = NULL;
-       if (!mcontrol)
-               return control_ui;
-
-       Plugin::ParameterDescriptor desc;
-
-       plugin->get_parameter_descriptor (port_index, desc);
-
-       control_ui = manage (new ControlUI ());
-       control_ui->combo = 0;
-       control_ui->combo_map = 0;
-       control_ui->control = mcontrol;
-       control_ui->update_pending = false;
-       control_ui->label.set_text (desc.label);
-       control_ui->label.set_alignment (0.0, 0.5);
-       control_ui->label.set_name ("PluginParameterLabel");
-
-       control_ui->set_spacing (5);
-
-       Gtk::Requisition req (control_ui->automate_button.size_request());
-
-       if (plugin->parameter_is_input (port_index)) {
-
-               boost::shared_ptr<LadspaPlugin> lp;
-
-               if ((lp = boost::dynamic_pointer_cast<LadspaPlugin>(plugin)) != 0) {
-                       
-                       lrdf_defaults* defaults = lrdf_get_scale_values(lp->unique_id(), port_index);
-                       
-                       if (defaults && defaults->count > 0)    {
-                               
-                               control_ui->combo = new Gtk::ComboBoxText;
-                               //control_ui->combo->set_value_in_list(true, false);
-                               set_popdown_strings (*control_ui->combo, setup_scale_values(port_index, control_ui));
-                               control_ui->combo->signal_changed().connect (bind (mem_fun(*this, &LadspaPluginUI::control_combo_changed), control_ui));
-                               mcontrol->Changed.connect (bind (mem_fun (*this, &LadspaPluginUI::parameter_changed), control_ui));
-                               control_ui->pack_start(control_ui->label, true, true);
-                               control_ui->pack_start(*control_ui->combo, false, true);
-                               
-                               update_control_display(control_ui);
-                               
-                               lrdf_free_setting_values(defaults);
-                               return control_ui;
-                       }
-               }
-                       
-               if (desc.toggled) {
-
-                       /* Build a button */
-               
-                       control_ui->button = manage (new ToggleButton ());
-                       control_ui->button->set_name ("PluginEditorButton");
-                       control_ui->button->set_size_request (20, 20);
-
-                       control_ui->pack_start (control_ui->label, true, true);
-                       control_ui->pack_start (*control_ui->button, false, true);
-                       control_ui->pack_start (control_ui->automate_button, false, false);
-
-                       control_ui->button->signal_clicked().connect (bind (mem_fun(*this, &LadspaPluginUI::control_port_toggled), control_ui));
-               
-                       if(plugin->get_parameter (port_index) == 1){
-                               control_ui->button->set_active(true);
-                       }
-
-                       return control_ui;
-               }
-
-               /* create the controller */
-       
-               control_ui->controller = AutomationController::create(insert, mcontrol->list(), mcontrol);
-
-               /* XXX this code is not right yet, because it doesn't handle
-                  the absence of bounds in any sensible fashion.
-               */
-
-#if 0
-               control_ui->controller->adjustment()->set_lower (desc.lower);
-               control_ui->controller->adjustment()->set_upper (desc.upper);
-
-               control_ui->logarithmic = desc.logarithmic;
-               if (control_ui->logarithmic) {
-                       if (control_ui->controller->adjustment()->get_lower() == 0.0) {
-                               control_ui->controller->adjustment()->set_lower (control_ui->controller->adjustment()->get_upper()/10000);
-                       }
-                       control_ui->controller->adjustment()->set_upper (log(control_ui->controller->adjustment()->get_upper()));
-                       control_ui->controller->adjustment()->set_lower (log(control_ui->controller->adjustment()->get_lower()));
-               }
-               
-       
-               float delta = desc.upper - desc.lower;
-
-               control_ui->controller->adjustment()->set_page_size (delta/100.0);
-               control_ui->controller->adjustment()->set_step_increment (desc.step);
-               control_ui->controller->adjustment()->set_page_increment (desc.largestep);
-#endif
-
-               if (desc.integer_step) {
-                       control_ui->clickbox = new ClickBox (control_ui->controller->adjustment(), "PluginUIClickBox");
-                       Gtkmm2ext::set_size_request_to_display_given_text (*control_ui->clickbox, "g9999999", 2, 2);
-                       control_ui->clickbox->set_print_func (integer_printer, 0);
-               } else {
-                       //sigc::slot<void,char*,uint32_t> pslot = sigc::bind (mem_fun(*this, &LadspaPluginUI::print_parameter), (uint32_t) port_index);
-
-                       control_ui->controller->set_size_request (200, req.height);
-                       control_ui->controller->set_name (X_("PluginSlider"));
-                       control_ui->controller->set_style (BarController::LeftToRight);
-                       control_ui->controller->set_use_parent (true);
-
-                       control_ui->controller->StartGesture.connect (bind (mem_fun(*this, &LadspaPluginUI::start_touch), control_ui));
-                       control_ui->controller->StopGesture.connect (bind (mem_fun(*this, &LadspaPluginUI::stop_touch), control_ui));
-                       
-               }
-
-               if (control_ui->logarithmic) {
-                       control_ui->controller->adjustment()->set_value(log(plugin->get_parameter(port_index)));
-               } else{
-                       control_ui->controller->adjustment()->set_value(plugin->get_parameter(port_index));
-               }
-
-               /* XXX memory leak: SliderController not destroyed by ControlUI
-                  destructor, and manage() reports object hierarchy
-                  ambiguity.
-               */
-
-               control_ui->pack_start (control_ui->label, true, true);
-               if (desc.integer_step) {
-                       control_ui->pack_start (*control_ui->clickbox, false, false);
-               } else {
-                       control_ui->pack_start (*control_ui->controller, false, false);
-               }
-
-               control_ui->pack_start (control_ui->automate_button, false, false);
-               control_ui->automate_button.signal_clicked().connect (bind (mem_fun(*this, &LadspaPluginUI::astate_clicked), control_ui, (uint32_t) port_index));
-
-               automation_state_changed (control_ui);
-
-               mcontrol->Changed.connect (bind (mem_fun (*this, &LadspaPluginUI::parameter_changed), control_ui));
-               mcontrol->list()->automation_state_changed.connect 
-                       (bind (mem_fun(*this, &LadspaPluginUI::automation_state_changed), control_ui));
-
-       } else if (plugin->parameter_is_output (port_index)) {
-
-               control_ui->display = manage (new EventBox);
-               control_ui->display->set_name ("ParameterValueDisplay");
-
-               control_ui->display_label = manage (new Label);
-
-               control_ui->display_label->set_name ("ParameterValueDisplay");
-
-               control_ui->display->add (*control_ui->display_label);
-               Gtkmm2ext::set_size_request_to_display_given_text (*control_ui->display, "-99,99", 2, 2);
-
-               control_ui->display->show_all ();
-
-               /* set up a meter */
-               /* TODO: only make a meter if the port is Hinted for it */
-
-               MeterInfo * info = new MeterInfo(port_index);
-               control_ui->meterinfo = info;
-               
-               info->meter = new FastMeter (5, 5, FastMeter::Vertical);
-
-               info->min_unbound = desc.min_unbound;
-               info->max_unbound = desc.max_unbound;
-
-               info->min = desc.lower;
-               info->max = desc.upper;
-
-               control_ui->vbox = manage (new VBox);
-               control_ui->hbox = manage (new HBox);
-               
-               control_ui->label.set_angle(90);
-               control_ui->hbox->pack_start (control_ui->label, false, false);
-               control_ui->hbox->pack_start (*info->meter, false, false);
-
-               control_ui->vbox->pack_start (*control_ui->hbox, false, false);
-               
-               control_ui->vbox->pack_start (*control_ui->display, false, false);
-
-               control_ui->pack_start (*control_ui->vbox);
-
-               control_ui->meterinfo->meter->show_all();
-               control_ui->meterinfo->packed = true;
-               
-               output_controls.push_back (control_ui);
-       }
-       
-       mcontrol->Changed.connect (bind (mem_fun (*this, &LadspaPluginUI::parameter_changed), control_ui));
-       
-       return control_ui;
-}
-
-void
-LadspaPluginUI::start_touch (LadspaPluginUI::ControlUI* cui)
-{
-       cui->control->list()->start_touch ();
-}
-
-void
-LadspaPluginUI::stop_touch (LadspaPluginUI::ControlUI* cui)
-{
-       cui->control->list()->stop_touch ();
-}
-
-void
-LadspaPluginUI::astate_clicked (ControlUI* cui, uint32_t port)
-{
-       using namespace Menu_Helpers;
-
-       if (automation_menu == 0) {
-               automation_menu = manage (new Menu);
-               automation_menu->set_name ("ArdourContextMenu");
-       } 
-
-       MenuList& items (automation_menu->items());
-
-       items.clear ();
-       items.push_back (MenuElem (_("Manual"), 
-                                  bind (mem_fun(*this, &LadspaPluginUI::set_automation_state), (AutoState) Off, cui)));
-       items.push_back (MenuElem (_("Play"),
-                                  bind (mem_fun(*this, &LadspaPluginUI::set_automation_state), (AutoState) Play, cui)));
-       items.push_back (MenuElem (_("Write"),
-                                  bind (mem_fun(*this, &LadspaPluginUI::set_automation_state), (AutoState) Write, cui)));
-       items.push_back (MenuElem (_("Touch"),
-                                  bind (mem_fun(*this, &LadspaPluginUI::set_automation_state), (AutoState) Touch, cui)));
-
-       automation_menu->popup (1, gtk_get_current_event_time());
-}
-
-void
-LadspaPluginUI::set_automation_state (AutoState state, ControlUI* cui)
-{
-       insert->set_parameter_automation_state (cui->parameter(), state);
-}
-
-void
-LadspaPluginUI::parameter_changed (ControlUI* cui)
-{
-       if (!cui->update_pending) {
-               cui->update_pending = true;
-               Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &LadspaPluginUI::update_control_display), cui));
-       }
-}
-
-void
-LadspaPluginUI::update_control_display (ControlUI* cui)        
-{
-       /* XXX how do we handle logarithmic stuff here ? */
-       
-       cui->update_pending = false;
-
-       float val = cui->control->get_value();
-
-       cui->ignore_change++;
-       if (cui->combo) {
-               std::map<string,float>::iterator it;
-               for (it = cui->combo_map->begin(); it != cui->combo_map->end(); ++it) {
-                       if (it->second == val) {
-                               cui->combo->set_active_text(it->first);
-                               break;
-                       }
-               }
-       } else if (cui->button) {
-
-               if (val > 0.5) {
-                       cui->button->set_active (true);
-               } else {
-                       cui->button->set_active (false);
-               }
-       }
-
-       cui->controller->display_effective_value();
-
-
-       /*} else {
-               if (cui->logarithmic) {
-                       val = log(val);
-               }
-               if (val != cui->adjustment->get_value()) {
-                       cui->adjustment->set_value (val);
-               }
-       }*/
-       cui->ignore_change--;
-}
-
-void
-LadspaPluginUI::control_port_toggled (ControlUI* cui)
-{
-       if (!cui->ignore_change) {
-               insert->set_parameter (cui->parameter(), cui->button->get_active());
-       }
-}
-
-void
-LadspaPluginUI::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->parameter(), mapping[value]);
-       }
-
-}
-
-void
-LadspaPluginUI::processor_active_changed (boost::weak_ptr<Processor> weak_processor)
-{
-       ENSURE_GUI_THREAD(bind (mem_fun(*this, &LadspaPluginUI::processor_active_changed), weak_processor));
-       
-       boost::shared_ptr<Processor> processor = weak_processor.lock();
-
-       bypass_button.set_active (!processor || !processor->active());
-}
-
-bool
-LadspaPluginUI::start_updating (GdkEventAny* ignored)
-{
-       if (output_controls.size() > 0 ) {
-               screen_update_connection.disconnect();
-               screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect 
-                       (mem_fun(*this, &LadspaPluginUI::output_update));
-       }
-       return false;
-}
-
-bool
-LadspaPluginUI::stop_updating (GdkEventAny* ignored)
-{
-       if (output_controls.size() > 0 ) {
-               screen_update_connection.disconnect();
-       }
-       return false;
-}
-
-void
-LadspaPluginUI::output_update ()
-{
-       for (vector<ControlUI*>::iterator i = output_controls.begin(); i != output_controls.end(); ++i) {
-               float val = plugin->get_parameter ((*i)->parameter().id());
-               char buf[32];
-               snprintf (buf, sizeof(buf), "%.2f", val);
-               (*i)->display_label->set_text (buf);
-
-               /* autoscaling for the meter */
-               if ((*i)->meterinfo && (*i)->meterinfo->packed) {
-                       
-                       if (val < (*i)->meterinfo->min) {
-                               if ((*i)->meterinfo->min_unbound)
-                                       (*i)->meterinfo->min = val;
-                               else
-                                       val = (*i)->meterinfo->min;
-                       }
-
-                       if (val > (*i)->meterinfo->max) {
-                               if ((*i)->meterinfo->max_unbound)
-                                       (*i)->meterinfo->max = val;
-                               else
-                                       val = (*i)->meterinfo->max;
-                       }
-                       
-                       if ((*i)->meterinfo->max > (*i)->meterinfo->min ) {
-                               float lval = (val - (*i)->meterinfo->min) / ((*i)->meterinfo->max - (*i)->meterinfo->min) ;
-                               (*i)->meterinfo->meter->set (lval );
-                       }
-               }
-       }
-}
-
-vector<string> 
-LadspaPluginUI::setup_scale_values(guint32 port_index, ControlUI* cui)
-{
-       vector<string> enums;
-       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);
-       if (defaults)   {
-               for (uint32_t i = 0; i < defaults->count; ++i) {
-                       enums.push_back(defaults->items[i].label);
-                       pair<string, float> newpair;
-                       newpair.first = defaults->items[i].label;
-                       newpair.second = defaults->items[i].value;
-                       cui->combo_map->insert(newpair);
-               }
-
-               lrdf_free_setting_values(defaults);
-       }
-
-       return enums;
-}
-
index f4f8e8952fca5aaa320acf0233bf9d75fa64df3d..cc1df9add5ecb79cf8276164678c3f21888079c5 100644 (file)
@@ -25,6 +25,7 @@
 #include <ardour/session.h>
 #include <ardour/session_route.h>
 #include <ardour/dB.h>
+#include <ardour/meter.h>
 
 #include <gtkmm2ext/utils.h>
 #include <gtkmm2ext/fastmeter.h>
@@ -43,7 +44,6 @@
 
 #include <ardour/session.h>
 #include <ardour/route.h>
-#include <ardour/meter.h>
 
 #include "i18n.h"
 
@@ -146,12 +146,10 @@ LevelMeter::setup_meters (int len)
        if ((r = dynamic_cast<Route*> (_io.get())) != 0) {
 
                switch (r->meter_point()) {
+               case MeterPreFader:
                case MeterInput:
                        nmeters = r->n_inputs().n_total();
                        break;
-               case MeterPreFader:
-                       nmeters = r->pre_fader_streams().n_total();
-                       break;
                case MeterPostFader:
                        nmeters = r->n_outputs().n_total();
                        break;
index b9dea243134ddaaea1c95ca975a629be8344bb5d..6e0be908ae9eaebd8c439c72f64af0b2e0544940 100644 (file)
@@ -678,6 +678,11 @@ LocationUI::~LocationUI()
 {
 }
 
+void LocationUI::on_show()
+{
+       ArdourDialog::on_show();
+       refresh_location_list();
+}
 
 
 gint LocationUI::do_location_remove (ARDOUR::Location *loc)
@@ -856,6 +861,9 @@ LocationUI::refresh_location_list ()
        ENSURE_GUI_THREAD(mem_fun(*this, &LocationUI::refresh_location_list));
        using namespace Box_Helpers;
 
+       // this is just too expensive to do when window is not shown
+       if (!is_visible()) return;
+
        BoxList & loc_children = location_rows.children();
        BoxList & range_children = range_rows.children();
 
index 51daa6814da418332b646992ee017e24b16a769a..de435b999fc8fbe9e25b693fd0df20e4ecca41ee 100644 (file)
@@ -145,6 +145,8 @@ class LocationUI : public ArdourDialog
 
        void set_session (ARDOUR::Session *);
 
+       void on_show();
+
   private:
        ARDOUR::LocationStack* locations;
         
index 32e14420ff519ce8129c6d33d68b326261e85d3e..e9c8613224ae33eb23244eb6a482b7b18daa4213 100644 (file)
@@ -23,6 +23,7 @@
 #include <gtkmm/settings.h>
 
 #include <pbd/error.h>
+#include <pbd/file_utils.h>
 #include <pbd/textreceiver.h>
 #include <pbd/failed_constructor.h>
 #include <pbd/pthread_utils.h>
 #include <ardour/ardour.h>
 #include <ardour/audioengine.h>
 #include <ardour/session_utils.h>
+#include <ardour/filesystem_paths.h>
 
 #include <gtkmm/main.h>
 #include <gtkmm2ext/popup.h>
 #include <gtkmm2ext/utils.h>
 
-#include "svn_revision.h"
+#include "../svn_revision.h"
 #include "version.h"
+#include "utils.h"
 #include "ardour_ui.h"
 #include "opts.h"
 #include "enums.h"
@@ -222,6 +225,63 @@ fixup_bundle_environment ()
 
 #endif
 
+static void
+setup_keybindings (ARDOUR_UI* ui)
+{
+       Glib::ustring path;
+
+       if (keybindings_path.empty()) {
+               keybindings_path = "ardour";
+       }
+
+       std::string kbpath;
+       
+       if (keybindings_path.find (".bindings") == string::npos) {
+
+               // just a style name - allow user to
+               // specify the layout type. 
+               
+               char* layout;
+               
+               if ((layout = getenv ("ARDOUR_KEYBOARD_LAYOUT")) != 0) {
+                       keybindings_path += '-';
+                       keybindings_path += layout;
+               }
+
+               keybindings_path += ".bindings";
+       } 
+
+       
+       // XXX timbyr - we need a portable test for "is-absolute" here 
+       
+       if (keybindings_path[0] != '/' && keybindings_path[0] != '.') {
+
+               /* not absolute - look in the usual places */
+               
+               sys::path key_bindings_file;
+
+               find_file_in_search_path (ardour_search_path() + system_config_search_path(),
+                               keybindings_path, key_bindings_file);
+
+               path = key_bindings_file.to_string();
+
+               if (path.empty()) {
+                       warning << string_compose (_("Key bindings file \"%1\" not found. Default bindings used instead"), 
+                                       keybindings_path) << endmsg;
+               }
+
+       } else {
+
+               // absolute path from user - use it as is
+
+               path = keybindings_path;
+       }
+
+       if (!path.empty()) {
+               ui->set_keybindings_path (path);
+       }
+}
+
 #ifdef VST_SUPPORT
 /* this is called from the entry point of a wine-compiled
    executable that is linked against gtk2_ardour built
@@ -310,9 +370,7 @@ int main (int argc, char *argv[])
                }
        }
 
-       if (!keybindings_path.empty()) {
-               ui->set_keybindings_path (keybindings_path);
-       }
+       setup_keybindings (ui);
 
        ui->run (text_receiver);
        ui = 0;
index de2ceb554e45c6be46abbe7259b9efa0683ce8fa..6e37908d1b3b1e01efee1c4b5eb2b070a740d785 100644 (file)
@@ -33,7 +33,7 @@ using namespace ARDOUR;
 Marker::Marker (PublicEditor& ed, ArdourCanvas::Group& parent, guint32 rgba, const string& annotation, 
                Type type, nframes_t frame, bool handle_events)
 
-       : editor (ed), _type(type)
+       : editor (ed), _parent(&parent), _type(type)
 {
        double label_offset = 0;
        bool annotate_left = false;
@@ -273,6 +273,7 @@ Marker::Marker (PublicEditor& ed, ArdourCanvas::Group& parent, guint32 rgba, con
 
 }
 
+
 Marker::~Marker ()
 {
        drop_references ();
@@ -288,6 +289,21 @@ Marker::~Marker ()
        }
 }
 
+void Marker::reparent(ArdourCanvas::Group & parent)
+{
+       group->reparent(parent);
+       _parent = &parent;
+}
+
+void
+Marker::set_line_length (double len)
+{
+       if (line) {
+               line_points->back().set_y (len);
+               line->property_points() = *line_points;
+       }
+}
+
 void
 Marker::add_line (ArdourCanvas::Group* group, double initial_height)
 {
@@ -301,12 +317,13 @@ Marker::add_line (ArdourCanvas::Group* group, double initial_height)
                line->property_width_pixels() = 1;
                line->property_points() = *line_points;
                line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EditPoint.get();
+#if 0
                line->property_first_arrowhead() = TRUE;
                line->property_last_arrowhead() = TRUE;
                line->property_arrow_shape_a() = 11.0;
                line->property_arrow_shape_b() = 0.0;
                line->property_arrow_shape_c() = 9.0;
-
+#endif
                line->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this));
        }
 
@@ -383,6 +400,7 @@ void
 Marker::set_color_rgba (uint32_t color)
 {
        mark->property_fill_color_rgba() = color;
+       mark->property_outline_color_rgba() = color;
 }
 
 /***********************************************************************/
index 5ffd6c5dd16448710cbe85871ae4a30d389cca7a..fa252571fb95796116e7fa7b988818e1b147c229 100644 (file)
@@ -60,6 +60,7 @@ class Marker : public PBD::Destructible
        void add_line (ArdourCanvas::Group*, double initial_height);
        void show_line ();
        void hide_line ();
+       void set_line_length (double);
 
        void set_position (nframes_t);
        void set_name (const string&);
@@ -67,14 +68,18 @@ class Marker : public PBD::Destructible
        
        nframes64_t position() const { return frame_position; }
 
+       ArdourCanvas::Group * get_parent() { return _parent; }
+       void reparent (ArdourCanvas::Group & parent);
+       
        void hide ();
        void show ();
 
        Type type () { return _type; }
-       
+
   protected:
        PublicEditor& editor;
 
+       ArdourCanvas::Group * _parent;
        ArdourCanvas::Group *group;
        ArdourCanvas::Polygon *mark;
        ArdourCanvas::Text *text;
index eb3e7496bf9b39faa5ac6e26fc9e8883b6fa10f3..19b81ec4f94ecc28180e74dbe996d19ba450b462 100644 (file)
@@ -41,6 +41,7 @@
 #include <ardour/panner.h>
 #include <ardour/send.h>
 #include <ardour/processor.h>
+#include <ardour/profile.h>
 #include <ardour/ladspa_plugin.h>
 #include <ardour/auto_bundle.h>
 #include <ardour/user_bundle.h>
@@ -448,10 +449,6 @@ MixerStrip::set_width (Width w, void* owner)
 
        _width_owner = owner;
 
-       if (_width == w) {
-               return;
-       }
-
        ensure_xml_node ();
        
        _width = w;
@@ -819,12 +816,14 @@ void
 MixerStrip::input_changed (IOChange change, void *src)
 {
        Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_input_display));
+       set_width(_width, this);
 }
 
 void
 MixerStrip::output_changed (IOChange change, void *src)
 {
        Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_output_display));
+       set_width(_width, this);
 }
 
 
@@ -1056,7 +1055,9 @@ MixerStrip::build_route_ops_menu ()
        build_remote_control_menu ();
        
        items.push_back (SeparatorElem());
-       items.push_back (MenuElem (_("Remote Control ID"), *remote_control_menu));
+       if (!Profile->get_sae()) {
+              items.push_back (MenuElem (_("Remote Control ID"), *remote_control_menu));
+        }
 
        items.push_back (SeparatorElem());
        items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route)));
@@ -1297,5 +1298,6 @@ MixerStrip::meter_changed (void *src)
        }
 
        gpm.setup_meters ();
+               set_width(_width, this);
 }
 
index ad3927b8b6da0f9f4b9416d4fe9a748754cb8a29..8d349d8dc89a9400a47538b93fc2838012e1e6df 100644 (file)
@@ -422,7 +422,7 @@ Mixer_UI::strip_button_release_event (GdkEventButton *ev, MixerStrip *strip)
                if (_selection.selected (strip->route())) {
                        _selection.remove (strip->route());
                } else {
-                       if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+                       if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
                                _selection.add (strip->route());
                        } else {
                                _selection.set (strip->route());
index ebf520fba74f8aa9901ed6991f2fa1c6b1c6255f..9ecc7ea2f5bc5933a46beb0e4f58b5956b92d1c9 100644 (file)
@@ -344,10 +344,6 @@ NewSessionDialog::NewSessionDialog()
        open_session_vbox->pack_start(*open_session_hbox, Gtk::PACK_SHRINK, 12);
        m_notebook->set_flags(Gtk::CAN_FOCUS);
        m_notebook->set_scrollable(true);
-       m_notebook->append_page(*new_session_table, _("New Session"));
-       m_notebook->pages().back().set_tab_label_packing(false, true, Gtk::PACK_START);
-       m_notebook->append_page(*open_session_vbox, _("Open Session"));
-       m_notebook->pages().back().set_tab_label_packing(false, true, Gtk::PACK_START);
        get_vbox()->set_homogeneous(false);
        get_vbox()->set_spacing(0);
        get_vbox()->pack_start(*m_notebook, Gtk::PACK_SHRINK, 0);
@@ -430,6 +426,8 @@ NewSessionDialog::NewSessionDialog()
        m_open_filechooser->signal_selection_changed ().connect (mem_fun (*this, &NewSessionDialog::file_chosen));
        m_template->signal_selection_changed ().connect (mem_fun (*this, &NewSessionDialog::template_chosen));
        m_name->grab_focus();
+       
+       page_set = Pages (0);
 }
 
 NewSessionDialog::~NewSessionDialog()
@@ -437,32 +435,74 @@ NewSessionDialog::~NewSessionDialog()
        in_destructor = true;
 }
 
+int
+NewSessionDialog::run ()
+{
+       if (!page_set) {
+               /* nothing to display */
+               return Gtk::RESPONSE_OK;
+       }
+
+       return ArdourDialog::run ();
+}
+
 void
 NewSessionDialog::set_have_engine (bool yn)
 {
-       if (yn) {
-               m_notebook->remove_page (engine_control);
-       } else {
-               // XXX this is a bit of crude hack. if we ever add or remove
-               // pages from the notebook, this is going to break.
-               if (m_notebook->get_n_pages () != 3) {
-                       m_notebook->append_page (engine_control, _("Audio Setup"));
-                       m_notebook->show_all_children();
-               }
-       }
+       if (yn) {
+               m_notebook->remove_page (engine_control);
+               page_set = Pages (page_set & ~EnginePage);
+       } else {
+               if (!(page_set & EnginePage)) {
+                       m_notebook->append_page (engine_control, _("Audio Setup"));
+                       m_notebook->show_all_children();
+                       page_set = Pages (page_set | EnginePage);
+               }
+       }
 }
 
 
 void
-NewSessionDialog::set_session_name(const Glib::ustring& name)
+NewSessionDialog::set_existing_session (bool yn)
+{
+       if (yn) {
+
+               if (page_set & NewPage) {
+                       m_notebook->remove_page (*new_session_table);
+                       page_set = Pages (page_set & ~NewPage);
+               }
+
+               if (page_set & OpenPage) {
+                       m_notebook->remove_page (*open_session_vbox);
+                       page_set = Pages (page_set & ~OpenPage);
+               }
+
+       } else {
+               if (!(page_set & NewPage)) {
+                       m_notebook->append_page(*new_session_table, _("New Session"));
+                       m_notebook->pages().back().set_tab_label_packing(false, true, Gtk::PACK_START);
+                       page_set = Pages (page_set | NewPage);
+               }
+               if (!(page_set & OpenPage)) {
+                       m_notebook->append_page(*open_session_vbox, _("Open Session"));
+                       m_notebook->pages().back().set_tab_label_packing(false, true, Gtk::PACK_START);
+                       page_set = Pages (page_set | OpenPage);
+               }
+
+               m_notebook->show_all_children();
+       }
+}
+
+void
+NewSessionDialog::set_session_name (const Glib::ustring& name)
 {
-       m_name->set_text(name);
+       m_name->set_text (name);
 }
 
 void
 NewSessionDialog::set_session_folder(const Glib::ustring& dir)
 {
-       // XXX DO SOMETHING
+       m_folder->set_current_folder (dir);
 }
 
 std::string
@@ -682,7 +722,8 @@ NewSessionDialog::file_chosen ()
 
        m_treeview->get_selection()->unselect_all();
 
-       get_window()->set_cursor(Gdk::Cursor(Gdk::WATCH));
+       if (get_window())
+               get_window()->set_cursor(Gdk::Cursor(Gdk::WATCH));
 
        if (!m_open_filechooser->get_filename().empty()) {
                set_response_sensitive (Gtk::RESPONSE_OK, true);
index 53ec3eabf2b3019fb98b6998884de38b4d36c6b9..0998f8a39a532401b68439481a49846af4c9d2b3 100644 (file)
@@ -57,6 +57,8 @@ public:
        NewSessionDialog();
        ~NewSessionDialog ();
 
+       int run ();
+
        void set_session_name(const Glib::ustring& name);
        void set_session_folder(const Glib::ustring& folder);
 
@@ -95,6 +97,7 @@ public:
 
        EngineControl engine_control;
        void set_have_engine (bool yn);
+       void set_existing_session (bool yn);
 
 protected:
 
@@ -167,6 +170,14 @@ protected:
        Gtk::Notebook* m_notebook;
 
  private:
+       enum Pages {
+               NewPage = 0x1,
+               OpenPage = 0x2,
+               EnginePage = 0x4
+       };
+
+       Pages page_set;
+
        struct RecentSessionModelColumns : public Gtk::TreeModel::ColumnRecord {
            RecentSessionModelColumns() { 
                    add (visible_name);
index e49b410668ecfc3dc8b6fb7c5e88cb5b6ccea5f1..0184e3a00a0db8ec838c6887d4f179b458e0e10c 100644 (file)
@@ -1079,6 +1079,23 @@ static const struct {
     const char *name;
     guint   modifier;
 } modifiers[] = {
+
+#ifdef GTKOSX 
+
+       /* Command = Mod1
+          Option/Alt = Mod5
+       */
+
+       { "Shift", GDK_SHIFT_MASK },
+       { "Command", GDK_MOD1_MASK },
+       { "Control", GDK_CONTROL_MASK },
+       { "Option", GDK_MOD5_MASK },
+       { "Command-Shift", GDK_MOD1_MASK|GDK_SHIFT_MASK },
+       { "Command-Option", GDK_MOD1_MASK|GDK_MOD5_MASK },
+       { "Shift-Option", GDK_SHIFT_MASK|GDK_MOD5_MASK },
+       { "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
+
+#else
        { "Shift", GDK_SHIFT_MASK },
        { "Control", GDK_CONTROL_MASK },
        { "Alt (Mod1)", GDK_MOD1_MASK },
@@ -1090,6 +1107,7 @@ static const struct {
        { "Mod3", GDK_MOD3_MASK },
        { "Mod4", GDK_MOD4_MASK },
        { "Mod5", GDK_MOD5_MASK },
+#endif
        { 0, 0 }
 };
 
index 8da0fb9ca115ced40f8ac217dce800006938f041..00aa5cf94e723e1f52568512b37926f06677adec 100644 (file)
@@ -21,6 +21,8 @@
 #include <iostream>
 #include <cstdlib>
 
+#include <ardour/session.h>
+
 #include "opts.h"
 
 #include "i18n.h"
@@ -38,6 +40,7 @@ char* ARDOUR_COMMAND_LINE::curvetest_file = 0;
 bool ARDOUR_COMMAND_LINE::try_hw_optimization = true;
 string ARDOUR_COMMAND_LINE::keybindings_path = ""; /* empty means use builtin default */
 Glib::ustring ARDOUR_COMMAND_LINE::menus_file = "ardour.menus";
+bool ARDOUR_COMMAND_LINE::finder_invoked_ardour = false;
 
 using namespace ARDOUR_COMMAND_LINE;
 
@@ -48,8 +51,9 @@ print_help (const char *execname)
             << _("  -v, --version                    Show version information\n")
             << _("  -h, --help                       Print this message\n")
             << _("  -b, --bindings                   Print all possible keyboard binding names\n")
-            << _("  -n, --show-splash                Show splash screen\n")
             << _("  -c, --name  name                 Use a specific jack client name, default is ardour\n")
+            << _("  -d, --disable-plugins            Disable all plugins in an existing session\n")
+            << _("  -n, --show-splash                Show splash screen\n")
             << _("  -m, --menus file                 Use \"file\" for Ardour menus\n")                       
             << _("  -N, --new session-name           Create a new session from the command line\n")                       
             << _("  -O, --no-hw-optimizations        Disable h/w specific optimizations\n")
@@ -69,11 +73,12 @@ int
 ARDOUR_COMMAND_LINE::parse_opts (int argc, char *argv[])
 
 {
-       const char *optstring = "U:hSbvVnOc:C:m:N:k:";
+       const char *optstring = "U:hSbvVnOdc:C:m:N:k:p:";
        const char *execname = strrchr (argv[0], '/');
 
        if (getenv ("ARDOUR_SAE")) {
                menus_file = "ardour-sae.menus";
+               keybindings_path = "ardour-sae";
        }
 
        if (execname == 0) {
@@ -122,6 +127,10 @@ ARDOUR_COMMAND_LINE::parse_opts (int argc, char *argv[])
                case 'b':
                        show_key_actions = true;
                        break;
+                       
+               case 'd':
+                       ARDOUR::Session::set_disable_all_loaded_plugins (true);
+                       break;
 
  
                 case 'm':
@@ -131,6 +140,11 @@ ARDOUR_COMMAND_LINE::parse_opts (int argc, char *argv[])
                case 'n':
                        no_splash = false;
                        break;
+
+               case 'p':
+                       //undocumented OS X finder -psn_XXXXX argument
+                       finder_invoked_ardour = true;
+                       break;
                
                case 'S':
                //      ; just pass this through to gtk it will figure it out
@@ -144,11 +158,6 @@ ARDOUR_COMMAND_LINE::parse_opts (int argc, char *argv[])
                case 'O':
                        try_hw_optimization = false;
                        break;
-
-
-               case 'p':
-                       //undocumented OS X finder -psn_XXXXX argument
-                       break;
                
                case 'V':
 #ifdef VST_SUPPORT
index c1b3f062d407030e12e33b71a400276f9c768456..08e38be88d5a35ced96c29d0cee67021c1be9ddf 100644 (file)
@@ -39,6 +39,7 @@ extern bool   try_hw_optimization;
 extern bool   use_gtk_theme;
 extern string keybindings_path;
 extern Glib::ustring menus_file;
+extern bool   finder_invoked_ardour;
 
 extern int32_t parse_opts (int argc, char *argv[]);
 
index 34f367b25b1ba978f8c8c996142bcc8b66eb7ffe..a1f99c40d46c95995734d739e84a111904254277 100644 (file)
@@ -534,7 +534,7 @@ Panner2d::on_button_release_event (GdkEventButton *ev)
                y = (int) floor (ev->y);
                state = (GdkModifierType) ev->state;
 
-               if (drag_is_puck && (Keyboard::modifier_state_contains (state, Keyboard::Shift))) {
+               if (drag_is_puck && (Keyboard::modifier_state_contains (state, Keyboard::TertiaryModifier))) {
                        
                        for (Targets::iterator i = pucks.begin(); i != pucks.end(); ++i) {
                                Target* puck = i->second;
index 0b96adf6822272f15b3eded606c00951c32a44a3..001ff370c836d73e0781f4340b098109d3752141 100644 (file)
@@ -65,20 +65,20 @@ PluginSelector::PluginSelector (PluginManager *mgr)
        manager = mgr;
        session = 0;
        
-       current_selection = ARDOUR::LADSPA;
-
-       lmodel = Gtk::ListStore::create(lcols);
-       ladspa_display.set_model (lmodel);
-       ladspa_display.append_column (_("Available LADSPA Plugins"), lcols.name);
-       ladspa_display.append_column (_("Type"), lcols.type);
-       ladspa_display.append_column (_("# Inputs"),lcols.ins);
-       ladspa_display.append_column (_("# Outputs"), lcols.outs);
-       ladspa_display.set_headers_visible (true);
-       ladspa_display.set_headers_clickable (true);
-       ladspa_display.set_reorderable (false);
-       lscroller.set_border_width(10);
-       lscroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
-       lscroller.add(ladspa_display);
+       plugin_model = Gtk::ListStore::create (plugin_columns);
+       plugin_display.set_model (plugin_model);
+       plugin_display.append_column (_("Available Plugins"), plugin_columns.name);
+       plugin_display.append_column (_("Type"), plugin_columns.type_name);
+       plugin_display.append_column (_("Category"), plugin_columns.category);
+       plugin_display.append_column (_("Creator"), plugin_columns.creator);
+       plugin_display.append_column (_("# Inputs"),plugin_columns.ins);
+       plugin_display.append_column (_("# Outputs"), plugin_columns.outs);
+       plugin_display.set_headers_visible (true);
+       plugin_display.set_headers_clickable (true);
+       plugin_display.set_reorderable (false);
+       scroller.set_border_width(10);
+       scroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+       scroller.add(plugin_display);
 
        amodel = Gtk::ListStore::create(acols);
        added_list.set_model (amodel);
@@ -87,48 +87,10 @@ PluginSelector::PluginSelector (PluginManager *mgr)
        added_list.set_reorderable (false);
 
        for (int i = 0; i <=3; i++) {
-               Gtk::TreeView::Column* column = ladspa_display.get_column(i);
+               Gtk::TreeView::Column* column = plugin_display.get_column(i);
                column->set_sort_column(i);
        }
 
-#ifdef VST_SUPPORT
-       vmodel = ListStore::create(vcols);
-       vst_display.set_model (vmodel);
-       vst_display.append_column (_("Available plugins"), vcols.name);
-       vst_display.append_column (_("# Inputs"), vcols.ins);
-       vst_display.append_column (_("# Outputs"), vcols.outs);
-       vst_display.set_headers_visible (true);
-       vst_display.set_headers_clickable (true);
-       vst_display.set_reorderable (false);
-       vscroller.set_border_width(10);
-       vscroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
-       vscroller.add(vst_display);
-
-       for (int i = 0; i <=2; i++) {
-               Gtk::TreeView::Column* column = vst_display.get_column(i);
-               column->set_sort_column(i);
-       }
-#endif
-
-#ifdef HAVE_AUDIOUNIT
-       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_headers_clickable (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);
@@ -146,7 +108,7 @@ PluginSelector::PluginSelector (PluginManager *mgr)
 
        Gtk::Table* table = manage(new Gtk::Table(7, 11));
        table->set_size_request(750, 500);
-       table->attach(notebook, 0, 7, 0, 5);
+       table->attach(scroller, 0, 7, 0, 5);
 
        HBox* filter_box = manage (new HBox);
 
@@ -176,98 +138,26 @@ PluginSelector::PluginSelector (PluginManager *mgr)
        table->attach(ascroller, 0, 7, 8, 10);
 
        add_button (Stock::CANCEL, RESPONSE_CANCEL);
-       add_button (Stock::CONNECT, RESPONSE_APPLY);
+       add_button (_("Insert Plugin(s)"), RESPONSE_APPLY);
        set_default_response (RESPONSE_APPLY);
        set_response_sensitive (RESPONSE_APPLY, false);
        get_vbox()->pack_start (*table);
 
-
-       // Notebook tab order must be the same in here as in set_correct_focus()
-       using namespace 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_AUDIOUNIT
-       notebook.pages().push_back (TabElem (auscroller, _("AudioUnit")));
-#endif
-
        table->set_name("PluginSelectorTable");
-       ladspa_display.set_name("PluginSelectorDisplay");
-       //ladspa_display.set_name("PluginSelectorList");
+       plugin_display.set_name("PluginSelectorDisplay");
+       //plugin_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));
-       ladspa_display.grab_focus();
+       plugin_display.signal_button_press_event().connect_notify (mem_fun(*this, &PluginSelector::row_clicked));
+       plugin_display.get_selection()->signal_changed().connect (mem_fun(*this, &PluginSelector::display_selection_changed));
+       plugin_display.grab_focus();
        
-#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_AUDIOUNIT
-       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));
        added_list.get_selection()->signal_changed().connect (mem_fun(*this, &PluginSelector::added_list_selection_changed));
 
-       ladspa_refiller ();
-       
-#ifdef VST_SUPPORT
-       vst_refiller ();
-#endif
-
-#ifdef HAVE_AUDIOUNIT
-       au_refiller ();
-#endif
-
-       signal_show().connect (mem_fun (*this, &PluginSelector::set_correct_focus));
-}
-
-/**
- * Makes sure keyboard focus is always in the plugin list
- * of the selected notebook tab.
- **/
-void
-PluginSelector::set_correct_focus()
-{
-       int cp = notebook.get_current_page();
-
-       if (cp == 0) {
-               ladspa_display.grab_focus();
-               return;
-       }
-
-#ifdef VST_SUPPORT
-       if (Config->get_use_vst()) {
-               cp--;
-       
-               if (cp == 0) {
-                       vst_display.grab_focus();
-                       return;
-               }
-       }
-#endif
-
-#ifdef HAVE_AUDIOUNIT
-       cp--;
-
-       if (cp == 0) {
-               au_display.grab_focus();
-               return;
-       }
-#endif
+       refill ();
 }
 
 void
@@ -290,7 +180,7 @@ PluginSelector::set_session (Session* s)
 }
 
 bool
-PluginSelector::show_this_plugin (PluginInfoPtr& info, const std::string& filterstr)
+PluginSelector::show_this_plugin (const PluginInfoPtr& info, const std::string& filterstr)
 {
        std::string compstr;
        std::string mode = filter_mode.get_active_text ();
@@ -328,124 +218,83 @@ PluginSelector::setup_filter_string (string& filterstr)
 }      
 
 void
-PluginSelector::ladspa_refiller ()
+PluginSelector::refill ()
 {
-       guint row;
-       PluginInfoList &plugs = manager->ladspa_plugin_info ();
-       PluginInfoList::iterator i;
-       char ibuf[16], obuf[16];
+       std::string filterstr;
 
-       lmodel->clear();
+       plugin_model->clear ();
 
-       std::string filterstr;
        setup_filter_string (filterstr);
-       
-       for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) {
-               if (show_this_plugin (*i, filterstr)) {
-                       snprintf (ibuf, sizeof(ibuf)-1, "%u", (*i)->n_inputs.n_total());
-                       snprintf (obuf, sizeof(obuf)-1, "%u", (*i)->n_outputs.n_total());               
-
-                       TreeModel::Row newrow = *(lmodel->append());
-                       newrow[lcols.name] = (*i)->name.c_str();
-                       newrow[lcols.type] = (*i)->category.c_str();
-                       newrow[lcols.ins] = ibuf;
-                       newrow[lcols.outs] = obuf;
-                       newrow[lcols.plugin] = *i;
-               }
-       }
 
-       lmodel->set_sort_column (0, SORT_ASCENDING);
+       ladspa_refiller (filterstr);
+       vst_refiller (filterstr);
+       au_refiller (filterstr);
 }
 
-#ifdef VST_SUPPORT
-
 void
-PluginSelector::vst_refiller ()
+PluginSelector::refiller (const PluginInfoList& plugs, const::std::string& filterstr, const char* type)
 {
-       guint row;
-       PluginInfoList &plugs = manager->vst_plugin_info ();
-       PluginInfoList::iterator i;
-       char ibuf[16], obuf[16];
-       vmodel->clear();
-       
-       std::string filterstr;
-       setup_filter_string (filterstr);
-       
-       for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) {
+       char buf[16];
+
+       for (PluginInfoList::const_iterator i = plugs.begin(); i != plugs.end(); ++i) {
 
                if (show_this_plugin (*i, filterstr)) {
-                       snprintf (ibuf, sizeof(ibuf)-1, "%d", (*i)->n_inputs);
-                       snprintf (obuf, sizeof(obuf)-1, "%d", (*i)->n_outputs);         
-                       
-                       TreeModel::Row newrow = *(vmodel->append());
-                       newrow[vcols.name] = (*i)->name.c_str();
-                       newrow[vcols.ins] = ibuf;
-                       newrow[vcols.outs] = obuf;
-                       newrow[vcols.plugin] = *i;
-               }
-       }
-       vmodel->set_sort_column (0, SORT_ASCENDING);
-}
 
-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);
-       }
+                       TreeModel::Row newrow = *(plugin_model->append());
+                       newrow[plugin_columns.name] = (*i)->name;
+                       newrow[plugin_columns.type_name] = type;
+                       newrow[plugin_columns.category] = (*i)->category;
 
-       current_selection = ARDOUR::VST;
-}
 
-#endif //VST_SUPPORT
+                       string creator = (*i)->creator;
+                       string::size_type pos = 0;
 
-#ifdef HAVE_AUDIOUNIT
+                       /* stupid LADSPA creator strings */
 
-void
-PluginSelector::au_refiller ()
-{
-       guint row;
-       PluginInfoList plugs (AUPluginInfo::discover ());
-       PluginInfoList::iterator i;
-       char ibuf[16], obuf[16];
-       aumodel->clear();
-       
-       std::string filterstr;
-       setup_filter_string (filterstr);
-       
-       for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) {
+                       while (pos < creator.length() && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos;
+                       creator = creator.substr (0, pos);
 
-               if (show_this_plugin (*i, filterstr)) {
+                       newrow[plugin_columns.creator] = creator;
+
+                       if ((*i)->n_inputs.n_total() < 0) {
+                               newrow[plugin_columns.ins] = "various";
+                       } else {
+                               snprintf (buf, sizeof(buf), "%d", (*i)->n_inputs.n_total());
+                               newrow[plugin_columns.ins] = buf;
+                       }
+                       if ((*i)->n_outputs.n_total() < 0) {
+                               newrow[plugin_columns.outs] = "various";
+                       } else {
+                               snprintf (buf, sizeof(buf), "%d", (*i)->n_outputs.n_total());           
+                               newrow[plugin_columns.outs] = buf;
+                       }
 
-                       snprintf (ibuf, sizeof(ibuf)-1, "%d", (*i)->n_inputs);
-                       snprintf (obuf, sizeof(obuf)-1, "%d", (*i)->n_outputs);         
-                       
-                       TreeModel::Row newrow = *(aumodel->append());
-                       newrow[aucols.name] = (*i)->name.c_str();
-                       newrow[aucols.ins] = ibuf;
-                       newrow[aucols.outs] = obuf;
-                       newrow[aucols.plugin] = *i;
+                       newrow[plugin_columns.plugin] = *i;
                }
-       }
+       }       
+}
 
-       aumodel->set_sort_column (0, SORT_ASCENDING);
+void
+PluginSelector::ladspa_refiller (const std::string& filterstr)
+{
+       refiller (manager->ladspa_plugin_info(), filterstr, "LADSPA");
 }
 
 void
-PluginSelector::au_display_selection_changed()
+PluginSelector::vst_refiller (const std::string& filterstr)
 {
-       if (au_display.get_selection()->count_selected_rows() != 0) {
-               btn_add->set_sensitive (true);
-       } else {
-               btn_add->set_sensitive (false);
-       }
-       
-       current_selection = ARDOUR::AudioUnit;
+#ifdef VST_SUPPORT
+       refiller (manager->vst_plugin_info(), filterstr, "VST");
+#endif
 }
 
-#endif //HAVE_AUDIOUNIT
+void
+PluginSelector::au_refiller (const std::string& filterstr)
+{
+#ifdef HAVE_AUDIOUNITS
+       refiller (manager->au_plugin_info(), filterstr, "AU");
+#endif
+}
 
 void
 PluginSelector::use_plugin (PluginInfoPtr pi)
@@ -467,33 +316,11 @@ PluginSelector::btn_add_clicked()
        std::string name;
        PluginInfoPtr pi;
        TreeModel::Row newrow = *(amodel->append());
-       
        TreeModel::Row row;
 
-       switch (current_selection) {
-               case ARDOUR::LADSPA:
-                       row = *(ladspa_display.get_selection()->get_selected());
-                       name = row[lcols.name];
-                       pi = row[lcols.plugin];
-                       break;
-               case ARDOUR::VST:
-#ifdef VST_SUPPORT
-                       row = *(vst_display.get_selection()->get_selected());
-                       name = row[vcols.name];
-                       pi = row[vcols.plugin];
-#endif
-                       break;
-               case ARDOUR::AudioUnit:
-#ifdef HAVE_AUDIOUNIT
-                       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;
-       }
+       row = *(plugin_display.get_selection()->get_selected());
+       name = row[plugin_columns.name];
+       pi = row[plugin_columns.plugin];
 
        newrow[acols.text] = name;
        newrow[acols.plugin] = pi;
@@ -522,27 +349,13 @@ PluginSelector::btn_update_clicked()
 }
 
 void
-PluginSelector::refill()
+PluginSelector::display_selection_changed()
 {
-       ladspa_refiller ();
-#ifdef VST_SUPPORT
-       vst_refiller ();
-#endif 
-#ifdef HAVE_AUDIOUNIT
-       au_refiller ();
-#endif
-}
-
-void
-PluginSelector::ladspa_display_selection_changed()
-{
-       if (ladspa_display.get_selection()->count_selected_rows() != 0) {
+       if (plugin_display.get_selection()->count_selected_rows() != 0) {
                btn_add->set_sensitive (true);
        } else {
                btn_add->set_sensitive (false);
        }
-       
-       current_selection = ARDOUR::LADSPA;
 }
 
 void
@@ -566,7 +379,8 @@ PluginSelector::run ()
        switch (r) {
        case RESPONSE_APPLY:
                for (i = amodel->children().begin(); i != amodel->children().end(); ++i) {
-                       use_plugin ((*i)[acols.plugin]);
+                       PluginInfoPtr pp = (*i)[acols.plugin];
+                       use_plugin (pp);
                }
                break;
 
index 5994e7b3efc7f82979795d45469ea2fa6b57b286..ac300638d728ad8418cd3a5a8d549782d1714734 100644 (file)
@@ -44,10 +44,7 @@ class PluginSelector : public ArdourDialog
 
   private:
        ARDOUR::Session* session;
-       Gtk::Notebook notebook;
-       Gtk::ScrolledWindow lscroller;  // ladspa
-       Gtk::ScrolledWindow vscroller;  // vst
-       Gtk::ScrolledWindow auscroller; // AudioUnit
+       Gtk::ScrolledWindow scroller;  // Available plugins
        Gtk::ScrolledWindow ascroller;  // Added plugins
 
        Gtk::ComboBoxText filter_mode;
@@ -58,27 +55,27 @@ class PluginSelector : public ArdourDialog
        void filter_entry_changed ();
        void filter_mode_changed ();
        
-       ARDOUR::PluginType current_selection;
-
-       // page 1
-       struct LadspaColumns : public Gtk::TreeModel::ColumnRecord {
-               LadspaColumns () {
+       struct PluginColumns : public Gtk::TreeModel::ColumnRecord {
+               PluginColumns () {
                        add (name);
-                   add (type);
+                       add (type_name);
+                       add (category);
+                       add (creator);
                        add (ins);
                        add (outs);
                        add (plugin);
                }
-           Gtk::TreeModelColumn<std::string> name;
-               Gtk::TreeModelColumn<std::string> type;
+               Gtk::TreeModelColumn<std::string> name;
+               Gtk::TreeModelColumn<std::string> type_name;
+               Gtk::TreeModelColumn<std::string> category;
+               Gtk::TreeModelColumn<std::string> creator;
                Gtk::TreeModelColumn<std::string> ins;
                Gtk::TreeModelColumn<std::string> outs;
-           Gtk::TreeModelColumn<ARDOUR::PluginInfoPtr> plugin;
+               Gtk::TreeModelColumn<ARDOUR::PluginInfoPtr> plugin;
        };
-       LadspaColumns lcols;
-       Glib::RefPtr<Gtk::ListStore> lmodel;
-       Glib::RefPtr<Gtk::TreeSelection> lselection;
-       Gtk::TreeView ladspa_display;
+       PluginColumns plugin_columns;
+       Glib::RefPtr<Gtk::ListStore> plugin_model;
+       Gtk::TreeView plugin_display;
        Gtk::Button* btn_add;
        Gtk::Button* btn_remove;
 
@@ -92,72 +89,27 @@ class PluginSelector : public ArdourDialog
        };
        AddedColumns acols;
        Glib::RefPtr<Gtk::ListStore> amodel;
-       Glib::RefPtr<Gtk::TreeSelection> aselection;
        Gtk::TreeView added_list;
 
-#ifdef VST_SUPPORT
-       // page 2
-       struct VstColumns : public Gtk::TreeModel::ColumnRecord {
-               VstColumns () {
-                       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;
-       };
-       VstColumns vcols;
-       Glib::RefPtr<Gtk::ListStore> vmodel;
-       Glib::RefPtr<Gtk::TreeSelection> vselection;
-       Gtk::TreeView vst_display;
-       void vst_refiller ();
-       void vst_display_selection_changed();
-#endif // VST_SUPPORT
-
-#ifdef HAVE_AUDIOUNIT
-       // 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;
-       void au_refiller ();
-       void au_display_selection_changed();
-#endif //HAVE_AUDIOUNIT
+       void refill ();
+       void refiller (const ARDOUR::PluginInfoList& plugs, const::std::string& filterstr, const char* type);
+       void ladspa_refiller (const std::string&);
+       void vst_refiller (const std::string&);
+       void au_refiller (const std::string&);
 
        ARDOUR::PluginManager *manager;
 
-       static void _ladspa_refiller (void *);
-       
-       void ladspa_refiller ();
        void row_clicked(GdkEventButton *);
        void btn_add_clicked();
        void btn_remove_clicked();
        void btn_update_clicked();
        void added_list_selection_changed();
-       void ladspa_display_selection_changed();
+       void display_selection_changed();
        void btn_apply_clicked();
        void use_plugin (ARDOUR::PluginInfoPtr);
        void cleanup ();
-       void refill ();
-       bool show_this_plugin (ARDOUR::PluginInfoPtr&, const std::string&);
+       bool show_this_plugin (const ARDOUR::PluginInfoPtr&, const std::string&);
        void setup_filter_string (std::string&);
-
-       void set_correct_focus();
 };
 
 #endif // __ardour_plugin_selector_h__
index 935fc6000d6134de5f6fa43250a51a652e667142..0f2eedb080e4f7be254183b3eb78b94bb04c1355 100644 (file)
@@ -64,41 +64,42 @@ using namespace sigc;
 PluginUIWindow::PluginUIWindow (boost::shared_ptr<PluginInsert> insert, nframes64_t sr, nframes64_t period, bool scrollable)
        : ArdourDialog ("plugin ui")
 {
-       if (insert->plugin()->has_editor()) {
-
-#ifdef VST_SUPPORT
+       bool have_gui = false;
+       non_gtk_gui = false;
 
-               boost::shared_ptr<VSTPlugin> vp;
-
-               if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (insert->plugin())) != 0) {
-                       
-                       
-                       VSTPluginUI* vpu = new VSTPluginUI (insert, vp, session.frame_rate(), session.engine().frames_per_cycle());
-                       
-                       _pluginui = vpu;
-                       get_vbox()->add (*vpu);
-                       vpu->package (*this);
+       if (insert->plugin()->has_editor()) {
+               switch (insert->type()) {
+               case ARDOUR::VST:
+                       have_gui = create_vst_editor (insert);
+                       break;
+
+               case ARDOUR::AudioUnit:
+                       have_gui = create_audiounit_editor (insert);
+                       break;
                        
-               } else {
-#endif
+               case ARDOUR::LADSPA:
+                       error << _("Eh? LADSPA plugins don't have editors!") << endmsg;
+                       break;
+
+               default:
                        error << _("unknown type of editor-supplying plugin (note: no VST support in this version of ardour)")
                              << endmsg;
                        throw failed_constructor ();
-#ifdef VST_SUPPORT
                }
-#endif
 
-       } else {
+       } 
+
+       if (!have_gui) {
 
-               LadspaPluginUI*  pu  = new LadspaPluginUI (insert, sr, period, scrollable);
+               GenericPluginUI*  pu  = new GenericPluginUI (insert, scrollable);
                
                _pluginui = pu;
                get_vbox()->add (*pu);
                
                set_wmclass (X_("ardour_plugin_editor"), "Ardour");
 
-               signal_map_event().connect (mem_fun (*pu, &LadspaPluginUI::start_updating));
-               signal_unmap_event().connect (mem_fun (*pu, &LadspaPluginUI::stop_updating));
+               signal_map_event().connect (mem_fun (*pu, &GenericPluginUI::start_updating));
+               signal_unmap_event().connect (mem_fun (*pu, &GenericPluginUI::stop_updating));
        }
 
        set_position (Gtk::WIN_POS_MOUSE);
@@ -108,21 +109,87 @@ PluginUIWindow::PluginUIWindow (boost::shared_ptr<PluginInsert> insert, nframes6
        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));
 
+       gint h = _pluginui->get_preferred_height ();
+       gint w = _pluginui->get_preferred_width ();
+
        if (scrollable) {
-               gint h = _pluginui->get_preferred_height ();
                if (h > 600) h = 600;
-               set_default_size (450, h); 
+               if (w > 600) w = 600;
+
+               if (w < 0) {
+                       w = 450;
+               }
        }
 
+       set_default_size (w, h); 
 }
 
 PluginUIWindow::~PluginUIWindow ()
 {
 }
 
+bool
+PluginUIWindow::create_vst_editor(boost::shared_ptr<PluginInsert> insert)
+{
+#ifndef VST_SUPPORT
+       return false;
+#else
+
+       boost::shared_ptr<VSTPlugin> vp;
+
+       if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (insert->plugin())) == 0) {
+               error << _("unknown type of editor-supplying plugin (note: no VST support in this version of ardour)")
+                             << endmsg;
+               throw failed_constructor ();
+       } else {
+               VSTPluginUI* vpu = new VSTPluginUI (insert, vp);
+       
+               _pluginui = vpu;
+               get_vbox()->add (*vpu);
+               vpu->package (*this);
+       }
+
+       non_gtk_gui = true;
+       return true;
+#endif
+}
+
+bool
+PluginUIWindow::create_audiounit_editor (boost::shared_ptr<PluginInsert> insert)
+{
+#if !defined(HAVE_AUDIOUNITS) || !defined(GTKOSX)
+       return false;
+#else
+       VBox* box;
+       _pluginui = create_au_gui (insert, &box);
+       get_vbox()->add (*box);
+       non_gtk_gui = true;
+
+       extern sigc::signal<void,bool> ApplicationActivationChanged;
+       ApplicationActivationChanged.connect (mem_fun (*this, &PluginUIWindow::app_activated));
+
+       return true;
+#endif
+}
+
+void
+PluginUIWindow::app_activated (bool yn)
+{
+#if defined (HAVE_AUDIOUNITS) && defined(GTKOSX)
+       if (yn) {
+               _pluginui->activate ();
+       }
+       cerr << "activated ? " << yn << endl;
+#endif
+}
+
 bool
 PluginUIWindow::on_key_press_event (GdkEventKey* event)
 {
+       if (non_gtk_gui) {
+               return false;
+       }
+
        if (!key_press_focus_accelerator_handler (*this, event)) {
                return PublicEditor::instance().on_key_press_event(event);
        } else {
@@ -145,12 +212,12 @@ PluginUIWindow::plugin_going_away ()
        delete_when_idle (this);
 }
 
-PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi, nframes64_t sr, nframes64_t period)
+PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
        : insert (pi),
          plugin (insert->plugin()),
          save_button(_("Add")),
          bypass_button (_("Bypass")),
-         latency_gui (*pi, sr, period)
+         latency_gui (*pi, pi->session().frame_rate(), pi->session().get_block_size())
 {
         //combo.set_use_arrows_always(true);
        set_popdown_strings (combo, plugin->get_presets());
index 5a712636f6f41c971872d1a2e1a896c4c0a92162..2ae7507d7c2aaaeb6618663271d943281b1e40e5 100644 (file)
@@ -68,12 +68,16 @@ namespace Gtkmm2ext {
 class PlugUIBase : public virtual sigc::trackable
 {
   public:
-       PlugUIBase (boost::shared_ptr<ARDOUR::PluginInsert>, nframes64_t sample_rate, nframes64_t period_size);
+       PlugUIBase (boost::shared_ptr<ARDOUR::PluginInsert>);
        virtual ~PlugUIBase() {}
 
        virtual gint get_preferred_height () = 0;
+       virtual gint get_preferred_width () = 0;
        virtual bool start_updating(GdkEventAny*) = 0;
        virtual bool stop_updating(GdkEventAny*) = 0;
+       
+       virtual void activate () {}
+       virtual void deactivate () {}
 
   protected:
        boost::shared_ptr<ARDOUR::PluginInsert> insert;
@@ -88,14 +92,15 @@ class PlugUIBase : public virtual sigc::trackable
        void bypass_toggled();
 };
 
-class LadspaPluginUI : public PlugUIBase, public Gtk::VBox 
+class GenericPluginUI : public PlugUIBase, public Gtk::VBox 
 {
   public:
-       LadspaPluginUI (boost::shared_ptr<ARDOUR::PluginInsert> plug, nframes64_t sample_rate, nframes64_t period_size, bool scrollable = false);
-       ~LadspaPluginUI ();
+       GenericPluginUI (boost::shared_ptr<ARDOUR::PluginInsert> plug, bool scrollable=false);
+       ~GenericPluginUI ();
        
        gint get_preferred_height () { return prefheight; }
-
+       gint get_preferred_width () { return -1; }
+       
        bool start_updating(GdkEventAny*);
        bool stop_updating(GdkEventAny*);
 
@@ -210,7 +215,12 @@ class PluginUIWindow : public ArdourDialog
        
   private:
        PlugUIBase* _pluginui;
+       bool non_gtk_gui;
+       void app_activated (bool);
        void plugin_going_away ();
+
+       bool create_vst_editor (boost::shared_ptr<ARDOUR::PluginInsert>);
+       bool create_audiounit_editor (boost::shared_ptr<ARDOUR::PluginInsert>);
 };
 
 #ifdef VST_SUPPORT
@@ -221,6 +231,7 @@ class VSTPluginUI : public PlugUIBase, public Gtk::VBox
        ~VSTPluginUI ();
 
        gint get_preferred_height ();
+       gint get_preferred_width ();
        bool start_updating(GdkEventAny*) {return false;}
        bool stop_updating(GdkEventAny*) {return false;}
 
@@ -237,4 +248,9 @@ class VSTPluginUI : public PlugUIBase, public Gtk::VBox
 };
 #endif // VST_SUPPORT
 
+#ifdef HAVE_AUDIOUNITS
+/* this function has to be in a .mm file */
+extern PlugUIBase* create_au_gui (boost::shared_ptr<ARDOUR::PluginInsert>, Gtk::VBox**);
+#endif
+
 #endif /* __ardour_plugin_ui_h__ */
index 200c296417a82dc09ca401d0d440a925a0bd3b87..5df81e92091f66153c8859bb3838277fabc1da50 100644 (file)
@@ -7,16 +7,17 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gtk-ardour 0.347.2\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-11-24 00:48+0100\n"
-"PO-Revision-Date: 2007-04-10 20:11+0100\n"
+"POT-Creation-Date: 2008-01-07 12:21+0100\n"
+"PO-Revision-Date: 2008-01-07 17:01+0100\n"
 "Last-Translator: Sebastian Arnold <mail@sebastian-arnold.net>\n"
 "Language-Team: Deutsch <de@li.org>\n"
 "MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
+"Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Generator: KBabel 0.9.6\n"
 "X-Poedit-Country: GERMANY\n"
+"X-Poedit-Basepath: ../\n"
 
 #: gtk2_ardour/about.cc:120
 msgid "Paul Davis"
@@ -154,7 +155,11 @@ msgstr "John Anderson"
 msgid "Nedko Arnaudov"
 msgstr "Nedko Arnaudov"
 
-#: gtk2_ardour/about.cc:158
+#: gtk2_ardour/about.cc:154
+msgid "Carl Hetherington"
+msgstr "Carl Hetherington"
+
+#: gtk2_ardour/about.cc:159
 msgid ""
 "French:\n"
 "\tAlain Fréhel <alain.frehel@free.fr>\n"
@@ -164,17 +169,17 @@ msgstr ""
 "\tAlain Fréhel <alain.frehel@free.fr>\n"
 "\tChristophe Combelles <ccomb@free.fr>\n"
 
-#: gtk2_ardour/about.cc:159
+#: gtk2_ardour/about.cc:160
 msgid ""
 "German:\n"
 "\tKarsten Petersen <kapet@kapet.de>\n"
 "\tSebastian Arnold <mail@sebastian-arnold.net>\n"
 msgstr ""
-"German:\n"
+"Deutsch:\n"
 "\tKarsten Petersen <kapet@kapet.de>\n"
 "\tSebastian Arnold <mail@sebastian-arnold.net>\n"
 
-#: gtk2_ardour/about.cc:160
+#: gtk2_ardour/about.cc:161
 msgid ""
 "Italian:\n"
 "\tFilippo Pappalardo <filippo@email.it>\n"
@@ -182,7 +187,7 @@ msgstr ""
 "Italian:\n"
 "\tFilippo Pappalardo <filippo@email.it>\n"
 
-#: gtk2_ardour/about.cc:161
+#: gtk2_ardour/about.cc:162
 msgid ""
 "Portuguese:\n"
 "\tRui Nuno Capela <rncbc@rncbc.org>\n"
@@ -190,7 +195,7 @@ msgstr ""
 "Portuguese:\n"
 "\tRui Nuno Capela <rncbc@rncbc.org>\n"
 
-#: gtk2_ardour/about.cc:162
+#: gtk2_ardour/about.cc:163
 msgid ""
 "Brazilian Portuguese:\n"
 "\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\n"
@@ -200,7 +205,7 @@ msgstr ""
 "\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\n"
 "\tChris Ross <chris@tebibyte.org>\n"
 
-#: gtk2_ardour/about.cc:164
+#: gtk2_ardour/about.cc:165
 msgid ""
 "Spanish:\n"
 "\t Alex Krohn <alexkrohn@fastmail.fm>\n"
@@ -208,7 +213,7 @@ msgstr ""
 "Spanish:\n"
 "\t Alex Krohn <alexkrohn@fastmail.fm>\n"
 
-#: gtk2_ardour/about.cc:165
+#: gtk2_ardour/about.cc:166
 msgid ""
 "Russian:\n"
 "\t Igor Blinov <pitstop@nm.ru>\n"
@@ -216,11 +221,19 @@ msgstr ""
 "Russian:\n"
 "\t Igor Blinov <pitstop@nm.ru>\n"
 
-#: gtk2_ardour/about.cc:193
+#: gtk2_ardour/about.cc:167
+msgid ""
+"Greek:\n"
+"\t Klearchos Gourgourinis <muadib@in.gr>\n"
+msgstr ""
+"Greek:\n"
+"\t Klearchos Gourgourinis <muadib@in.gr>\n"
+
+#: gtk2_ardour/about.cc:195
 msgid "Copyright (C) 1999-2007 Paul Davis\n"
 msgstr "Copyright (C) 1999-2007 Paul Davis\n"
 
-#: gtk2_ardour/about.cc:194
+#: gtk2_ardour/about.cc:196
 msgid ""
 "Ardour comes with ABSOLUTELY NO WARRANTY\n"
 "This is free software, and you are welcome to redistribute it\n"
@@ -230,11 +243,11 @@ msgstr ""
 "Dies ist freie Software und Sie dürfen sie gerne weiterverbreiten,\n"
 "solange Sie sich an die Bedingungen, die in der Datei COPYING aufgeführt sind halten.\n"
 
-#: gtk2_ardour/about.cc:199
+#: gtk2_ardour/about.cc:201
 msgid "visit http://www.ardour.org/"
 msgstr "besuchen Sie  http://www.ardour.org"
 
-#: gtk2_ardour/about.cc:200
+#: gtk2_ardour/about.cc:202
 msgid ""
 "%1\n"
 "(built from revision %2)"
@@ -242,98 +255,93 @@ msgstr ""
 "%1\n"
 "(built from revision %2)"
 
-#: gtk2_ardour/actions.cc:76
+#: gtk2_ardour/actions.cc:78
 msgid "badly formatted UI definition file"
 msgstr "die UI Definitionsdatei ist falsch formatiert"
 
-#: gtk2_ardour/actions.cc:78
+#: gtk2_ardour/actions.cc:80
 msgid "Ardour menu definition file not found"
 msgstr "Konnte die ardour Menü-Definition nicht finden"
 
-#: gtk2_ardour/actions.cc:82
+#: gtk2_ardour/actions.cc:84
 msgid "ardour will not work without a valid ardour.menus file"
 msgstr "ardour benötigt eine gültige ardour.menus Datei"
 
-#: gtk2_ardour/actions.cc:234
+#: gtk2_ardour/actions.cc:265
 msgid "programmer error: %1 %2"
 msgstr "Programmierfehler: %1 %2"
 
-#: gtk2_ardour/actions.cc:253
+#: gtk2_ardour/actions.cc:284
 msgid "Unknown action name: %1"
 msgstr "Unbekannte Aktionsbezeichnung: %1"
 
-#: gtk2_ardour/add_route_dialog.cc:40
-#: gtk2_ardour/add_route_dialog.cc:195
+#: gtk2_ardour/add_route_dialog.cc:41
+#: gtk2_ardour/add_route_dialog.cc:219
 msgid "Mono"
 msgstr "Mono"
 
-#: gtk2_ardour/add_route_dialog.cc:41
-#: gtk2_ardour/add_route_dialog.cc:197
+#: gtk2_ardour/add_route_dialog.cc:42
+#: gtk2_ardour/add_route_dialog.cc:221
 msgid "Stereo"
 msgstr "Stereo"
 
-#: gtk2_ardour/add_route_dialog.cc:42
+#: gtk2_ardour/add_route_dialog.cc:43
 msgid "3 Channels"
 msgstr "3 Kanäle"
 
-#: gtk2_ardour/add_route_dialog.cc:43
+#: gtk2_ardour/add_route_dialog.cc:44
 msgid "4 Channels"
 msgstr "4 Kanäle"
 
-#: gtk2_ardour/add_route_dialog.cc:44
+#: gtk2_ardour/add_route_dialog.cc:45
 msgid "6 Channels"
 msgstr "6 Kanäle"
 
-#: gtk2_ardour/add_route_dialog.cc:45
+#: gtk2_ardour/add_route_dialog.cc:46
 msgid "8 Channels"
 msgstr "8 Kanäle"
 
-#: gtk2_ardour/add_route_dialog.cc:46
+#: gtk2_ardour/add_route_dialog.cc:47
 msgid "Manual Setup"
 msgstr "Manuell"
 
-#: gtk2_ardour/add_route_dialog.cc:51
-#: gtk2_ardour/add_route_dialog.cc:176
-#: gtk2_ardour/editor.cc:128
-#: gtk2_ardour/editor.cc:3011
-#: gtk2_ardour/editor_actions.cc:288
-#: gtk2_ardour/time_axis_view.cc:589
+#: gtk2_ardour/add_route_dialog.cc:52
+#: gtk2_ardour/add_route_dialog.cc:200
+#: gtk2_ardour/time_axis_view.cc:592
 msgid "Normal"
 msgstr "Normal"
 
-#: gtk2_ardour/add_route_dialog.cc:52
-#: gtk2_ardour/add_route_dialog.cc:178
+#: gtk2_ardour/add_route_dialog.cc:53
+#: gtk2_ardour/add_route_dialog.cc:202
 msgid "Tape"
 msgstr "Tape"
 
-#: gtk2_ardour/add_route_dialog.cc:61
+#: gtk2_ardour/add_route_dialog.cc:62
 msgid "ardour: add track/bus"
 msgstr "ardour: Füge Spur/Bus hinzu"
 
-#: gtk2_ardour/add_route_dialog.cc:62
-#: gtk2_ardour/editor_route_list.cc:72
+#: gtk2_ardour/add_route_dialog.cc:63
 msgid "Tracks"
 msgstr "Audiospuren"
 
-#: gtk2_ardour/add_route_dialog.cc:63
-#: gtk2_ardour/editor_route_list.cc:69
+#: gtk2_ardour/add_route_dialog.cc:64
 msgid "Busses"
 msgstr "Busse"
 
-#: gtk2_ardour/add_route_dialog.cc:95
-#: gtk2_ardour/plugin_ui.cc:151
+#: gtk2_ardour/add_route_dialog.cc:113
+#: gtk2_ardour/plugin_ui.cc:220
 msgid "Add"
 msgstr "Hinzufügen"
 
-#: gtk2_ardour/add_route_dialog.cc:113
+#: gtk2_ardour/add_route_dialog.cc:131
 msgid "Name (template)"
 msgstr "Name für Mixer-Vorlage"
 
-#: gtk2_ardour/add_route_dialog.cc:119
+#: gtk2_ardour/add_route_dialog.cc:137
 msgid "Channel Configuration"
 msgstr "Kanaleinstellungen"
 
-#: gtk2_ardour/ardour_ui.cc:110
+#: gtk2_ardour/ardour_ui.cc:114
 msgid ""
 "pre\n"
 "roll"
@@ -341,7 +349,7 @@ msgstr ""
 "pre\n"
 "roll"
 
-#: gtk2_ardour/ardour_ui.cc:111
+#: gtk2_ardour/ardour_ui.cc:115
 msgid ""
 "post\n"
 "roll"
@@ -349,42 +357,42 @@ msgstr ""
 "post\n"
 "roll"
 
-#: gtk2_ardour/ardour_ui.cc:137
+#: gtk2_ardour/ardour_ui.cc:141
 msgid "% "
 msgstr ""
 
-#: gtk2_ardour/ardour_ui.cc:139
-#: gtk2_ardour/ardour_ui_ed.cc:294
+#: gtk2_ardour/ardour_ui.cc:143
+#: gtk2_ardour/ardour_ui_ed.cc:306
 msgid "Punch In"
 msgstr "Punch In"
 
-#: gtk2_ardour/ardour_ui.cc:140
-#: gtk2_ardour/ardour_ui_ed.cc:297
+#: gtk2_ardour/ardour_ui.cc:144
+#: gtk2_ardour/ardour_ui_ed.cc:309
 msgid "Punch Out"
 msgstr "Punch Out"
 
-#: gtk2_ardour/ardour_ui.cc:141
-#: gtk2_ardour/ardour_ui_ed.cc:309
+#: gtk2_ardour/ardour_ui.cc:145
+#: gtk2_ardour/ardour_ui_ed.cc:321
 msgid "Auto Return"
 msgstr "Auto Return"
 
-#: gtk2_ardour/ardour_ui.cc:142
-#: gtk2_ardour/ardour_ui_ed.cc:306
+#: gtk2_ardour/ardour_ui.cc:146
+#: gtk2_ardour/ardour_ui_ed.cc:318
 msgid "Auto Play"
 msgstr "Auto Play"
 
-#: gtk2_ardour/ardour_ui.cc:143
-#: gtk2_ardour/ardour_ui_ed.cc:303
+#: gtk2_ardour/ardour_ui.cc:147
+#: gtk2_ardour/ardour_ui_ed.cc:315
 msgid "Auto Input"
 msgstr "Auto Input"
 
-#: gtk2_ardour/ardour_ui.cc:144
-#: gtk2_ardour/ardour_ui_ed.cc:300
-#: gtk2_ardour/option_editor.cc:133
+#: gtk2_ardour/ardour_ui.cc:148
+#: gtk2_ardour/ardour_ui_ed.cc:312
+#: gtk2_ardour/option_editor.cc:147
 msgid "Click"
 msgstr "Click"
 
-#: gtk2_ardour/ardour_ui.cc:145
+#: gtk2_ardour/ardour_ui.cc:149
 msgid ""
 "time\n"
 "master"
@@ -392,15 +400,83 @@ msgstr ""
 "Time\n"
 "Master"
 
-#: gtk2_ardour/ardour_ui.cc:147
+#: gtk2_ardour/ardour_ui.cc:151
 msgid "AUDITION"
 msgstr "VORHÖREN"
 
-#: gtk2_ardour/ardour_ui.cc:148
+#: gtk2_ardour/ardour_ui.cc:152
 msgid "SOLO"
 msgstr "SOLO"
 
-#: gtk2_ardour/ardour_ui.cc:475
+#: gtk2_ardour/ardour_ui.cc:154
+msgid "Errors"
+msgstr "Fehlermeldungen"
+
+#: gtk2_ardour/ardour_ui.cc:237
+msgid "could not initialize Ardour."
+msgstr "Konnte ardour nicht initialisieren."
+
+#: gtk2_ardour/ardour_ui.cc:548
+msgid "Ardour could not start JACK"
+msgstr "Ardour konnte JACK nicht starten"
+
+#: gtk2_ardour/ardour_ui.cc:550
+msgid "Ardour could not connect to JACK."
+msgstr "ardour konnte nicht zu JACK verbinden."
+
+#: gtk2_ardour/ardour_ui.cc:559
+msgid ""
+"There are several possible reasons:\n"
+"\n"
+"1) You requested audio parameters that are not supported..\n"
+"2) JACK is running as another user.\n"
+"\n"
+"Please consider the possibilities, and perhaps try different parameters."
+msgstr ""
+"Dafür kann es verschiedene Gründe geben:\n"
+"\n"
+"1) Sie haben nicht unterstützte Audioeinstellungen gewählt.\n"
+"2) JACK wurde unter einem anderen Benutzer gestartet.\n"
+"\n"
+"Betrachten Sie bitte diese Möglichkeiten und verwenden sie ggf. andere Einstellungen."
+
+#: gtk2_ardour/ardour_ui.cc:566
+msgid ""
+"There are several possible reasons:\n"
+"\n"
+"1) JACK is not running.\n"
+"2) JACK is running as another user, perhaps root.\n"
+"3) There is already another client called \"ardour\".\n"
+"\n"
+"Please consider the possibilities, and perhaps (re)start JACK."
+msgstr ""
+"Dafür kann es verschiedene Gründe geben:\n"
+"\n"
+"1) JACK läuft nicht.\n"
+"2) JACK wurde unter einem anderen Benutzer gestartet, möglicherweise als root.\n"
+"3) Es gibt bereits einen anderen Client mit der Bezeichnung \"ardour\".\n"
+"\n"
+"Betrachten Sie bitte diese Möglichkeiten und starten Sie JACK neu, wenn dies notwendig sein sollte."
+
+#: gtk2_ardour/ardour_ui.cc:615
+msgid "Could not find command line session \"%1\""
+msgstr "Konnte das per Kommandozeile Ã¼bergebene Projekt nicht laden: \"%1\""
+
+#: gtk2_ardour/ardour_ui.cc:633
+msgid ""
+"\n"
+"\n"
+"No session named \"%1\" exists.\n"
+"To create it from the command line, start ardour as:\n"
+"   ardour --new %1"
+msgstr ""
+"\n"
+"\n"
+"Es existiert kein Projekt mit dem Namen \"%1\".\n"
+"Um es von der Kommandozeile aus zu erstellen, starten Sie ardour mit:\n"
+"   ardour --new %1"
+
+#: gtk2_ardour/ardour_ui.cc:702
 msgid ""
 "WARNING: Your system has a limit for maximum amount of locked memory. This might cause Ardour to run out of memory before your system runs out of memory. \n"
 "\n"
@@ -410,15 +486,15 @@ msgstr ""
 "\n"
 "Sie können die Speicherbegrenzung mit 'ulimit -l' einsehen und normalerweise in /etc/security/limits.conf verändern."
 
-#: gtk2_ardour/ardour_ui.cc:483
+#: gtk2_ardour/ardour_ui.cc:710
 msgid "Do not show this window again"
 msgstr "Diese Meldung nicht wieder anzeigen"
 
-#: gtk2_ardour/ardour_ui.cc:504
+#: gtk2_ardour/ardour_ui.cc:730
 msgid "quit"
 msgstr "Beenden"
 
-#: gtk2_ardour/ardour_ui.cc:513
+#: gtk2_ardour/ardour_ui.cc:739
 msgid ""
 "Ardour was unable to save your session.\n"
 "\n"
@@ -432,31 +508,31 @@ msgstr ""
 "\n"
 "\"Trotzdem beenden\"."
 
-#: gtk2_ardour/ardour_ui.cc:537
+#: gtk2_ardour/ardour_ui.cc:763
 msgid "ardour: save session?"
 msgstr "ardour: Projekt speichern?"
 
-#: gtk2_ardour/ardour_ui.cc:544
+#: gtk2_ardour/ardour_ui.cc:770
 msgid "Don't %1"
-msgstr "Nicht %1"
+msgstr "Abbrechen"
 
-#: gtk2_ardour/ardour_ui.cc:546
+#: gtk2_ardour/ardour_ui.cc:772
 msgid "Just %1"
-msgstr "Nur %1"
+msgstr "%1"
 
-#: gtk2_ardour/ardour_ui.cc:548
+#: gtk2_ardour/ardour_ui.cc:774
 msgid "Save and %1"
 msgstr "Speichern und %1"
 
-#: gtk2_ardour/ardour_ui.cc:560
+#: gtk2_ardour/ardour_ui.cc:786
 msgid "session"
 msgstr "Das Projekt"
 
-#: gtk2_ardour/ardour_ui.cc:562
+#: gtk2_ardour/ardour_ui.cc:788
 msgid "snapshot"
 msgstr "Der Schnappschuss"
 
-#: gtk2_ardour/ardour_ui.cc:564
+#: gtk2_ardour/ardour_ui.cc:790
 msgid ""
 "The %1\"%2\"\n"
 "has not been saved.\n"
@@ -472,87 +548,95 @@ msgstr ""
 "\n"
 "Wie wollen Sie vorgehen?"
 
-#: gtk2_ardour/ardour_ui.cc:578
+#: gtk2_ardour/ardour_ui.cc:804
 msgid "Prompter"
 msgstr "Frage"
 
-#: gtk2_ardour/ardour_ui.cc:638
+#: gtk2_ardour/ardour_ui.cc:866
 #, c-format
 msgid "disconnected"
 msgstr "getrennt"
 
-#: gtk2_ardour/ardour_ui.cc:645
+#: gtk2_ardour/ardour_ui.cc:873
 #, c-format
 msgid "%.1f kHz / %4.1f ms"
 msgstr "%.1f kHz / %4.1f ms"
 
-#: gtk2_ardour/ardour_ui.cc:649
+#: gtk2_ardour/ardour_ui.cc:877
 #, c-format
 msgid "%u kHz / %4.1f ms"
 msgstr "%u kHz / %4.1f ms"
 
-#: gtk2_ardour/ardour_ui.cc:662
+#: gtk2_ardour/ardour_ui.cc:890
 #, c-format
 msgid "DSP: %5.1f%%"
 msgstr "DSP: %5.1f%%"
 
-#: gtk2_ardour/ardour_ui.cc:672
+#: gtk2_ardour/ardour_ui.cc:900
 #, c-format
 msgid "Buffers p:%<PRIu32>%% c:%<PRIu32>%%"
 msgstr "Buffer p:%<PRIu32>%% c:%<PRIu32>%%"
 
-#: gtk2_ardour/ardour_ui.cc:700
+#: gtk2_ardour/ardour_ui.cc:928
 msgid "Disk: 24hrs+"
 msgstr "HD: >24 Std."
 
-#: gtk2_ardour/ardour_ui.cc:720
+#: gtk2_ardour/ardour_ui.cc:948
 #, c-format
 msgid "Disk: %02dh:%02dm:%02ds"
 msgstr "HD: %02dh:%02dm:%02ds"
 
-#: gtk2_ardour/ardour_ui.cc:833
-#: gtk2_ardour/new_session_dialog.cc:362
+#: gtk2_ardour/ardour_ui.cc:1061
+#: gtk2_ardour/new_session_dialog.cc:365
 msgid "Recent Sessions"
 msgstr "Zuletzt verwendete Projekte"
 
-#: gtk2_ardour/ardour_ui.cc:926
+#: gtk2_ardour/ardour_ui.cc:1150
+msgid ""
+"Ardour is not connected to JACK\n"
+"You cannot open or close sessions in this condition"
+msgstr ""
+"Ardour ist derzeit nicht mit JACK verbunden.\n"
+"Es ist nicht möglich, neue Projekte zu erstellen."
+
+#: gtk2_ardour/ardour_ui.cc:1174
 msgid "open session"
 msgstr "Projekt Ã¶ffnen"
 
-#: gtk2_ardour/ardour_ui.cc:932
+#: gtk2_ardour/ardour_ui.cc:1181
 msgid "Ardour sessions"
 msgstr "ardour-Projekte"
 
-#: gtk2_ardour/ardour_ui.cc:965
+#: gtk2_ardour/ardour_ui.cc:1214
 msgid "Patience is a virtue.\n"
 msgstr "Geduld ist eine Tugend.\n"
 
-#: gtk2_ardour/ardour_ui.cc:975
+#: gtk2_ardour/ardour_ui.cc:1224
 msgid "You cannot add a track or bus without a session already loaded."
 msgstr "Sie können erst Spuren oder Busse hinzufügen, wenn ein Projekt geladen wurde."
 
-#: gtk2_ardour/ardour_ui.cc:985
-#: gtk2_ardour/ardour_ui.cc:998
+#: gtk2_ardour/ardour_ui.cc:1234
+#: gtk2_ardour/ardour_ui.cc:1247
 msgid "could not create a new audio track"
 msgstr "Konnte neue Spur nicht erstellen."
 
-#: gtk2_ardour/ardour_ui.cc:987
+#: gtk2_ardour/ardour_ui.cc:1236
 msgid "could only create %1 of %2 new audio %3"
 msgstr "Konnte nur %1 von %2 neuen %3 erstellen"
 
-#: gtk2_ardour/ardour_ui.cc:988
+#: gtk2_ardour/ardour_ui.cc:1237
 msgid "tracks"
 msgstr "Spuren"
 
-#: gtk2_ardour/ardour_ui.cc:988
+#: gtk2_ardour/ardour_ui.cc:1237
 msgid "busses"
 msgstr "Audio-Bussen"
 
-#: gtk2_ardour/ardour_ui.cc:1000
+#: gtk2_ardour/ardour_ui.cc:1249
 msgid "could not create %1 new audio tracks"
 msgstr "Konnte %1 neue Spuren nicht erstellen."
 
-#: gtk2_ardour/ardour_ui.cc:1021
+#: gtk2_ardour/ardour_ui.cc:1270
 msgid ""
 "There are insufficient JACK ports available\n"
 "to create a new track or bus.\n"
@@ -565,7 +649,7 @@ msgstr ""
 "ardour sowie JACK mit einer größeren\n"
 "Anzahl Ports erneut."
 
-#: gtk2_ardour/ardour_ui.cc:1141
+#: gtk2_ardour/ardour_ui.cc:1390
 msgid ""
 "Please create 1 or more track\n"
 "before trying to record.\n"
@@ -575,7 +659,7 @@ msgstr ""
 "bevor Sie aufnehmen.\n"
 "Weitere Einstellungen finden Sie im Projektmenü."
 
-#: gtk2_ardour/ardour_ui.cc:1386
+#: gtk2_ardour/ardour_ui.cc:1645
 msgid ""
 "JACK has either been shutdown or it\n"
 "disconnected Ardour because Ardour\n"
@@ -587,39 +671,61 @@ msgstr ""
 "schnell genug war. Sie sollten versuchen,\n"
 "das Projekt zu speichern und erneut mit JACK zu verbinden."
 
-#: gtk2_ardour/ardour_ui.cc:1403
+#: gtk2_ardour/ardour_ui.cc:1662
 msgid "Unable to start the session running"
 msgstr "Konnte das aktuelle Projekt nicht starten"
 
-#: gtk2_ardour/ardour_ui.cc:1503
-#: gtk2_ardour/ardour_ui.cc:1522
-#: gtk2_ardour/audio_clock.cc:461
+#: gtk2_ardour/ardour_ui.cc:1753
+#: gtk2_ardour/ardour_ui.cc:1772
+#: gtk2_ardour/audio_clock.cc:508
 msgid "none"
 msgstr "keine"
 
-#: gtk2_ardour/ardour_ui.cc:1512
-#: gtk2_ardour/ardour_ui.cc:1531
+#: gtk2_ardour/ardour_ui.cc:1762
+#: gtk2_ardour/ardour_ui.cc:1781
 msgid "off"
 msgstr "aus"
 
-#: gtk2_ardour/ardour_ui.cc:1557
+#: gtk2_ardour/ardour_ui.cc:1807
 msgid "Name of New Snapshot"
 msgstr "Name für neuen Schnappschuss"
 
-#: gtk2_ardour/ardour_ui.cc:1697
+#: gtk2_ardour/ardour_ui.cc:1959
 msgid "Name for mix template:"
 msgstr "Name für Mixer-Vorlage"
 
-#: gtk2_ardour/ardour_ui.cc:1698
+#: gtk2_ardour/ardour_ui.cc:1960
 msgid "-template"
 msgstr "Vorlage"
 
-#: gtk2_ardour/ardour_ui.cc:1722
-#: gtk2_ardour/ardour_ui.cc:1739
-msgid "Ardour is not connected to JACK at this time. Creating new sessions is not possible."
-msgstr "Ardour ist derzeit nicht mit JACK verbunden. Es ist nicht möglich, neue Projekte zu erstellen."
+#: gtk2_ardour/ardour_ui.cc:1989
+msgid ""
+"Welcome to Ardour.\n"
+"\n"
+"The program will take a bit longer to start up\n"
+"while the system fonts are checked.\n"
+"\n"
+"This will only be done once, and you will\n"
+"not see this message again\n"
+msgstr ""
+"Willkommen bei Ardour.\n"
+"\n"
+"Der Programmstart wird etwas länger dauern,\n"
+"da die Systemschriften geprüft werden.\n"
+"\n"
+"Diese Meldung wird nur dieses eine Mal\n"
+"auftauchen.\n"
+
+#: gtk2_ardour/ardour_ui.cc:2039
+msgid "Ardour cannot understand \"%1\" as a session name"
+msgstr "Ardour kann \"%1\" nicht als Projektnamen benutzen"
 
-#: gtk2_ardour/ardour_ui.cc:1832
+#: gtk2_ardour/ardour_ui.cc:2074
+#: gtk2_ardour/ardour_ui.cc:2131
+msgid "Starting audio engine"
+msgstr "Starte Audio Engine"
+
+#: gtk2_ardour/ardour_ui.cc:2249
 msgid ""
 "This session\n"
 "%1\n"
@@ -629,7 +735,7 @@ msgstr ""
 "%1\n"
 "existiert bereits. Wollen Sie sie Ã¶ffnen?"
 
-#: gtk2_ardour/ardour_ui.cc:1955
+#: gtk2_ardour/ardour_ui.cc:2430
 msgid ""
 "You do not have write access to this session.\n"
 "This prevents the session from being loaded."
@@ -637,19 +743,32 @@ msgstr ""
 "Sie haben keinen Schreibzugriff auf dieses Projekt.\n"
 "Dadurch kann das Projekt nicht geladen werden."
 
-#: gtk2_ardour/ardour_ui.cc:1967
+#: gtk2_ardour/ardour_ui.cc:2437
+msgid "Please wait while Ardour loads your session"
+msgstr "Bitte warten Sie, während Ardour das Projekt lädt"
+
+#: gtk2_ardour/ardour_ui.cc:2448
 msgid "Session \"%1 (snapshot %2)\" did not load successfully"
 msgstr "Projekt  \"%1 (Schnappschuss %2)\" konnte nicht geladen werden."
 
-#: gtk2_ardour/ardour_ui.cc:2017
+#: gtk2_ardour/ardour_ui.cc:2453
+#, fuzzy
+msgid "Loading Error"
+msgstr "Programmierfehler:"
+
+#: gtk2_ardour/ardour_ui.cc:2454
+msgid "Click the OK button to try again."
+msgstr "Klicken Sie auf OK, um es erneut zu versuchen."
+
+#: gtk2_ardour/ardour_ui.cc:2527
 msgid "Could not create session in \"%1\""
 msgstr "Konnte kein Projekt in \"%1\" anlegen"
 
-#: gtk2_ardour/ardour_ui.cc:2077
+#: gtk2_ardour/ardour_ui.cc:2587
 msgid "No audio files were ready for cleanup"
 msgstr "Keine Audiodateien zum Aufräumen vorhanden"
 
-#: gtk2_ardour/ardour_ui.cc:2081
+#: gtk2_ardour/ardour_ui.cc:2591
 msgid ""
 "If this seems suprising, \n"
 "check for any existing snapshots.\n"
@@ -661,25 +780,25 @@ msgstr ""
 "sind sie wahrscheinlich noch in einem\n"
 "älteren Schnappschuss als Region eingebunden."
 
-#: gtk2_ardour/ardour_ui.cc:2090
+#: gtk2_ardour/ardour_ui.cc:2600
 msgid "ardour: cleanup"
 msgstr "ardour: Aufräumen"
 
-#: gtk2_ardour/ardour_ui.cc:2126
-#: gtk2_ardour/ardour_ui.cc:2132
+#: gtk2_ardour/ardour_ui.cc:2636
+#: gtk2_ardour/ardour_ui.cc:2642
 msgid "files were"
 msgstr "folgenden Dateien wurden"
 
-#: gtk2_ardour/ardour_ui.cc:2128
-#: gtk2_ardour/ardour_ui.cc:2134
+#: gtk2_ardour/ardour_ui.cc:2638
+#: gtk2_ardour/ardour_ui.cc:2644
 msgid "file was"
 msgstr "folgende Datei wurde"
 
-#: gtk2_ardour/ardour_ui.cc:2175
+#: gtk2_ardour/ardour_ui.cc:2685
 msgid "Are you sure you want to cleanup?"
 msgstr "Sind Sie sicher, dass Sie aufräumen wollen?"
 
-#: gtk2_ardour/ardour_ui.cc:2180
+#: gtk2_ardour/ardour_ui.cc:2690
 msgid ""
 "Cleanup is a destructive operation.\n"
 "ALL undo/redo information will be lost if you cleanup.\n"
@@ -689,19 +808,19 @@ msgstr ""
 "Sämtliche Wiederherstellungsinformationen gehen verloren, wenn Sie aufräumen.\n"
 "Nach dem Aufräumen werden alle nicht benötigten Audiodateien in einen \"dead sounds\" Ordner verschoben."
 
-#: gtk2_ardour/ardour_ui.cc:2186
+#: gtk2_ardour/ardour_ui.cc:2696
 msgid "Clean Up"
 msgstr "Aufräumen"
 
-#: gtk2_ardour/ardour_ui.cc:2189
+#: gtk2_ardour/ardour_ui.cc:2699
 msgid "CleanupDialog"
 msgstr ""
 
-#: gtk2_ardour/ardour_ui.cc:2217
+#: gtk2_ardour/ardour_ui.cc:2727
 msgid "cleaned files"
 msgstr "aufgeräumte Dateien"
 
-#: gtk2_ardour/ardour_ui.cc:2218
+#: gtk2_ardour/ardour_ui.cc:2728
 msgid ""
 "The following %1 %2 not in use and \n"
 "have been moved to:\n"
@@ -718,11 +837,11 @@ msgstr ""
 "Wenn Sie den Müll leeren werden weitere\n"
 "%4 %5byte Speicherplatz frei.\n"
 
-#: gtk2_ardour/ardour_ui.cc:2246
+#: gtk2_ardour/ardour_ui.cc:2756
 msgid "deleted file"
 msgstr "gelöschte Datei"
 
-#: gtk2_ardour/ardour_ui.cc:2247
+#: gtk2_ardour/ardour_ui.cc:2757
 msgid ""
 "The following %1 %2 deleted from\n"
 "%3,\n"
@@ -732,11 +851,11 @@ msgstr ""
 "%3,\n"
 "und machten %4 %5byte Speicherplatz frei"
 
-#: gtk2_ardour/ardour_ui.cc:2365
+#: gtk2_ardour/ardour_ui.cc:2875
 msgid "Recording was stopped because your system could not keep up."
 msgstr "Die Aufnahme wurde gestoppt, da Ihr System nicht schnell genug folgen konnte."
 
-#: gtk2_ardour/ardour_ui.cc:2376
+#: gtk2_ardour/ardour_ui.cc:2886
 msgid ""
 "The disk system on your computer\n"
 "was not able to keep up with Ardour.\n"
@@ -750,7 +869,7 @@ msgstr ""
 "Die Daten konnten nicht schnell genug geschrieben\n"
 "werden, um die Aufnahme fortzuführen.\n"
 
-#: gtk2_ardour/ardour_ui.cc:2395
+#: gtk2_ardour/ardour_ui.cc:2905
 msgid ""
 "The disk system on your computer\n"
 "was not able to keep up with Ardour.\n"
@@ -764,7 +883,7 @@ msgstr ""
 "Die Daten konnten nicht schnell genug gelesen\n"
 "werden, um die Wiedergabe aufrechtzuerhalten.\n"
 
-#: gtk2_ardour/ardour_ui.cc:2416
+#: gtk2_ardour/ardour_ui.cc:2926
 msgid ""
 "This session appears to have been in\n"
 "middle of recording when ardour or\n"
@@ -782,19 +901,19 @@ msgstr ""
 "für Sie wiederherstellen oder sie verwerfen.\n"
 "Bitte entscheiden Sie, wie Sie vorgehen möchten.\n"
 
-#: gtk2_ardour/ardour_ui.cc:2426
+#: gtk2_ardour/ardour_ui.cc:2936
 msgid "Recover from crash"
 msgstr "Daten wiederherstellen"
 
-#: gtk2_ardour/ardour_ui.cc:2427
+#: gtk2_ardour/ardour_ui.cc:2937
 msgid "Ignore crash data"
 msgstr "Daten verwerfen"
 
-#: gtk2_ardour/ardour_ui.cc:2445
+#: gtk2_ardour/ardour_ui.cc:2955
 msgid "Could not disconnect from JACK"
 msgstr "Konnte Verbindung mit JACK nicht trennen"
 
-#: gtk2_ardour/ardour_ui.cc:2458
+#: gtk2_ardour/ardour_ui.cc:2968
 msgid "Could not reconnect to JACK"
 msgstr "Konnte nicht erneut zu JACK verbinden"
 
@@ -806,84 +925,96 @@ msgstr "Der Editor konnte nicht initialisiert werden."
 msgid "UI: cannot setup mixer"
 msgstr "Der Mixer konnte nicht initialisiert werden."
 
-#: gtk2_ardour/ardour_ui2.cc:243
+#: gtk2_ardour/ardour_ui2.cc:110
+msgid "[ERROR]: "
+msgstr "[FEHLER]:"
+
+#: gtk2_ardour/ardour_ui2.cc:112
+msgid "[WARNING]: "
+msgstr "[WARNUNG]:"
+
+#: gtk2_ardour/ardour_ui2.cc:114
+msgid "[INFO]: "
+msgstr "[INFO]: "
+
+#: gtk2_ardour/ardour_ui2.cc:282
 msgid "Play from playhead"
 msgstr "Wiedergabe ab Positionszeiger"
 
-#: gtk2_ardour/ardour_ui2.cc:244
+#: gtk2_ardour/ardour_ui2.cc:283
 msgid "Stop playback"
 msgstr "Wiedergabe anhalten"
 
-#: gtk2_ardour/ardour_ui2.cc:245
+#: gtk2_ardour/ardour_ui2.cc:284
 msgid "Play range/selection"
 msgstr "Bereich/Auswahl wiedergeben"
 
-#: gtk2_ardour/ardour_ui2.cc:246
+#: gtk2_ardour/ardour_ui2.cc:285
 msgid "Go to start of session"
 msgstr "Zum Anfang des Projekts springen"
 
-#: gtk2_ardour/ardour_ui2.cc:247
+#: gtk2_ardour/ardour_ui2.cc:286
 msgid "Go to end of session"
 msgstr "Zum Ende des Projekts springen"
 
-#: gtk2_ardour/ardour_ui2.cc:248
+#: gtk2_ardour/ardour_ui2.cc:287
 msgid "Play loop range"
 msgstr "Schleife wiedergeben"
 
-#: gtk2_ardour/ardour_ui2.cc:250
+#: gtk2_ardour/ardour_ui2.cc:289
 msgid "Return to last playback start when stopped"
 msgstr "Bei Stop zum letzten Wiedergabeanfang springen"
 
-#: gtk2_ardour/ardour_ui2.cc:251
+#: gtk2_ardour/ardour_ui2.cc:290
 msgid "Start playback after any locate"
 msgstr "Startet die Wiedergabe nach setzen des Positionszeigers"
 
-#: gtk2_ardour/ardour_ui2.cc:252
+#: gtk2_ardour/ardour_ui2.cc:291
 msgid "Be sensible about input monitoring"
 msgstr "Automatisches Input Monitoring aktivieren"
 
-#: gtk2_ardour/ardour_ui2.cc:253
+#: gtk2_ardour/ardour_ui2.cc:292
 msgid "Start recording at auto-punch start"
 msgstr "Beginnt die Aufnahme bei Auto-Punch Start"
 
-#: gtk2_ardour/ardour_ui2.cc:254
+#: gtk2_ardour/ardour_ui2.cc:293
 msgid "Stop recording at auto-punch end"
 msgstr "Beginnt die Aufnahme bei Auto-Punch Ende"
 
-#: gtk2_ardour/ardour_ui2.cc:255
+#: gtk2_ardour/ardour_ui2.cc:294
 msgid "Enable/Disable audio click"
 msgstr "Aktiviert/Deaktiviert Audio Click"
 
-#: gtk2_ardour/ardour_ui2.cc:256
+#: gtk2_ardour/ardour_ui2.cc:295
 msgid "Positional sync source"
 msgstr "Positionsbezogene Sync-quelle"
 
-#: gtk2_ardour/ardour_ui2.cc:257
+#: gtk2_ardour/ardour_ui2.cc:296
 msgid "Does Ardour control the time?"
 msgstr "Bestimmt ardour die Time?"
 
-#: gtk2_ardour/ardour_ui2.cc:258
+#: gtk2_ardour/ardour_ui2.cc:297
 msgid "Shuttle speed control"
 msgstr "Shuttle-Geschwindigkeit"
 
-#: gtk2_ardour/ardour_ui2.cc:259
+#: gtk2_ardour/ardour_ui2.cc:298
 #, c-format
 msgid "Select semitones or %%-age for speed display"
 msgstr "Geschwindigkeitsanzeige als Prozent oder Halbtöne einstellen"
 
-#: gtk2_ardour/ardour_ui2.cc:260
+#: gtk2_ardour/ardour_ui2.cc:299
 msgid "Current transport speed"
 msgstr "Geschwindigkeitsanzeige"
 
-#: gtk2_ardour/ardour_ui2.cc:280
+#: gtk2_ardour/ardour_ui2.cc:320
 msgid "Primary clock"
-msgstr "Primärer Zeitgeber"
+msgstr "Primäre Zeitanzeige"
 
-#: gtk2_ardour/ardour_ui2.cc:281
+#: gtk2_ardour/ardour_ui2.cc:321
 msgid "secondary clock"
-msgstr "Sekundärer Zeitgeber"
+msgstr "Sekundäre Zeitanzeige"
 
-#: gtk2_ardour/ardour_ui2.cc:307
+#: gtk2_ardour/ardour_ui2.cc:347
 msgid ""
 "When active, something is soloed.\n"
 "Click to de-solo everything"
@@ -891,7 +1022,7 @@ msgstr ""
 "Wird aktiv, wenn eine Spur Solo läuft.\n"
 "Schaltet bei Klick Solo aus."
 
-#: gtk2_ardour/ardour_ui2.cc:308
+#: gtk2_ardour/ardour_ui2.cc:348
 msgid ""
 "When active, auditioning is taking place\n"
 "Click to stop the audition"
@@ -899,972 +1030,1057 @@ msgstr ""
 "Wird beim Vorhören aktiv.\n"
 "Klicken stoppt das Vorhören."
 
-#: gtk2_ardour/ardour_ui2.cc:336
-#: gtk2_ardour/ardour_ui2.cc:775
-#: gtk2_ardour/ardour_ui2.cc:831
-#: gtk2_ardour/ardour_ui_options.cc:910
+#: gtk2_ardour/ardour_ui2.cc:376
+#: gtk2_ardour/ardour_ui2.cc:826
+#: gtk2_ardour/ardour_ui2.cc:882
+#: gtk2_ardour/ardour_ui_options.cc:1064
 msgid "sprung"
 msgstr "Feder"
 
-#: gtk2_ardour/ardour_ui2.cc:337
-#: gtk2_ardour/ardour_ui2.cc:777
-#: gtk2_ardour/ardour_ui_options.cc:921
+#: gtk2_ardour/ardour_ui2.cc:377
+#: gtk2_ardour/ardour_ui2.cc:828
+#: gtk2_ardour/ardour_ui_options.cc:1075
 msgid "wheel"
 msgstr "Drehrad"
 
-#: gtk2_ardour/ardour_ui2.cc:545
+#: gtk2_ardour/ardour_ui2.cc:596
 msgid "Maximum speed"
 msgstr "Max. Geschwindigkeit"
 
-#: gtk2_ardour/ardour_ui2.cc:787
-#: gtk2_ardour/ardour_ui2.cc:810
+#: gtk2_ardour/ardour_ui2.cc:838
+#: gtk2_ardour/ardour_ui2.cc:861
 msgid "stop"
 msgstr "Stop"
 
-#: gtk2_ardour/ardour_ui2.cc:829
+#: gtk2_ardour/ardour_ui2.cc:880
 msgid "-0.55"
 msgstr "-0.55"
 
-#: gtk2_ardour/ardour_ui_dependents.cc:84
+#: gtk2_ardour/ardour_ui_dependents.cc:85
 msgid "Ardour key bindings file not found at \"%1\" or contains errors."
 msgstr "Konnte die Datei mit den Tastaturzuweisungen nicht an der Stelle \"%1\" finden, oder sie ist fehlerhaft."
 
-#: gtk2_ardour/ardour_ui_dialogs.cc:165
+#: gtk2_ardour/ardour_ui_dialogs.cc:170
 #: gtk2_ardour/playlist_selector.cc:73
 msgid "close"
 msgstr "Schließen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:81
+#: gtk2_ardour/ardour_ui_ed.cc:84
 msgid "Session"
 msgstr "Projekt"
 
-#: gtk2_ardour/ardour_ui_ed.cc:82
-#: gtk2_ardour/ardour_ui_ed.cc:143
-#: gtk2_ardour/editor.cc:1625
-#: gtk2_ardour/export_dialog.cc:125
-#: gtk2_ardour/export_dialog.cc:352
-#: gtk2_ardour/export_dialog.cc:1061
-#: gtk2_ardour/export_dialog.cc:1065
-msgid "Export"
-msgstr "Exportieren"
+#: gtk2_ardour/ardour_ui_ed.cc:85
+msgid "Import/Export"
+msgstr "Import/Export"
 
-#: gtk2_ardour/ardour_ui_ed.cc:83
+#: gtk2_ardour/ardour_ui_ed.cc:86
+#: gtk2_ardour/editor.cc:576
+#: gtk2_ardour/editor.cc:647
+msgid "Regions"
+msgstr "Regionen"
+
+#: gtk2_ardour/ardour_ui_ed.cc:87
 msgid "Cleanup"
 msgstr "Aufräumen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:84
-#: gtk2_ardour/option_editor.cc:130
+#: gtk2_ardour/ardour_ui_ed.cc:88
+#: gtk2_ardour/option_editor.cc:144
 msgid "Sync"
 msgstr "Sync"
 
-#: gtk2_ardour/ardour_ui_ed.cc:85
-#: gtk2_ardour/ardour_ui_ed.cc:86
+#: gtk2_ardour/ardour_ui_ed.cc:89
+#: gtk2_ardour/ardour_ui_ed.cc:90
+#: gtk2_ardour/engine_dialog.cc:343
 msgid "Options"
 msgstr "Optionen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:87
+#: gtk2_ardour/ardour_ui_ed.cc:91
 msgid "Help"
 msgstr "Hilfe"
 
-#: gtk2_ardour/ardour_ui_ed.cc:88
+#: gtk2_ardour/ardour_ui_ed.cc:92
 msgid "KeyMouse Actions"
 msgstr "Tastatur/Maus-Befehle"
 
-#: gtk2_ardour/ardour_ui_ed.cc:89
+#: gtk2_ardour/ardour_ui_ed.cc:93
 msgid "Audio File Format"
 msgstr "Audio-Dateiformat"
 
-#: gtk2_ardour/ardour_ui_ed.cc:90
+#: gtk2_ardour/ardour_ui_ed.cc:94
 msgid "Header"
 msgstr "Header"
 
-#: gtk2_ardour/ardour_ui_ed.cc:91
+#: gtk2_ardour/ardour_ui_ed.cc:95
 msgid "Data"
 msgstr "Datenformat"
 
-#: gtk2_ardour/ardour_ui_ed.cc:92
+#: gtk2_ardour/ardour_ui_ed.cc:96
 msgid "Control Surfaces"
 msgstr "Eingabegeräte / Controller"
 
-#: gtk2_ardour/ardour_ui_ed.cc:93
+#: gtk2_ardour/ardour_ui_ed.cc:97
 msgid "Metering"
 msgstr "Pegelanzeige"
 
-#: gtk2_ardour/ardour_ui_ed.cc:94
+#: gtk2_ardour/ardour_ui_ed.cc:98
 msgid "Fall off rate"
 msgstr "Abfall der Pegelanzeige"
 
-#: gtk2_ardour/ardour_ui_ed.cc:95
+#: gtk2_ardour/ardour_ui_ed.cc:99
 msgid "Hold Time"
 msgstr "Pegelanzeige halten"
 
-#: gtk2_ardour/ardour_ui_ed.cc:99
-#: gtk2_ardour/route_time_axis.cc:1308
-#: gtk2_ardour/new_session_dialog.cc:619
+#: gtk2_ardour/ardour_ui_ed.cc:100
+msgid "Denormal Handling"
+msgstr "Umgang mit Denormals"
+
+#: gtk2_ardour/ardour_ui_ed.cc:104
+#: gtk2_ardour/route_time_axis.cc:1343
 msgid "New"
 msgstr "Neu"
 
-#: gtk2_ardour/ardour_ui_ed.cc:101
-#: gtk2_ardour/new_session_dialog.cc:606
+#: gtk2_ardour/ardour_ui_ed.cc:106
 msgid "Open"
 msgstr "Öffnen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:102
+#: gtk2_ardour/ardour_ui_ed.cc:107
 msgid "Recent"
 msgstr "Zuletzt verwendet..."
 
-#: gtk2_ardour/ardour_ui_ed.cc:103
+#: gtk2_ardour/ardour_ui_ed.cc:108
 #: gtk2_ardour/io_selector.cc:59
 #: gtk2_ardour/io_selector.cc:747
 #: gtk2_ardour/connection_editor.cc:58
 msgid "Close"
 msgstr "Schließen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:106
+#: gtk2_ardour/ardour_ui_ed.cc:111
 #: gtk2_ardour/route_params_ui.cc:513
 msgid "Add Track/Bus"
 msgstr "Spur/Bus hinzufügen..."
 
-#: gtk2_ardour/ardour_ui_ed.cc:118
+#: gtk2_ardour/ardour_ui_ed.cc:123
 msgid "Connect"
 msgstr "Verbinden"
 
-#: gtk2_ardour/ardour_ui_ed.cc:126
+#: gtk2_ardour/ardour_ui_ed.cc:131
 msgid "Snapshot"
 msgstr "Schnappschuss..."
 
-#: gtk2_ardour/ardour_ui_ed.cc:129
+#: gtk2_ardour/ardour_ui_ed.cc:134
 msgid "Save Template..."
 msgstr "Als Vorlage Speichern..."
 
-#: gtk2_ardour/ardour_ui_ed.cc:132
+#: gtk2_ardour/ardour_ui_ed.cc:137
 msgid "Export session to audiofile..."
 msgstr "Exportiere Projekt als Audio-Datei..."
 
-#: gtk2_ardour/ardour_ui_ed.cc:135
+#: gtk2_ardour/ardour_ui_ed.cc:140
 msgid "Export selection to audiofile..."
-msgstr "Exportiere Auswahl als Audio-Datei..."
+msgstr "Exportiere Auswahlbereich als Audio-Datei..."
 
-#: gtk2_ardour/ardour_ui_ed.cc:139
+#: gtk2_ardour/ardour_ui_ed.cc:144
 msgid "Export range markers to audiofile..."
-msgstr "Exportiere Bereich als Audio-Datei..."
+msgstr "Exportiere Bereiche als Audio-Datei..."
+
+#: gtk2_ardour/ardour_ui_ed.cc:148
+#: gtk2_ardour/editor.cc:1724
+#: gtk2_ardour/export_dialog.cc:125
+#: gtk2_ardour/export_dialog.cc:374
+#: gtk2_ardour/export_dialog.cc:1122
+#: gtk2_ardour/export_dialog.cc:1126
+msgid "Export"
+msgstr "Exportieren"
 
-#: gtk2_ardour/ardour_ui_ed.cc:146
+#: gtk2_ardour/ardour_ui_ed.cc:151
 msgid "Cleanup unused sources"
 msgstr "Nicht benutzte Dateien entfernen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:148
+#: gtk2_ardour/ardour_ui_ed.cc:153
 msgid "Flush wastebasket"
 msgstr "Müll leeren"
 
-#: gtk2_ardour/ardour_ui_ed.cc:154
+#: gtk2_ardour/ardour_ui_ed.cc:159
 msgid "JACK"
 msgstr "JACK"
 
-#: gtk2_ardour/ardour_ui_ed.cc:155
+#: gtk2_ardour/ardour_ui_ed.cc:160
 msgid "Latency"
 msgstr "Latenz"
 
-#: gtk2_ardour/ardour_ui_ed.cc:157
+#: gtk2_ardour/ardour_ui_ed.cc:162
 msgid "Reconnect"
 msgstr "Neu Verbinden"
 
-#: gtk2_ardour/ardour_ui_ed.cc:160
-#: gtk2_ardour/mixer_strip.cc:510
-#: gtk2_ardour/mixer_strip.cc:572
+#: gtk2_ardour/ardour_ui_ed.cc:165
+#: gtk2_ardour/mixer_strip.cc:504
+#: gtk2_ardour/mixer_strip.cc:566
 msgid "Disconnect"
 msgstr "Trennen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:187
+#: gtk2_ardour/ardour_ui_ed.cc:192
 msgid "Windows"
 msgstr "Fenster"
 
-#: gtk2_ardour/ardour_ui_ed.cc:188
+#: gtk2_ardour/ardour_ui_ed.cc:193
 msgid "Quit"
 msgstr "Beenden"
 
-#: gtk2_ardour/ardour_ui_ed.cc:192
+#: gtk2_ardour/ardour_ui_ed.cc:197
 msgid "Maximise Editor Space"
 msgstr "Editor Maximieren"
 
-#: gtk2_ardour/ardour_ui_ed.cc:194
+#: gtk2_ardour/ardour_ui_ed.cc:199
 msgid "Show Editor"
 msgstr "Editor anzeigen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:195
+#: gtk2_ardour/ardour_ui_ed.cc:200
 msgid "Show Mixer"
 msgstr "Mixer anzeigen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:196
-#: gtk2_ardour/option_editor.cc:103
-msgid "Options Editor"
+#: gtk2_ardour/ardour_ui_ed.cc:201
+#: gtk2_ardour/option_editor.cc:117
+msgid "Preferences"
 msgstr "Einstellungen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:197
+#: gtk2_ardour/ardour_ui_ed.cc:202
 #: gtk2_ardour/route_params_ui.cc:143
 #: gtk2_ardour/route_params_ui.cc:659
 msgid "Track/Bus Inspector"
 msgstr "Verbindungen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:199
+#: gtk2_ardour/ardour_ui_ed.cc:204
 #: gtk2_ardour/connection_editor.cc:146
 #: gtk2_ardour/connection_editor.cc:147
 msgid "Connections"
 msgstr "Verbindungen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:201
-#: gtk2_ardour/location_ui.cc:577
+#: gtk2_ardour/ardour_ui_ed.cc:206
+#: gtk2_ardour/location_ui.cc:611
 msgid "Locations"
 msgstr "Positionen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:203
+#: gtk2_ardour/ardour_ui_ed.cc:208
 msgid "Big Clock"
 msgstr "Große Zeitanzeige"
 
-#: gtk2_ardour/ardour_ui_ed.cc:205
+#: gtk2_ardour/ardour_ui_ed.cc:210
 msgid "About"
 msgstr "Ãœber ardour..."
 
-#: gtk2_ardour/ardour_ui_ed.cc:206
-msgid "Colors"
-msgstr "Farben"
+#: gtk2_ardour/ardour_ui_ed.cc:211
+msgid "Theme Manager"
+msgstr "Thema"
 
-#: gtk2_ardour/ardour_ui_ed.cc:208
+#: gtk2_ardour/ardour_ui_ed.cc:212
+msgid "Keybindings"
+msgstr "Tastaturbefehle"
+
+#: gtk2_ardour/ardour_ui_ed.cc:214
 msgid "Add Audio Track"
 msgstr "Audiospur hinzufügen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:210
+#: gtk2_ardour/ardour_ui_ed.cc:216
 msgid "Add Audio Bus"
 msgstr "Audio-Bus hinzufügen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:212
+#: gtk2_ardour/ardour_ui_ed.cc:218
 msgid "Save"
 msgstr "Speichern"
 
-#: gtk2_ardour/ardour_ui_ed.cc:214
-#: gtk2_ardour/editor_actions.cc:258
+#: gtk2_ardour/ardour_ui_ed.cc:220
+#: gtk2_ardour/editor_actions.cc:377
 msgid "Remove Last Capture"
 msgstr "Letzte Aufnahme entfernen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:221
+#: gtk2_ardour/ardour_ui_ed.cc:227
 msgid "Transport"
 msgstr "Transport"
 
-#: gtk2_ardour/ardour_ui_ed.cc:227
-#: gtk2_ardour/sfdb_ui.cc:62
+#: gtk2_ardour/ardour_ui_ed.cc:233
+#: gtk2_ardour/engine_dialog.cc:56
+#: gtk2_ardour/sfdb_ui.cc:178
 msgid "Stop"
 msgstr "Stop"
 
-#: gtk2_ardour/ardour_ui_ed.cc:230
+#: gtk2_ardour/ardour_ui_ed.cc:236
 msgid "Roll"
 msgstr "Wiedergabe"
 
-#: gtk2_ardour/ardour_ui_ed.cc:234
+#: gtk2_ardour/ardour_ui_ed.cc:240
 msgid "Start/Stop"
 msgstr "Start/Stop"
 
-#: gtk2_ardour/ardour_ui_ed.cc:237
+#: gtk2_ardour/ardour_ui_ed.cc:243
 msgid "Stop + Forget Capture"
 msgstr "Stop + Aufnahme verwerfen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:247
+#: gtk2_ardour/ardour_ui_ed.cc:253
 msgid "Transition To Roll"
-msgstr "Ãœbergang zu Roll"
+msgstr "Vorwärts wiedergeben"
 
-#: gtk2_ardour/ardour_ui_ed.cc:251
+#: gtk2_ardour/ardour_ui_ed.cc:257
 msgid "Transition To Reverse"
-msgstr "Ãœbergang zu Rückwärts"
+msgstr "Rückwärts wiedergeben"
 
-#: gtk2_ardour/ardour_ui_ed.cc:256
+#: gtk2_ardour/ardour_ui_ed.cc:262
 msgid "Play Loop Range"
 msgstr "Schleife wiedergeben"
 
-#: gtk2_ardour/ardour_ui_ed.cc:259
+#: gtk2_ardour/ardour_ui_ed.cc:265
 msgid "Play Selection"
-msgstr "Auswahl wiedergeben"
+msgstr "Ausgewählten Bereich wiedergeben"
 
-#: gtk2_ardour/ardour_ui_ed.cc:263
+#: gtk2_ardour/ardour_ui_ed.cc:269
 msgid "Enable Record"
 msgstr "Aufnahme aktivieren"
 
-#: gtk2_ardour/ardour_ui_ed.cc:266
+#: gtk2_ardour/ardour_ui_ed.cc:271
+msgid "Start Recording"
+msgstr "Aufnahme beginnen"
+
+#: gtk2_ardour/ardour_ui_ed.cc:274
 msgid "Rewind"
 msgstr "Rückwärts"
 
-#: gtk2_ardour/ardour_ui_ed.cc:269
+#: gtk2_ardour/ardour_ui_ed.cc:277
 msgid "Rewind (Slow)"
 msgstr "Rückwärts (langsam)"
 
-#: gtk2_ardour/ardour_ui_ed.cc:272
+#: gtk2_ardour/ardour_ui_ed.cc:280
 msgid "Rewind (Fast)"
 msgstr "Rückwärts (schnell)"
 
-#: gtk2_ardour/ardour_ui_ed.cc:275
+#: gtk2_ardour/ardour_ui_ed.cc:283
 msgid "Forward"
 msgstr "Vorwärts"
 
-#: gtk2_ardour/ardour_ui_ed.cc:278
+#: gtk2_ardour/ardour_ui_ed.cc:286
 msgid "Forward (Slow)"
 msgstr "Vorwärts (langsam)"
 
-#: gtk2_ardour/ardour_ui_ed.cc:281
+#: gtk2_ardour/ardour_ui_ed.cc:289
 msgid "Forward (Fast)"
 msgstr "Vorwärts (schnell)"
 
-#: gtk2_ardour/ardour_ui_ed.cc:284
+#: gtk2_ardour/ardour_ui_ed.cc:292
 msgid "Goto Zero"
 msgstr "Zum Nullpunkt springen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:287
+#: gtk2_ardour/ardour_ui_ed.cc:295
 msgid "Goto Start"
 msgstr "Zum Anfang springen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:290
+#: gtk2_ardour/ardour_ui_ed.cc:298
 msgid "Goto End"
 msgstr "Zum Ende Springen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:313
+#: gtk2_ardour/ardour_ui_ed.cc:302
+msgid "Focus On Clock"
+msgstr "Fokus auf Zeitanzeige setzen"
+
+#: gtk2_ardour/ardour_ui_ed.cc:325
 msgid "Sync startup to video"
 msgstr "Mit Video synchronisieren"
 
-#: gtk2_ardour/ardour_ui_ed.cc:314
+#: gtk2_ardour/ardour_ui_ed.cc:326
 msgid "Time master"
 msgstr "Time Master"
 
-#: gtk2_ardour/ardour_ui_ed.cc:317
+#: gtk2_ardour/ardour_ui_ed.cc:329
 msgid "Toggle Record Enable Track1"
 msgstr "Aufnahme aktivieren für Spur 1"
 
-#: gtk2_ardour/ardour_ui_ed.cc:319
+#: gtk2_ardour/ardour_ui_ed.cc:331
 msgid "Toggle Record Enable Track2"
 msgstr "Aufnahme aktivieren für Spur 2"
 
-#: gtk2_ardour/ardour_ui_ed.cc:321
+#: gtk2_ardour/ardour_ui_ed.cc:333
 msgid "Toggle Record Enable Track3"
 msgstr "Aufnahme aktivieren für Spur 3"
 
-#: gtk2_ardour/ardour_ui_ed.cc:323
+#: gtk2_ardour/ardour_ui_ed.cc:335
 msgid "Toggle Record Enable Track4"
 msgstr "Aufnahme aktivieren für Spur 4"
 
-#: gtk2_ardour/ardour_ui_ed.cc:325
+#: gtk2_ardour/ardour_ui_ed.cc:337
 msgid "Toggle Record Enable Track5"
 msgstr "Aufnahme aktivieren für Spur 5"
 
-#: gtk2_ardour/ardour_ui_ed.cc:327
+#: gtk2_ardour/ardour_ui_ed.cc:339
 msgid "Toggle Record Enable Track6"
 msgstr "Aufnahme aktivieren für Spur 6"
 
-#: gtk2_ardour/ardour_ui_ed.cc:329
+#: gtk2_ardour/ardour_ui_ed.cc:341
 msgid "Toggle Record Enable Track7"
 msgstr "Aufnahme aktivieren für Spur 7"
 
-#: gtk2_ardour/ardour_ui_ed.cc:331
+#: gtk2_ardour/ardour_ui_ed.cc:343
 msgid "Toggle Record Enable Track8"
 msgstr "Aufnahme aktivieren für Spur 8"
 
-#: gtk2_ardour/ardour_ui_ed.cc:333
+#: gtk2_ardour/ardour_ui_ed.cc:345
 msgid "Toggle Record Enable Track9"
 msgstr "Aufnahme aktivieren für Spur 9"
 
-#: gtk2_ardour/ardour_ui_ed.cc:335
+#: gtk2_ardour/ardour_ui_ed.cc:347
 msgid "Toggle Record Enable Track10"
 msgstr "Aufnahme aktivieren für Spur 10"
 
-#: gtk2_ardour/ardour_ui_ed.cc:337
+#: gtk2_ardour/ardour_ui_ed.cc:349
 msgid "Toggle Record Enable Track11"
 msgstr "Aufnahme aktivieren für Spur 11"
 
-#: gtk2_ardour/ardour_ui_ed.cc:339
+#: gtk2_ardour/ardour_ui_ed.cc:351
 msgid "Toggle Record Enable Track12"
 msgstr "Aufnahme aktivieren für Spur 12"
 
-#: gtk2_ardour/ardour_ui_ed.cc:341
+#: gtk2_ardour/ardour_ui_ed.cc:353
 msgid "Toggle Record Enable Track13"
 msgstr "Aufnahme aktivieren für Spur 13"
 
-#: gtk2_ardour/ardour_ui_ed.cc:343
+#: gtk2_ardour/ardour_ui_ed.cc:355
 msgid "Toggle Record Enable Track14"
 msgstr "Aufnahme aktivieren für Spur 14"
 
-#: gtk2_ardour/ardour_ui_ed.cc:345
+#: gtk2_ardour/ardour_ui_ed.cc:357
 msgid "Toggle Record Enable Track15"
 msgstr "Aufnahme aktivieren für Spur 15"
 
-#: gtk2_ardour/ardour_ui_ed.cc:347
+#: gtk2_ardour/ardour_ui_ed.cc:359
 msgid "Toggle Record Enable Track16"
 msgstr "Aufnahme aktivieren für Spur 16"
 
-#: gtk2_ardour/ardour_ui_ed.cc:349
+#: gtk2_ardour/ardour_ui_ed.cc:361
 msgid "Toggle Record Enable Track17"
 msgstr "Aufnahme aktivieren für Spur 17"
 
-#: gtk2_ardour/ardour_ui_ed.cc:351
+#: gtk2_ardour/ardour_ui_ed.cc:363
 msgid "Toggle Record Enable Track18"
 msgstr "Aufnahme aktivieren für Spur 18"
 
-#: gtk2_ardour/ardour_ui_ed.cc:353
+#: gtk2_ardour/ardour_ui_ed.cc:365
 msgid "Toggle Record Enable Track19"
 msgstr "Aufnahme aktivieren für Spur 19"
 
-#: gtk2_ardour/ardour_ui_ed.cc:355
+#: gtk2_ardour/ardour_ui_ed.cc:367
 msgid "Toggle Record Enable Track20"
 msgstr "Aufnahme aktivieren für Spur 20"
 
-#: gtk2_ardour/ardour_ui_ed.cc:357
+#: gtk2_ardour/ardour_ui_ed.cc:369
 msgid "Toggle Record Enable Track21"
 msgstr "Aufnahme aktivieren für Spur 21"
 
-#: gtk2_ardour/ardour_ui_ed.cc:359
+#: gtk2_ardour/ardour_ui_ed.cc:371
 msgid "Toggle Record Enable Track22"
 msgstr "Aufnahme aktivieren für Spur 22"
 
-#: gtk2_ardour/ardour_ui_ed.cc:361
+#: gtk2_ardour/ardour_ui_ed.cc:373
 msgid "Toggle Record Enable Track23"
 msgstr "Aufnahme aktivieren für Spur 23"
 
-#: gtk2_ardour/ardour_ui_ed.cc:363
+#: gtk2_ardour/ardour_ui_ed.cc:375
 msgid "Toggle Record Enable Track24"
 msgstr "Aufnahme aktivieren für Spur 24"
 
-#: gtk2_ardour/ardour_ui_ed.cc:365
+#: gtk2_ardour/ardour_ui_ed.cc:377
 msgid "Toggle Record Enable Track25"
 msgstr "Aufnahme aktivieren für Spur 25"
 
-#: gtk2_ardour/ardour_ui_ed.cc:367
+#: gtk2_ardour/ardour_ui_ed.cc:379
 msgid "Toggle Record Enable Track26"
 msgstr "Aufnahme aktivieren für Spur 26"
 
-#: gtk2_ardour/ardour_ui_ed.cc:369
+#: gtk2_ardour/ardour_ui_ed.cc:381
 msgid "Toggle Record Enable Track27"
 msgstr "Aufnahme aktivieren für Spur 27"
 
-#: gtk2_ardour/ardour_ui_ed.cc:371
+#: gtk2_ardour/ardour_ui_ed.cc:383
 msgid "Toggle Record Enable Track28"
 msgstr "Aufnahme aktivieren für Spur 28"
 
-#: gtk2_ardour/ardour_ui_ed.cc:373
+#: gtk2_ardour/ardour_ui_ed.cc:385
 msgid "Toggle Record Enable Track29"
 msgstr "Aufnahme aktivieren für Spur 29"
 
-#: gtk2_ardour/ardour_ui_ed.cc:375
+#: gtk2_ardour/ardour_ui_ed.cc:387
 msgid "Toggle Record Enable Track30"
 msgstr "Aufnahme aktivieren für Spur 30"
 
-#: gtk2_ardour/ardour_ui_ed.cc:377
+#: gtk2_ardour/ardour_ui_ed.cc:389
 msgid "Toggle Record Enable Track31"
 msgstr "Aufnahme aktivieren für Spur 31"
 
-#: gtk2_ardour/ardour_ui_ed.cc:379
+#: gtk2_ardour/ardour_ui_ed.cc:391
 msgid "Toggle Record Enable Track32"
 msgstr "Aufnahme aktivieren für Spur 32"
 
-#: gtk2_ardour/ardour_ui_ed.cc:384
+#: gtk2_ardour/ardour_ui_ed.cc:396
 msgid "Percentage"
 msgstr "Prozent"
 
-#: gtk2_ardour/ardour_ui_ed.cc:385
+#: gtk2_ardour/ardour_ui_ed.cc:397
 msgid "Semitones"
 msgstr "Halbtöne"
 
-#: gtk2_ardour/ardour_ui_ed.cc:389
+#: gtk2_ardour/ardour_ui_ed.cc:401
 msgid "Send MTC"
 msgstr "MTC senden"
 
-#: gtk2_ardour/ardour_ui_ed.cc:391
+#: gtk2_ardour/ardour_ui_ed.cc:403
 msgid "Send MMC"
 msgstr "MMC senden"
 
-#: gtk2_ardour/ardour_ui_ed.cc:393
+#: gtk2_ardour/ardour_ui_ed.cc:405
 msgid "Use MMC"
 msgstr "Benutze MMC"
 
-#: gtk2_ardour/ardour_ui_ed.cc:395
+#: gtk2_ardour/ardour_ui_ed.cc:407
 msgid "Send MIDI feedback"
 msgstr "MIDI Feedback senden"
 
-#: gtk2_ardour/ardour_ui_ed.cc:398
+#: gtk2_ardour/ardour_ui_ed.cc:410
 msgid "Use OSC"
 msgstr "Aktiviere OSC"
 
-#: gtk2_ardour/ardour_ui_ed.cc:403
+#: gtk2_ardour/ardour_ui_ed.cc:415
+msgid "Sync Editor and Mixer track order"
+msgstr "Einheitliche Reihenfolge der Spuren im Editor und Mixer"
+
+#: gtk2_ardour/ardour_ui_ed.cc:416
 msgid "Stop plugins with transport"
 msgstr "Plugins mit Transport stoppen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:404
+#: gtk2_ardour/ardour_ui_ed.cc:417
 msgid "Verify remove last capture"
 msgstr "Verwerfen der letzten Aufnahme bestätigen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:405
+#: gtk2_ardour/ardour_ui_ed.cc:418
+msgid "Make periodic safety backups"
+msgstr "Erstelle regelmäßig Sicherungskopien"
+
+#: gtk2_ardour/ardour_ui_ed.cc:419
 msgid "Stop recording on xrun"
 msgstr "Aufnahme bei XRUN stoppen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:406
+#: gtk2_ardour/ardour_ui_ed.cc:420
 msgid "Stop transport at session end"
 msgstr "Transport am Ende des Projekts stoppen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:407
+#: gtk2_ardour/ardour_ui_ed.cc:421
 msgid "-12dB gain reduce ffwd/rewind"
 msgstr "Beim Spulen Pegel um -12dB absenken"
 
-#: gtk2_ardour/ardour_ui_ed.cc:408
+#: gtk2_ardour/ardour_ui_ed.cc:422
 msgid "Rec-enable stays engaged at stop"
 msgstr "Aufnahmestatus bleibt nach Stop erhalten"
 
-#: gtk2_ardour/ardour_ui_ed.cc:409
+#: gtk2_ardour/ardour_ui_ed.cc:423
 msgid "Region equivalents overlap"
 msgstr "Region entspricht Ãœberdeckung"
 
-#: gtk2_ardour/ardour_ui_ed.cc:411
+#: gtk2_ardour/ardour_ui_ed.cc:424
+msgid "Primary Clock delta to edit point"
+msgstr "Primäre Zeitanzeige zeigt Abstand zum Arbeitspunkt"
+
+#: gtk2_ardour/ardour_ui_ed.cc:425
+msgid "Secondary Clock delta to edit point"
+msgstr "Sekundäre Zeitanzeige zeigt Abstand zum Arbeitspunkt"
+
+#: gtk2_ardour/ardour_ui_ed.cc:426
+msgid "Enable Editor Meters"
+msgstr "Aktiviere Pegelanzeigen im Editor"
+
+#: gtk2_ardour/ardour_ui_ed.cc:427
+msgid "Always copy imported files"
+msgstr "Importierte Dateien immer kopieren"
+
+#: gtk2_ardour/ardour_ui_ed.cc:431
+msgid "Use DC bias"
+msgstr "DC bias aktivieren"
+
+#: gtk2_ardour/ardour_ui_ed.cc:433
+msgid "No processor handling"
+msgstr "Keine Korrekturen"
+
+#: gtk2_ardour/ardour_ui_ed.cc:442
+#: gtk2_ardour/ardour_ui_ed.cc:453
+msgid "Use FlushToZero"
+msgstr "Benutze FlushToZero"
+
+#: gtk2_ardour/ardour_ui_ed.cc:444
+#: gtk2_ardour/ardour_ui_ed.cc:458
+msgid "Use DenormalsAreZero"
+msgstr "Benutze DenormalsAreZero"
+
+#: gtk2_ardour/ardour_ui_ed.cc:446
+#: gtk2_ardour/ardour_ui_ed.cc:463
+msgid "Use FlushToZero & DenormalsAreZero"
+msgstr "Benutze FlushToZero & DenormalsAreZero"
+
+#: gtk2_ardour/ardour_ui_ed.cc:469
 msgid "Do not run plugins while recording"
 msgstr "Plugins während der Aufnahme daktivieren"
 
-#: gtk2_ardour/ardour_ui_ed.cc:414
+#: gtk2_ardour/ardour_ui_ed.cc:471
 msgid "Latched solo"
 msgstr "Latch Solo"
 
-#: gtk2_ardour/ardour_ui_ed.cc:416
+#: gtk2_ardour/ardour_ui_ed.cc:473
 msgid "Show solo muting"
 msgstr "Solo als Mute anzeigen"
 
-#: gtk2_ardour/ardour_ui_ed.cc:424
-#: gtk2_ardour/ardour_ui_ed.cc:432
-#: gtk2_ardour/audio_clock.cc:1805
+#: gtk2_ardour/ardour_ui_ed.cc:481
+#: gtk2_ardour/ardour_ui_ed.cc:489
+#: gtk2_ardour/audio_clock.cc:1889
 msgid "Off"
 msgstr "Aus"
 
-#: gtk2_ardour/ardour_ui_ed.cc:425
-#: gtk2_ardour/editor.cc:1246
-#: gtk2_ardour/editor.cc:1263
+#: gtk2_ardour/ardour_ui_ed.cc:482
+#: gtk2_ardour/editor.cc:1335
+#: gtk2_ardour/editor.cc:1338
+#: gtk2_ardour/editor.cc:1357
+#: gtk2_ardour/editor.cc:1360
 msgid "Slowest"
 msgstr "Sehr langsam"
 
-#: gtk2_ardour/ardour_ui_ed.cc:426
-#: gtk2_ardour/editor.cc:1247
-#: gtk2_ardour/editor.cc:1264
+#: gtk2_ardour/ardour_ui_ed.cc:483
+#: gtk2_ardour/editor.cc:1339
+#: gtk2_ardour/editor.cc:1361
 msgid "Slow"
 msgstr "Langsam"
 
-#: gtk2_ardour/ardour_ui_ed.cc:427
-#: gtk2_ardour/ardour_ui_ed.cc:434
+#: gtk2_ardour/ardour_ui_ed.cc:484
+#: gtk2_ardour/ardour_ui_ed.cc:491
 msgid "Medium"
 msgstr "Mittel"
 
-#: gtk2_ardour/ardour_ui_ed.cc:428
-#: gtk2_ardour/editor.cc:1248
-#: gtk2_ardour/editor.cc:1265
+#: gtk2_ardour/ardour_ui_ed.cc:485
+#: gtk2_ardour/editor.cc:1340
+#: gtk2_ardour/editor.cc:1362
+#: gtk2_ardour/sfdb_ui.cc:1070
+#: gtk2_ardour/sfdb_ui.cc:1151
 msgid "Fast"
 msgstr "Schnell"
 
-#: gtk2_ardour/ardour_ui_ed.cc:429
+#: gtk2_ardour/ardour_ui_ed.cc:486
 msgid "Faster"
 msgstr "Schneller"
 
-#: gtk2_ardour/ardour_ui_ed.cc:430
-#: gtk2_ardour/editor.cc:1249
-#: gtk2_ardour/editor.cc:1266
+#: gtk2_ardour/ardour_ui_ed.cc:487
+#: gtk2_ardour/editor.cc:1341
+#: gtk2_ardour/editor.cc:1363
+#: gtk2_ardour/sfdb_ui.cc:1071
 msgid "Fastest"
 msgstr "Schnellstmöglich"
 
-#: gtk2_ardour/ardour_ui_ed.cc:433
-#: gtk2_ardour/editor_actions.cc:58
+#: gtk2_ardour/ardour_ui_ed.cc:490
+#: gtk2_ardour/editor_actions.cc:79
 msgid "Short"
 msgstr "Kurz"
 
-#: gtk2_ardour/ardour_ui_ed.cc:435
+#: gtk2_ardour/ardour_ui_ed.cc:492
 msgid "Long"
 msgstr "Lange"
 
-#: gtk2_ardour/ardour_ui_ed.cc:453
+#: gtk2_ardour/ardour_ui_ed.cc:511
 msgid "Hardware monitoring"
 msgstr "Hardware Monitoring"
 
-#: gtk2_ardour/ardour_ui_ed.cc:454
+#: gtk2_ardour/ardour_ui_ed.cc:512
 msgid "Software monitoring"
 msgstr "Software Monitoring"
 
-#: gtk2_ardour/ardour_ui_ed.cc:455
+#: gtk2_ardour/ardour_ui_ed.cc:513
 msgid "External monitoring"
 msgstr "Externes Monitoring"
 
-#: gtk2_ardour/ardour_ui_ed.cc:459
+#: gtk2_ardour/ardour_ui_ed.cc:517
 msgid "Solo in-place"
 msgstr "Solo-In-Place"
 
-#: gtk2_ardour/ardour_ui_ed.cc:461
+#: gtk2_ardour/ardour_ui_ed.cc:519
 msgid "Solo via bus"
 msgstr "Solo Ã¼ber Bus"
 
-#: gtk2_ardour/ardour_ui_ed.cc:466
+#: gtk2_ardour/ardour_ui_ed.cc:524
 msgid "Auto-connect inputs to physical inputs"
-msgstr "Eingänge automatisch mit Soundkarteneingängen verbinden"
+msgstr "Eingänge automatisch mit Audioeingängen verbinden"
 
-#: gtk2_ardour/ardour_ui_ed.cc:468
+#: gtk2_ardour/ardour_ui_ed.cc:526
 msgid "Manually connect inputs"
 msgstr "Eingänge manuell verbinden"
 
-#: gtk2_ardour/ardour_ui_ed.cc:473
+#: gtk2_ardour/ardour_ui_ed.cc:531
 msgid "Auto-connect outputs to physical outs"
-msgstr "Ausgänge automatisch mit Soundkartenausgängen verbinden"
+msgstr "Ausgänge automatisch mit Audioausgängen verbinden"
 
-#: gtk2_ardour/ardour_ui_ed.cc:475
+#: gtk2_ardour/ardour_ui_ed.cc:533
 msgid "Auto-connect outputs to master bus"
 msgstr "Ausgänge automatisch mit Master-Bus verbinden"
 
-#: gtk2_ardour/ardour_ui_ed.cc:477
+#: gtk2_ardour/ardour_ui_ed.cc:535
 msgid "Manually connect outputs"
 msgstr "Ausgänge manuell verbinden"
 
-#: gtk2_ardour/ardour_ui_ed.cc:482
+#: gtk2_ardour/ardour_ui_ed.cc:540
 msgid "Remote ID assigned by User"
 msgstr "Fernsteuerungs-ID vom Benutzer festgelegt"
 
-#: gtk2_ardour/ardour_ui_ed.cc:484
+#: gtk2_ardour/ardour_ui_ed.cc:542
 msgid "Remote ID follows order of Mixer"
 msgstr "Fernsteuerungs-ID aus Reihenfolge im Mixer"
 
-#: gtk2_ardour/ardour_ui_ed.cc:486
+#: gtk2_ardour/ardour_ui_ed.cc:544
 msgid "Remote ID follows order of Editor"
 msgstr "Fernsteuerungs-ID aus Reihenfolge im Editor"
 
-#: gtk2_ardour/ardour_ui_ed.cc:635
-#: gtk2_ardour/ladspa_pluginui.cc:168
+#: gtk2_ardour/ardour_ui_ed.cc:693
+#: gtk2_ardour/generic_pluginui.cc:168
 msgid "Controls"
 msgstr "Steuerelemente"
 
-#: gtk2_ardour/ardour_ui_ed.cc:639
+#: gtk2_ardour/ardour_ui_ed.cc:697
 msgid "Feedback"
 msgstr "Feedback"
 
-#: gtk2_ardour/ardour_ui_ed.cc:723
+#: gtk2_ardour/ardour_ui_ed.cc:803
 msgid "Clock"
-msgstr "Clock"
-
-#: gtk2_ardour/ardour_ui_options.cc:106
-#: gtk2_ardour/ardour_ui_options.cc:133
-#: gtk2_ardour/editor_actions.cc:725
-#: gtk2_ardour/editor_actions.cc:953
-#: gtk2_ardour/editor_actions.cc:966
-#: gtk2_ardour/editor_actions.cc:1030
-#: gtk2_ardour/sfdb_ui.cc:536
-#: gtk2_ardour/audio_streamview.cc:173
+msgstr "Zeitanzeige"
+
+#: gtk2_ardour/ardour_ui_options.cc:119
+#: gtk2_ardour/ardour_ui_options.cc:149
+#: gtk2_ardour/editor_actions.cc:874
+#: gtk2_ardour/editor_actions.cc:1233
+#: gtk2_ardour/editor_actions.cc:1246
+#: gtk2_ardour/editor_actions.cc:1310
+#: gtk2_ardour/engine_dialog.cc:887
+#: gtk2_ardour/audio_streamview.cc:172
 msgid "programming error: %1"
 msgstr "Programmierfehler: %1"
 
-#: gtk2_ardour/ardour_ui_options.cc:212
+#: gtk2_ardour/ardour_ui_options.cc:228
 msgid "programming error: unknown solo model in ARDOUR_UI::set_solo_model: %1"
 msgstr "Programmierfehler: unbekannte Solo-Einstellung in ARDOUR_UI::set_solo_model: %1"
 
-#: gtk2_ardour/ardour_ui_options.cc:245
+#: gtk2_ardour/ardour_ui_options.cc:261
 msgid "programming error: unknown remote model in ARDOUR_UI::set_remote_model: %1"
 msgstr "Programmierfehler: unbekanntes Fernsteuerungsmodell in ARDOUR_UI::set_remote_model: %1"
 
-#: gtk2_ardour/ardour_ui_options.cc:279
+#: gtk2_ardour/ardour_ui_options.cc:295
 msgid "programming error: unknown monitor model in ARDOUR_UI::set_monitor_model: %1"
 msgstr "Programmierfehler: unbekannte Monitoring-Einstellung in ARDOUR_UI::set_monitor_model: %1"
 
-#: gtk2_ardour/ardour_ui_options.cc:571
+#: gtk2_ardour/ardour_ui_options.cc:334
+msgid "programming error: unknown denormal model in ARDOUR_UI::set_denormal_model: %1"
+msgstr "Programmierfehler: unknown denormal model in ARDOUR_UI::set_denormal_model: %1"
+
+#: gtk2_ardour/ardour_ui_options.cc:699
 msgid "programming error: unknown file header format passed to ARDOUR_UI::map_file_data_format: %1"
 msgstr "Programmierfehler: unbekanntes Dateiheaderformat Ã¼bergeben an ARDOUR_UI::map_file_data_format: %1"
 
-#: gtk2_ardour/ardour_ui_options.cc:603
+#: gtk2_ardour/ardour_ui_options.cc:735
 msgid "programming error: unknown file data format passed to ARDOUR_UI::map_file_data_format: %1"
 msgstr "Programmierfehler: unbekanntes Dateiformat Ã¼bergeben an ARDOUR_UI::map_file_data_format: %1"
 
-#: gtk2_ardour/ardour_ui_options.cc:932
+#: gtk2_ardour/ardour_ui_options.cc:1086
 msgid "ST"
 msgstr "HT"
 
-#: gtk2_ardour/audio_clock.cc:1801
-#: gtk2_ardour/editor.cc:181
+#: gtk2_ardour/audio_clock.cc:1885
+#: gtk2_ardour/editor.cc:179
+#: gtk2_ardour/editor_rulers.cc:410
 msgid "Timecode"
 msgstr "Timecode"
 
-#: gtk2_ardour/audio_clock.cc:1802
-#: gtk2_ardour/editor.cc:180
-#: gtk2_ardour/editor_rulers.cc:395
+#: gtk2_ardour/audio_clock.cc:1886
+#: gtk2_ardour/editor.cc:178
+#: gtk2_ardour/editor_rulers.cc:422
 msgid "Bars:Beats"
 msgstr "Takte:Schläge"
 
-#: gtk2_ardour/audio_clock.cc:1803
+#: gtk2_ardour/audio_clock.cc:1887
 msgid "Minutes:Seconds"
 msgstr "Minuten:Sekunden"
 
-#: gtk2_ardour/audio_clock.cc:1804
-msgid "Audio Frames"
-msgstr "Audio Frames"
-
-#: gtk2_ardour/audio_clock.cc:1807
-msgid "Mode"
-msgstr "Modus"
+#: gtk2_ardour/audio_clock.cc:1888
+#: gtk2_ardour/editor.cc:180
+#: gtk2_ardour/editor_rulers.cc:416
+msgid "Samples"
+msgstr "Samples"
 
-#: gtk2_ardour/route_time_axis.cc:87
+#: gtk2_ardour/route_time_axis.cc:88
 msgid "m"
 msgstr "m"
 
-#: gtk2_ardour/route_time_axis.cc:87
+#: gtk2_ardour/route_time_axis.cc:88
 msgid "s"
 msgstr "s"
 
-#: gtk2_ardour/route_time_axis.cc:87
+#: gtk2_ardour/route_time_axis.cc:88
 msgid "r"
 msgstr "r"
 
-#: gtk2_ardour/route_time_axis.cc:91
+#: gtk2_ardour/route_time_axis.cc:92
 msgid "g"
 msgstr "g"
 
-#: gtk2_ardour/route_time_axis.cc:92
+#: gtk2_ardour/route_time_axis.cc:93
 msgid "p"
 msgstr "w"
 
-#: gtk2_ardour/route_time_axis.cc:93
-#: gtk2_ardour/automation_time_axis.cc:36
+#: gtk2_ardour/route_time_axis.cc:94
+#: gtk2_ardour/automation_time_axis.cc:55
 #: gtk2_ardour/visual_time_axis.cc:73
 msgid "h"
 msgstr "h"
 
-#: gtk2_ardour/route_time_axis.cc:94
+#: gtk2_ardour/route_time_axis.cc:95
 msgid "a"
 msgstr "a"
 
-#: gtk2_ardour/route_time_axis.cc:95
+#: gtk2_ardour/route_time_axis.cc:96
 #: gtk2_ardour/visual_time_axis.cc:72
 msgid "v"
 msgstr "v"
 
-#: gtk2_ardour/route_time_axis.cc:148
-#: gtk2_ardour/mixer_strip.cc:86
+#: gtk2_ardour/route_time_axis.cc:154
+#: gtk2_ardour/mixer_strip.cc:88
 msgid "Record"
 msgstr "Aufnahme"
 
-#: gtk2_ardour/route_time_axis.cc:156
-#: gtk2_ardour/editor_actions.cc:38
-#: gtk2_ardour/mixer_strip.cc:86
-#: gtk2_ardour/mixer_strip.cc:426
+#: gtk2_ardour/route_time_axis.cc:168
+#: gtk2_ardour/editor_actions.cc:58
+#: gtk2_ardour/mixer_strip.cc:88
+#: gtk2_ardour/mixer_strip.cc:422
 msgid "Solo"
 msgstr "Solo"
 
-#: gtk2_ardour/route_time_axis.cc:157
-#: gtk2_ardour/editor.cc:1549
-#: gtk2_ardour/editor.cc:1644
-#: gtk2_ardour/mixer_strip.cc:86
-#: gtk2_ardour/mixer_strip.cc:425
+#: gtk2_ardour/route_time_axis.cc:169
+#: gtk2_ardour/editor.cc:1647
+#: gtk2_ardour/editor.cc:1743
+#: gtk2_ardour/mixer_strip.cc:88
+#: gtk2_ardour/mixer_strip.cc:421
 #: gtk2_ardour/panner_ui.cc:404
 msgid "Mute"
 msgstr "Mute"
 
-#: gtk2_ardour/route_time_axis.cc:158
+#: gtk2_ardour/route_time_axis.cc:170
 msgid "Edit Group"
 msgstr "Bearbeitungsgruppe"
 
-#: gtk2_ardour/route_time_axis.cc:159
+#: gtk2_ardour/route_time_axis.cc:171
 #: gtk2_ardour/visual_time_axis.cc:91
 msgid "Display Height"
 msgstr "Anzeigehöhe"
 
-#: gtk2_ardour/route_time_axis.cc:160
+#: gtk2_ardour/route_time_axis.cc:172
 msgid "Playlist"
 msgstr "Wiedergabeliste"
 
-#: gtk2_ardour/route_time_axis.cc:161
-#: gtk2_ardour/route_time_axis.cc:414
+#: gtk2_ardour/route_time_axis.cc:173
+#: gtk2_ardour/route_time_axis.cc:431
 msgid "Automation"
 msgstr "Automationen"
 
-#: gtk2_ardour/route_time_axis.cc:162
+#: gtk2_ardour/route_time_axis.cc:174
 #: gtk2_ardour/visual_time_axis.cc:92
 msgid "Visual options"
 msgstr "Visuelle optionen"
 
-#: gtk2_ardour/route_time_axis.cc:163
+#: gtk2_ardour/route_time_axis.cc:175
 #: gtk2_ardour/visual_time_axis.cc:93
 msgid "Hide this track"
 msgstr "Diese Spur verbergen"
 
-#: gtk2_ardour/route_time_axis.cc:265
-#: gtk2_ardour/mixer_strip.cc:910
+#: gtk2_ardour/route_time_axis.cc:282
+#: gtk2_ardour/mixer_strip.cc:907
 msgid "No group"
 msgstr "keine Gruppe"
 
-#: gtk2_ardour/route_time_axis.cc:375
+#: gtk2_ardour/route_time_axis.cc:391
 msgid "Show all automation"
 msgstr "Alle Automationen zeigen"
 
-#: gtk2_ardour/route_time_axis.cc:378
+#: gtk2_ardour/route_time_axis.cc:394
 msgid "Show existing automation"
 msgstr "Verfügbare Automationen zeigen"
 
-#: gtk2_ardour/route_time_axis.cc:381
+#: gtk2_ardour/route_time_axis.cc:397
 msgid "Hide all automation"
 msgstr "Automationen verbergen"
 
-#: gtk2_ardour/route_time_axis.cc:384
+#: gtk2_ardour/route_time_axis.cc:400
 msgid "Plugins"
 msgstr "Plugins"
 
-#: gtk2_ardour/route_time_axis.cc:405
-#: gtk2_ardour/automation_time_axis.cc:431
+#: gtk2_ardour/route_time_axis.cc:421
+#: gtk2_ardour/automation_time_axis.cc:450
 #: gtk2_ardour/imageframe_time_axis.cc:254
 #: gtk2_ardour/marker_time_axis.cc:210
 msgid "Height"
 msgstr "Höhe"
 
-#: gtk2_ardour/route_time_axis.cc:406
-#: gtk2_ardour/color_manager.cc:41
+#: gtk2_ardour/route_time_axis.cc:422
 #: gtk2_ardour/imageframe_time_axis.cc:255
 #: gtk2_ardour/marker_time_axis.cc:211
+#: gtk2_ardour/theme_manager.cc:52
 msgid "Color"
 msgstr "Farbe"
 
-#: gtk2_ardour/route_time_axis.cc:411
+#: gtk2_ardour/route_time_axis.cc:430
 #: gtk2_ardour/mixer_strip.cc:995
 msgid "Remote Control ID"
 msgstr "ID für Fernsteuerung"
 
-#: gtk2_ardour/route_time_axis.cc:429
+#: gtk2_ardour/route_time_axis.cc:447
 msgid "Align with existing material"
 msgstr "An vorhandenem Material ausrichten"
 
-#: gtk2_ardour/route_time_axis.cc:435
+#: gtk2_ardour/route_time_axis.cc:453
 msgid "Align with capture time"
 msgstr "An Aufnahmezeit ausrichten"
 
-#: gtk2_ardour/route_time_axis.cc:441
+#: gtk2_ardour/route_time_axis.cc:460
 msgid "Alignment"
 msgstr "Ausrichtung"
 
-#: gtk2_ardour/route_time_axis.cc:447
+#: gtk2_ardour/route_time_axis.cc:464
 msgid "Normal mode"
 msgstr "Normaler Modus"
 
-#: gtk2_ardour/route_time_axis.cc:450
+#: gtk2_ardour/route_time_axis.cc:467
 msgid "Tape mode"
 msgstr "Tape-Modus"
 
-#: gtk2_ardour/route_time_axis.cc:466
-#: gtk2_ardour/editor.cc:487
-#: gtk2_ardour/editor_actions.cc:61
-#: gtk2_ardour/mixer_strip.cc:984
-#: gtk2_ardour/mixer_ui.cc:108
+#: gtk2_ardour/route_time_axis.cc:484
+#: gtk2_ardour/editor.cc:502
+#: gtk2_ardour/editor_actions.cc:82
+#: gtk2_ardour/mixer_strip.cc:980
+#: gtk2_ardour/mixer_ui.cc:116
 msgid "Active"
 msgstr "Aktiv"
 
-#: gtk2_ardour/route_time_axis.cc:471
-#: gtk2_ardour/editor.cc:1746
-#: gtk2_ardour/editor.cc:3456
-#: gtk2_ardour/editor_actions.cc:328
-#: gtk2_ardour/editor_markers.cc:529
+#: gtk2_ardour/route_time_axis.cc:489
+#: gtk2_ardour/editor.cc:1852
+#: gtk2_ardour/editor.cc:3730
+#: gtk2_ardour/editor_actions.cc:463
+#: gtk2_ardour/editor_markers.cc:596
+#: gtk2_ardour/editor_markers.cc:652
 #: gtk2_ardour/imageframe_time_axis.cc:258
 #: gtk2_ardour/location_ui.cc:58
 #: gtk2_ardour/marker_time_axis.cc:214
-#: gtk2_ardour/mixer_strip.cc:998
+#: gtk2_ardour/mixer_strip.cc:999
 msgid "Remove"
 msgstr "Löschen"
 
-#: gtk2_ardour/route_time_axis.cc:496
-#: gtk2_ardour/route_time_axis.cc:551
-#: gtk2_ardour/route_time_axis.cc:816
-#: gtk2_ardour/editor_actions.cc:1017
+#: gtk2_ardour/route_time_axis.cc:514
+#: gtk2_ardour/route_time_axis.cc:569
+#: gtk2_ardour/route_time_axis.cc:838
+#: gtk2_ardour/editor_actions.cc:1297
 msgid "programming error: %1 %2"
 msgstr "Programmierfehler: %1 %2"
 
-#: gtk2_ardour/route_time_axis.cc:840
+#: gtk2_ardour/route_time_axis.cc:862
 msgid "Name for playlist"
 msgstr "Name für Wiedergabeliste"
 
-#: gtk2_ardour/route_time_axis.cc:842
-#: gtk2_ardour/route_time_axis.cc:1305
-#: gtk2_ardour/editor.cc:3461
-#: gtk2_ardour/editor_markers.cc:875
-#: gtk2_ardour/editor_mouse.cc:4752
+#: gtk2_ardour/route_time_axis.cc:864
+#: gtk2_ardour/route_time_axis.cc:1340
+#: gtk2_ardour/editor.cc:1714
+#: gtk2_ardour/editor.cc:3735
+#: gtk2_ardour/editor_markers.cc:590
+#: gtk2_ardour/editor_markers.cc:1022
+#: gtk2_ardour/editor_mouse.cc:5097
 #: gtk2_ardour/imageframe_time_axis.cc:247
 #: gtk2_ardour/marker_time_axis.cc:207
-#: gtk2_ardour/mixer_strip.cc:982
-#: gtk2_ardour/redirect_box.cc:825
-#: gtk2_ardour/redirect_box.cc:1165
-#: gtk2_ardour/route_ui.cc:807
+#: gtk2_ardour/mixer_strip.cc:978
+#: gtk2_ardour/redirect_box.cc:860
+#: gtk2_ardour/redirect_box.cc:1192
+#: gtk2_ardour/route_ui.cc:814
 #: gtk2_ardour/visual_time_axis.cc:330
 msgid "Rename"
 msgstr "Umbenennen"
 
-#: gtk2_ardour/route_time_axis.cc:884
-#: gtk2_ardour/route_time_axis.cc:930
+#: gtk2_ardour/route_time_axis.cc:906
+#: gtk2_ardour/route_time_axis.cc:952
 msgid "Name for Playlist"
 msgstr "Name für Wiedergabeliste"
 
-#: gtk2_ardour/route_time_axis.cc:1133
+#: gtk2_ardour/route_time_axis.cc:1155
 #: gtk2_ardour/visual_time_axis.cc:340
 #: gtk2_ardour/visual_time_axis.cc:387
 msgid "A track already exists with that name"
 msgstr "Es existiert bereits eine Spur mit diesem Namen"
 
-#: gtk2_ardour/route_time_axis.cc:1309
+#: gtk2_ardour/route_time_axis.cc:1344
 msgid "New Copy"
 msgstr "Neue Kopie"
 
-#: gtk2_ardour/route_time_axis.cc:1311
+#: gtk2_ardour/route_time_axis.cc:1346
 msgid "Clear Current"
 msgstr "Ausgewählte zurücksetzen"
 
-#: gtk2_ardour/route_time_axis.cc:1314
+#: gtk2_ardour/route_time_axis.cc:1349
 msgid "Select from all ..."
 msgstr "Aus allen auswählen..."
 
-#: gtk2_ardour/route_time_axis.cc:1520
-#: gtk2_ardour/editor.cc:1271
-#: gtk2_ardour/selection.cc:661
-#: gtk2_ardour/selection.cc:700
+#: gtk2_ardour/route_time_axis.cc:1554
+#: gtk2_ardour/editor.cc:1368
+#: gtk2_ardour/selection.cc:694
+#: gtk2_ardour/selection.cc:733
 msgid "programming error: "
 msgstr "Programmierfehler:"
 
-#: gtk2_ardour/audio_time_axis.cc:213
+#: gtk2_ardour/audio_time_axis.cc:214
 msgid "Fader"
 msgstr "Fader"
 
-#: gtk2_ardour/audio_time_axis.cc:218
+#: gtk2_ardour/audio_time_axis.cc:219
 msgid "Pan"
 msgstr "Pan"
 
-#: gtk2_ardour/audio_time_axis.cc:233
+#: gtk2_ardour/audio_time_axis.cc:235
 msgid "Hide all crossfades"
 msgstr "Alle Crossfades verbergen"
 
-#: gtk2_ardour/audio_time_axis.cc:234
+#: gtk2_ardour/audio_time_axis.cc:236
 msgid "Show all crossfades"
 msgstr "Alle Crossfades zeigen"
 
-#: gtk2_ardour/audio_time_axis.cc:241
+#: gtk2_ardour/audio_time_axis.cc:244
 msgid "Show waveforms"
 msgstr "Wellenformen zeigen"
 
-#: gtk2_ardour/audio_time_axis.cc:251
+#: gtk2_ardour/audio_time_axis.cc:254
 msgid "Traditional"
 msgstr "Traditionell"
 
-#: gtk2_ardour/audio_time_axis.cc:254
+#: gtk2_ardour/audio_time_axis.cc:258
 msgid "Rectified"
 msgstr "Gleichgerichtet"
 
-#: gtk2_ardour/audio_time_axis.cc:261
-#: gtk2_ardour/editor.cc:1245
-#: gtk2_ardour/editor.cc:1262
+#: gtk2_ardour/audio_time_axis.cc:268
+#: gtk2_ardour/editor.cc:1334
+#: gtk2_ardour/editor.cc:1337
+#: gtk2_ardour/editor.cc:1356
+#: gtk2_ardour/editor.cc:1359
 msgid "Linear"
 msgstr "Linear"
 
-#: gtk2_ardour/audio_time_axis.cc:264
+#: gtk2_ardour/audio_time_axis.cc:271
 msgid "Logarithmic"
 msgstr "Logarithmisch"
 
-#: gtk2_ardour/audio_time_axis.cc:281
+#: gtk2_ardour/audio_time_axis.cc:290
 msgid "Waveform"
 msgstr "Wellenform"
 
-#: gtk2_ardour/audio_time_axis.cc:353
+#: gtk2_ardour/audio_time_axis.cc:362
 msgid "gain"
 msgstr "Gain"
 
-#: gtk2_ardour/audio_time_axis.cc:393
+#: gtk2_ardour/audio_time_axis.cc:402
 msgid "pan"
 msgstr "Pan"
 
@@ -1877,96 +2093,96 @@ msgid "automation range drag"
 msgstr "Automationsbereich bewegen"
 
 #: gtk2_ardour/automation_line.cc:1021
-#: gtk2_ardour/region_gain_line.cc:64
+#: gtk2_ardour/region_gain_line.cc:83
 msgid "remove control point"
 msgstr "Automationspunkt entfernen"
 
-#: gtk2_ardour/automation_time_axis.cc:37
-#: gtk2_ardour/editor_ops.cc:2641
+#: gtk2_ardour/automation_time_axis.cc:56
+#: gtk2_ardour/editor_ops.cc:3404
 msgid "clear"
 msgstr "Leeren"
 
-#: gtk2_ardour/automation_time_axis.cc:78
+#: gtk2_ardour/automation_time_axis.cc:97
 msgid "track height"
 msgstr "Anzeigehöhe"
 
-#: gtk2_ardour/automation_time_axis.cc:79
+#: gtk2_ardour/automation_time_axis.cc:98
 msgid "automation state"
 msgstr "Automationsmodus"
 
-#: gtk2_ardour/automation_time_axis.cc:80
+#: gtk2_ardour/automation_time_axis.cc:99
 msgid "clear track"
 msgstr "Spur zurücksetzen"
 
-#: gtk2_ardour/automation_time_axis.cc:81
+#: gtk2_ardour/automation_time_axis.cc:100
 msgid "hide track"
 msgstr "Diese Spur verbergen"
 
-#: gtk2_ardour/automation_time_axis.cc:188
-#: gtk2_ardour/automation_time_axis.cc:217
-#: gtk2_ardour/automation_time_axis.cc:442
-#: gtk2_ardour/gain_meter.cc:159
-#: gtk2_ardour/ladspa_pluginui.cc:332
-#: gtk2_ardour/ladspa_pluginui.cc:576
+#: gtk2_ardour/automation_time_axis.cc:207
+#: gtk2_ardour/automation_time_axis.cc:236
+#: gtk2_ardour/automation_time_axis.cc:461
+#: gtk2_ardour/gain_meter.cc:160
+#: gtk2_ardour/generic_pluginui.cc:332
+#: gtk2_ardour/generic_pluginui.cc:579
 #: gtk2_ardour/panner_ui.cc:88
 msgid "Manual"
 msgstr "Manuell"
 
-#: gtk2_ardour/automation_time_axis.cc:190
-#: gtk2_ardour/automation_time_axis.cc:228
-#: gtk2_ardour/automation_time_axis.cc:446
-#: gtk2_ardour/editor.cc:1824
-#: gtk2_ardour/editor.cc:1905
-#: gtk2_ardour/gain_meter.cc:161
-#: gtk2_ardour/ladspa_pluginui.cc:335
-#: gtk2_ardour/ladspa_pluginui.cc:578
+#: gtk2_ardour/automation_time_axis.cc:209
+#: gtk2_ardour/automation_time_axis.cc:247
+#: gtk2_ardour/automation_time_axis.cc:465
+#: gtk2_ardour/editor.cc:1931
+#: gtk2_ardour/editor.cc:2014
+#: gtk2_ardour/gain_meter.cc:162
+#: gtk2_ardour/generic_pluginui.cc:335
+#: gtk2_ardour/generic_pluginui.cc:581
 #: gtk2_ardour/panner_ui.cc:90
-#: gtk2_ardour/sfdb_ui.cc:61
 msgid "Play"
-msgstr "Play"
+msgstr "Wiedergabe"
 
-#: gtk2_ardour/automation_time_axis.cc:192
-#: gtk2_ardour/automation_time_axis.cc:239
-#: gtk2_ardour/automation_time_axis.cc:450
-#: gtk2_ardour/gain_meter.cc:163
-#: gtk2_ardour/ladspa_pluginui.cc:338
-#: gtk2_ardour/ladspa_pluginui.cc:580
+#: gtk2_ardour/automation_time_axis.cc:211
+#: gtk2_ardour/automation_time_axis.cc:258
+#: gtk2_ardour/automation_time_axis.cc:469
+#: gtk2_ardour/gain_meter.cc:164
+#: gtk2_ardour/generic_pluginui.cc:338
+#: gtk2_ardour/generic_pluginui.cc:583
 #: gtk2_ardour/panner_ui.cc:92
 msgid "Write"
 msgstr "Write"
 
-#: gtk2_ardour/automation_time_axis.cc:194
-#: gtk2_ardour/automation_time_axis.cc:250
-#: gtk2_ardour/automation_time_axis.cc:454
-#: gtk2_ardour/gain_meter.cc:165
-#: gtk2_ardour/ladspa_pluginui.cc:341
-#: gtk2_ardour/ladspa_pluginui.cc:582
+#: gtk2_ardour/automation_time_axis.cc:213
+#: gtk2_ardour/automation_time_axis.cc:269
+#: gtk2_ardour/automation_time_axis.cc:473
+#: gtk2_ardour/gain_meter.cc:166
+#: gtk2_ardour/generic_pluginui.cc:341
+#: gtk2_ardour/generic_pluginui.cc:585
 #: gtk2_ardour/panner_ui.cc:94
 msgid "Touch"
 msgstr "Touch"
 
-#: gtk2_ardour/automation_time_axis.cc:261
-#: gtk2_ardour/ladspa_pluginui.cc:344
+#: gtk2_ardour/automation_time_axis.cc:280
+#: gtk2_ardour/generic_pluginui.cc:344
 msgid "???"
 msgstr "???"
 
-#: gtk2_ardour/automation_time_axis.cc:275
+#: gtk2_ardour/automation_time_axis.cc:294
 msgid "clear automation"
 msgstr "Automation zurücksetzen"
 
-#: gtk2_ardour/automation_time_axis.cc:433
-#: gtk2_ardour/editor_actions.cc:326
+#: gtk2_ardour/automation_time_axis.cc:452
+#: gtk2_ardour/editor_actions.cc:461
+#: gtk2_ardour/editor_markers.cc:588
 msgid "Hide"
 msgstr "Verbergen"
 
-#: gtk2_ardour/automation_time_axis.cc:435
-#: gtk2_ardour/crossfade_edit.cc:78
-#: gtk2_ardour/redirect_box.cc:1157
+#: gtk2_ardour/automation_time_axis.cc:454
+#: gtk2_ardour/crossfade_edit.cc:77
+#: gtk2_ardour/redirect_box.cc:1180
 #: gtk2_ardour/connection_editor.cc:56
 msgid "Clear"
 msgstr "Leeren"
 
-#: gtk2_ardour/automation_time_axis.cc:458
+#: gtk2_ardour/automation_time_axis.cc:477
 msgid "State"
 msgstr "Automationssmodus"
 
@@ -2116,765 +2332,840 @@ msgstr ""
 msgid "color of fill"
 msgstr ""
 
-#: gtk2_ardour/color_manager.cc:40
-msgid "Object"
-msgstr ""
-
-#: gtk2_ardour/color_manager.cc:78
-msgid "cannot open color definition file %1: %2"
-msgstr "Konnte die Datei mit den Farbdefinitonen %1 nicht laden: %2"
-
-#: gtk2_ardour/crossfade_edit.cc:75
+#: gtk2_ardour/crossfade_edit.cc:74
 msgid "ardour: x-fade edit"
 msgstr "ardour: Crossfade Editor"
 
-#: gtk2_ardour/crossfade_edit.cc:79
+#: gtk2_ardour/crossfade_edit.cc:78
 #: gtk2_ardour/panner_ui.cc:420
 msgid "Reset"
 msgstr "Zurücksetzen"
 
-#: gtk2_ardour/crossfade_edit.cc:80
+#: gtk2_ardour/crossfade_edit.cc:79
 msgid "Fade"
 msgstr "Fade"
 
-#: gtk2_ardour/crossfade_edit.cc:81
+#: gtk2_ardour/crossfade_edit.cc:80
 msgid "Out (dry)"
 msgstr "Out (dry)"
 
-#: gtk2_ardour/crossfade_edit.cc:82
+#: gtk2_ardour/crossfade_edit.cc:81
 msgid "Out"
 msgstr "Out"
 
-#: gtk2_ardour/crossfade_edit.cc:83
+#: gtk2_ardour/crossfade_edit.cc:82
 msgid "In (dry)"
 msgstr "In (dry)"
 
-#: gtk2_ardour/crossfade_edit.cc:84
+#: gtk2_ardour/crossfade_edit.cc:83
 msgid "In"
 msgstr "In"
 
-#: gtk2_ardour/crossfade_edit.cc:86
+#: gtk2_ardour/crossfade_edit.cc:85
 msgid "With Pre-roll"
 msgstr "mit Pre-Roll"
 
-#: gtk2_ardour/crossfade_edit.cc:87
+#: gtk2_ardour/crossfade_edit.cc:86
 msgid "With Post-roll"
 msgstr "mit Post-Roll"
 
-#: gtk2_ardour/crossfade_edit.cc:95
+#: gtk2_ardour/crossfade_edit.cc:94
 msgid "Fade In"
 msgstr "Fade In"
 
-#: gtk2_ardour/crossfade_edit.cc:96
+#: gtk2_ardour/crossfade_edit.cc:95
 msgid "Fade Out"
 msgstr "Fade Out"
 
-#: gtk2_ardour/crossfade_edit.cc:172
-#: gtk2_ardour/editor.cc:1624
-#: gtk2_ardour/editor_actions.cc:324
-#: gtk2_ardour/option_editor.cc:134
+#: gtk2_ardour/crossfade_edit.cc:171
+#: gtk2_ardour/editor.cc:1723
+#: gtk2_ardour/editor_actions.cc:459
+#: gtk2_ardour/option_editor.cc:148
 msgid "Audition"
 msgstr "Vorhören"
 
-#: gtk2_ardour/editor.cc:104
-#: gtk2_ardour/editor.cc:2995
-#: gtk2_ardour/editor_actions.cc:402
-#: gtk2_ardour/export_dialog.cc:78
-#: gtk2_ardour/export_dialog.cc:92
-#: gtk2_ardour/export_dialog.cc:895
-#: gtk2_ardour/export_dialog.cc:1227
-#: gtk2_ardour/route_ui.cc:506
-msgid "None"
-msgstr "Kein"
-
-#: gtk2_ardour/editor.cc:105
-#: gtk2_ardour/editor.cc:2983
+#: gtk2_ardour/editor.cc:109
+#: gtk2_ardour/editor.cc:3214
 msgid "CD Frames"
 msgstr "CD-Frames"
 
-#: gtk2_ardour/editor.cc:106
-#: gtk2_ardour/editor.cc:2985
+#: gtk2_ardour/editor.cc:110
+#: gtk2_ardour/editor.cc:3216
 msgid "SMPTE Frames"
 msgstr "SMPTE-Frames"
 
-#: gtk2_ardour/editor.cc:107
-#: gtk2_ardour/editor.cc:2987
+#: gtk2_ardour/editor.cc:111
+#: gtk2_ardour/editor.cc:2748
+#: gtk2_ardour/editor.cc:3218
 msgid "SMPTE Seconds"
 msgstr "SMPTE-Sekunden"
 
-#: gtk2_ardour/editor.cc:108
-#: gtk2_ardour/editor.cc:2989
+#: gtk2_ardour/editor.cc:112
+#: gtk2_ardour/editor.cc:3220
 msgid "SMPTE Minutes"
 msgstr "SMPTE-Minuten"
 
-#: gtk2_ardour/editor.cc:109
-#: gtk2_ardour/editor.cc:2991
+#: gtk2_ardour/editor.cc:113
+#: gtk2_ardour/editor.cc:3222
 msgid "Seconds"
 msgstr "Sekunden"
 
-#: gtk2_ardour/editor.cc:110
-#: gtk2_ardour/editor.cc:2993
+#: gtk2_ardour/editor.cc:114
+#: gtk2_ardour/editor.cc:3224
 msgid "Minutes"
 msgstr "Minuten"
 
-#: gtk2_ardour/editor.cc:111
-#: gtk2_ardour/editor.cc:2965
+#: gtk2_ardour/editor.cc:115
+#: gtk2_ardour/editor.cc:3198
 msgid "Beats/32"
 msgstr "Schläge / 32"
 
-#: gtk2_ardour/editor.cc:112
-#: gtk2_ardour/editor.cc:2963
+#: gtk2_ardour/editor.cc:116
+#: gtk2_ardour/editor.cc:3196
 msgid "Beats/16"
 msgstr "Schläge / 16"
 
-#: gtk2_ardour/editor.cc:113
-#: gtk2_ardour/editor.cc:2961
+#: gtk2_ardour/editor.cc:117
+#: gtk2_ardour/editor.cc:3194
 msgid "Beats/8"
 msgstr "Schläge / 8"
 
-#: gtk2_ardour/editor.cc:114
-#: gtk2_ardour/editor.cc:2959
+#: gtk2_ardour/editor.cc:118
+#: gtk2_ardour/editor.cc:3192
 msgid "Beats/4"
 msgstr "Schläge / 4"
 
-#: gtk2_ardour/editor.cc:115
-#: gtk2_ardour/editor.cc:2957
+#: gtk2_ardour/editor.cc:119
+#: gtk2_ardour/editor.cc:3190
 msgid "Beats/3"
 msgstr "Schläge / 3"
 
-#: gtk2_ardour/editor.cc:116
-#: gtk2_ardour/editor.cc:2967
+#: gtk2_ardour/editor.cc:120
+#: gtk2_ardour/editor.cc:3200
 msgid "Beats"
 msgstr "Schläge"
 
-#: gtk2_ardour/editor.cc:117
-#: gtk2_ardour/editor.cc:2969
+#: gtk2_ardour/editor.cc:121
+#: gtk2_ardour/editor.cc:3202
 msgid "Bars"
 msgstr "Takte"
 
-#: gtk2_ardour/editor.cc:118
-#: gtk2_ardour/editor.cc:2971
+#: gtk2_ardour/editor.cc:122
+#: gtk2_ardour/editor.cc:3204
 msgid "Marks"
 msgstr "Marker"
 
-#: gtk2_ardour/editor.cc:119
-#: gtk2_ardour/editor.cc:138
-#: gtk2_ardour/editor.cc:2973
-#: gtk2_ardour/editor.cc:3038
-msgid "Edit Cursor"
-msgstr "Editierzeiger"
-
-#: gtk2_ardour/editor.cc:120
-#: gtk2_ardour/editor.cc:2975
+#: gtk2_ardour/editor.cc:123
+#: gtk2_ardour/editor.cc:3206
 msgid "Region starts"
 msgstr "Regionen-Anfang"
 
-#: gtk2_ardour/editor.cc:121
-#: gtk2_ardour/editor.cc:2977
+#: gtk2_ardour/editor.cc:124
+#: gtk2_ardour/editor.cc:3208
 msgid "Region ends"
 msgstr "Regionen-Ende"
 
-#: gtk2_ardour/editor.cc:122
-#: gtk2_ardour/editor.cc:2981
+#: gtk2_ardour/editor.cc:125
+#: gtk2_ardour/editor.cc:3212
 msgid "Region syncs"
 msgstr "Regionen-Sync"
 
-#: gtk2_ardour/editor.cc:123
-#: gtk2_ardour/editor.cc:2979
+#: gtk2_ardour/editor.cc:126
+#: gtk2_ardour/editor.cc:3210
 msgid "Region bounds"
 msgstr "Regionen-Grenzen"
 
-#: gtk2_ardour/editor.cc:129
-#: gtk2_ardour/editor.cc:3013
-#: gtk2_ardour/editor_actions.cc:289
+#: gtk2_ardour/editor.cc:131
+#: gtk2_ardour/editor.cc:3240
+#: gtk2_ardour/editor_actions.cc:421
+msgid "No Grid"
+msgstr "Raster aus"
+
+#: gtk2_ardour/editor.cc:132
+#: gtk2_ardour/editor.cc:3242
+#: gtk2_ardour/editor_actions.cc:422
+msgid "Grid"
+msgstr "Einrasten"
+
+#: gtk2_ardour/editor.cc:133
+#: gtk2_ardour/editor.cc:3244
+#: gtk2_ardour/editor_actions.cc:423
 msgid "Magnetic"
 msgstr "Magnetisch"
 
-#: gtk2_ardour/editor.cc:134
-#: gtk2_ardour/editor.cc:3030
+#: gtk2_ardour/editor.cc:138
+#: gtk2_ardour/editor.cc:148
+#: gtk2_ardour/editor.cc:2734
+#: gtk2_ardour/editor.cc:2760
+#: gtk2_ardour/editor.cc:3283
+#: gtk2_ardour/editor.cc:3308
+#: gtk2_ardour/editor_actions.cc:406
+msgid "Playhead"
+msgstr "Positionszeiger"
+
+#: gtk2_ardour/editor.cc:139
+#: gtk2_ardour/editor.cc:3281
+#: gtk2_ardour/editor_actions.cc:408
+#: gtk2_ardour/marker_time_axis.cc:255
+msgid "Marker"
+msgstr "Marker"
+
+#: gtk2_ardour/editor.cc:140
+#: gtk2_ardour/editor.cc:149
+#: gtk2_ardour/editor.cc:3310
+#: gtk2_ardour/editor_actions.cc:407
+msgid "Mouse"
+msgstr "Maus"
+
+#: gtk2_ardour/editor.cc:145
+#: gtk2_ardour/editor.cc:3302
 #: gtk2_ardour/export_dialog.cc:142
 #: gtk2_ardour/export_dialog.cc:158
-#: gtk2_ardour/export_dialog.cc:1070
-#: gtk2_ardour/export_dialog.cc:1074
+#: gtk2_ardour/export_dialog.cc:1131
+#: gtk2_ardour/export_dialog.cc:1135
 msgid "Left"
 msgstr "Links"
 
-#: gtk2_ardour/editor.cc:135
-#: gtk2_ardour/editor.cc:3032
+#: gtk2_ardour/editor.cc:146
+#: gtk2_ardour/editor.cc:3304
 #: gtk2_ardour/export_dialog.cc:143
 #: gtk2_ardour/export_dialog.cc:159
 msgid "Right"
 msgstr "Rechts"
 
-#: gtk2_ardour/editor.cc:136
-#: gtk2_ardour/editor.cc:3034
+#: gtk2_ardour/editor.cc:147
+#: gtk2_ardour/editor.cc:3306
 msgid "Center"
 msgstr "Mitte"
 
-#: gtk2_ardour/editor.cc:137
-#: gtk2_ardour/editor.cc:3036
-msgid "Playhead"
-msgstr "Positionszeiger"
+#: gtk2_ardour/editor.cc:150
+#: gtk2_ardour/editor.cc:3312
+msgid "Edit Point"
+msgstr "Arbeitspunkt"
 
-#: gtk2_ardour/editor.cc:179
+#: gtk2_ardour/editor.cc:177
 msgid "Mins:Secs"
 msgstr "Min:Sek"
 
-#: gtk2_ardour/editor.cc:182
-#: gtk2_ardour/editor_rulers.cc:389
-msgid "Frames"
-msgstr "Frames"
-
-#: gtk2_ardour/editor.cc:183
-#: gtk2_ardour/editor_rulers.cc:409
+#: gtk2_ardour/editor.cc:181
+#: gtk2_ardour/editor_rulers.cc:436
 msgid "Tempo"
 msgstr "Tempo"
 
-#: gtk2_ardour/editor.cc:184
-#: gtk2_ardour/editor_rulers.cc:403
+#: gtk2_ardour/editor.cc:182
+#: gtk2_ardour/editor_rulers.cc:430
 msgid "Meter"
 msgstr "Taktart"
 
-#: gtk2_ardour/editor.cc:185
-#: gtk2_ardour/editor_rulers.cc:415
+#: gtk2_ardour/editor.cc:183
+#: gtk2_ardour/editor_rulers.cc:442
 msgid "Location Markers"
 msgstr "Positionsmarker"
 
-#: gtk2_ardour/editor.cc:186
-#: gtk2_ardour/editor_rulers.cc:421
+#: gtk2_ardour/editor.cc:184
+#: gtk2_ardour/editor_rulers.cc:449
 msgid "Range Markers"
 msgstr "Bereiche"
 
-#: gtk2_ardour/editor.cc:187
-#: gtk2_ardour/editor_rulers.cc:427
+#: gtk2_ardour/editor.cc:185
+#: gtk2_ardour/editor_rulers.cc:462
 msgid "Loop/Punch Ranges"
 msgstr "Schleifen/Punch-Bereiche"
 
-#: gtk2_ardour/editor.cc:205
+#: gtk2_ardour/editor.cc:186
+#: gtk2_ardour/editor_rulers.cc:456
+msgid "CD Markers"
+msgstr "CD-Marker"
+
+#: gtk2_ardour/editor.cc:204
 msgid "mode"
 msgstr "Modus"
 
-#: gtk2_ardour/editor.cc:206
+#: gtk2_ardour/editor.cc:205
 msgid "automation"
 msgstr "Automation"
 
-#: gtk2_ardour/editor.cc:462
-#: gtk2_ardour/editor.cc:488
-#: gtk2_ardour/editor_actions.cc:63
-#: gtk2_ardour/mixer_ui.cc:83
-#: gtk2_ardour/mixer_ui.cc:109
+#: gtk2_ardour/editor.cc:476
+#: gtk2_ardour/editor.cc:503
+#: gtk2_ardour/editor_actions.cc:84
+#: gtk2_ardour/mixer_ui.cc:90
+#: gtk2_ardour/mixer_ui.cc:117
 #: gtk2_ardour/analysis_window.cc:63
 msgid "Show"
 msgstr "Anzeigen"
 
-#: gtk2_ardour/editor.cc:463
-#: gtk2_ardour/editor.cc:486
+#: gtk2_ardour/editor.cc:477
+#: gtk2_ardour/editor.cc:501
 msgid "Name"
 msgstr "Name"
 
-#: gtk2_ardour/editor.cc:561
-#: gtk2_ardour/editor.cc:628
-msgid "Regions"
-msgstr "Regionen"
-
-#: gtk2_ardour/editor.cc:600
-#: gtk2_ardour/editor.cc:640
+#: gtk2_ardour/editor.cc:619
+#: gtk2_ardour/editor.cc:661
 msgid "Chunks"
 msgstr "Teile"
 
-#: gtk2_ardour/editor.cc:631
+#: gtk2_ardour/editor.cc:650
 msgid "Tracks/Busses"
 msgstr "Spuren/Busse"
 
-#: gtk2_ardour/editor.cc:634
+#: gtk2_ardour/editor.cc:653
 msgid "Snapshots"
-msgstr "Schnapschüsse"
+msgstr "Schnappschüsse"
 
-#: gtk2_ardour/editor.cc:637
+#: gtk2_ardour/editor.cc:656
 msgid "Edit Groups"
 msgstr "Bearbeitungsgruppen"
 
-#: gtk2_ardour/editor.cc:688
+#: gtk2_ardour/editor.cc:720
 msgid "Nudge Region/Selection Forwards"
 msgstr "Region/Auswahl schrittweise nach vorne"
 
-#: gtk2_ardour/editor.cc:689
+#: gtk2_ardour/editor.cc:721
 msgid "Nudge Region/Selection Backwards"
 msgstr "Region/Auswahl schrittweise nach hinten"
 
-#: gtk2_ardour/editor.cc:719
-#: gtk2_ardour/editor_mixer.cc:352
+#: gtk2_ardour/editor.cc:751
+#: gtk2_ardour/editor_mixer.cc:358
 msgid "Editor"
 msgstr "Editor"
 
-#: gtk2_ardour/editor.cc:1095
-#: gtk2_ardour/editor.cc:1103
-#: gtk2_ardour/editor_markers.cc:919
+#: gtk2_ardour/editor.cc:1169
+#: gtk2_ardour/editor.cc:1177
+#: gtk2_ardour/editor.cc:4181
+#: gtk2_ardour/editor.cc:4209
 msgid "Loop"
 msgstr "Schleife"
 
-#: gtk2_ardour/editor.cc:1108
-#: gtk2_ardour/editor.cc:1116
-#: gtk2_ardour/editor_markers.cc:947
+#: gtk2_ardour/editor.cc:1182
+#: gtk2_ardour/editor.cc:1190
 msgid "Punch"
 msgstr "Punch"
 
-#: gtk2_ardour/editor.cc:1226
-#: gtk2_ardour/editor_mouse.cc:1691
+#: gtk2_ardour/editor.cc:1314
+#: gtk2_ardour/editor_mouse.cc:1823
 msgid "programming error: fade in canvas item has no regionview data pointer!"
 msgstr "Programmierfehler: fade in canvas item has no regionview data pointer!"
 
-#: gtk2_ardour/editor.cc:1238
-#: gtk2_ardour/editor.cc:1255
-#: gtk2_ardour/redirect_box.cc:1173
+#: gtk2_ardour/editor.cc:1326
+#: gtk2_ardour/editor.cc:1348
+#: gtk2_ardour/redirect_box.cc:1200
 msgid "Deactivate"
 msgstr "Deaktivieren"
 
-#: gtk2_ardour/editor.cc:1240
-#: gtk2_ardour/editor.cc:1257
-#: gtk2_ardour/redirect_box.cc:1171
+#: gtk2_ardour/editor.cc:1328
+#: gtk2_ardour/editor.cc:1350
+#: gtk2_ardour/redirect_box.cc:1198
 msgid "Activate"
 msgstr "Aktivieren"
 
-#: gtk2_ardour/editor.cc:1378
-#: gtk2_ardour/editor.cc:1386
-#: gtk2_ardour/editor_ops.cc:2534
+#: gtk2_ardour/editor.cc:1475
+#: gtk2_ardour/editor.cc:1483
+#: gtk2_ardour/editor_ops.cc:3297
 msgid "Freeze"
 msgstr "Einfrieren"
 
-#: gtk2_ardour/editor.cc:1382
+#: gtk2_ardour/editor.cc:1479
 msgid "Unfreeze"
 msgstr "Auftauen"
 
-#: gtk2_ardour/editor.cc:1551
+#: gtk2_ardour/editor.cc:1649
 msgid "Unmute"
 msgstr "Unmute"
 
-#: gtk2_ardour/editor.cc:1555
-#: gtk2_ardour/editor.cc:1869
-#: gtk2_ardour/editor_actions.cc:28
-#: gtk2_ardour/editor_markers.cc:528
-#: gtk2_ardour/mixer_strip.cc:508
-#: gtk2_ardour/mixer_strip.cc:570
-#: gtk2_ardour/redirect_box.cc:1179
+#: gtk2_ardour/editor.cc:1653
+#: gtk2_ardour/editor.cc:1978
+#: gtk2_ardour/editor_actions.cc:47
+#: gtk2_ardour/editor_markers.cc:651
+#: gtk2_ardour/mixer_strip.cc:502
+#: gtk2_ardour/mixer_strip.cc:564
+#: gtk2_ardour/redirect_box.cc:1206
 msgid "Edit"
 msgstr "Bearbeiten"
 
-#: gtk2_ardour/editor.cc:1560
+#: gtk2_ardour/editor.cc:1658
 msgid "Convert to short"
 msgstr "In kurzen Crossfade umwandeln"
 
-#: gtk2_ardour/editor.cc:1562
+#: gtk2_ardour/editor.cc:1660
 msgid "Convert to full"
 msgstr "In langen Crossfade umwandeln"
 
-#: gtk2_ardour/editor.cc:1573
+#: gtk2_ardour/editor.cc:1671
 msgid "Crossfade"
 msgstr "Crossfade"
 
-#: gtk2_ardour/editor.cc:1616
+#: gtk2_ardour/editor.cc:1715
 msgid "Popup region editor"
 msgstr "Regioneneditor Ã¶ffnen"
 
-#: gtk2_ardour/editor.cc:1617
+#: gtk2_ardour/editor.cc:1716
 msgid "Raise to top layer"
 msgstr "Region ganz nach oben"
 
-#: gtk2_ardour/editor.cc:1618
+#: gtk2_ardour/editor.cc:1717
 msgid "Lower to bottom layer"
 msgstr "Region ganz nach unten"
 
-#: gtk2_ardour/editor.cc:1620
+#: gtk2_ardour/editor.cc:1719
 msgid "Define sync point"
-msgstr "Synchronisationspunkt definieren"
+msgstr "Einrastpunkt definieren"
 
-#: gtk2_ardour/editor.cc:1621
+#: gtk2_ardour/editor.cc:1720
 msgid "Remove sync point"
-msgstr "Synchronisationspunkt entfernen"
+msgstr "Einrastpunkt entfernen"
 
-#: gtk2_ardour/editor.cc:1626
+#: gtk2_ardour/editor.cc:1725
 msgid "Bounce"
 msgstr "Bounce"
 
-#: gtk2_ardour/editor.cc:1629
+#: gtk2_ardour/editor.cc:1728
 msgid "Analyze region"
 msgstr "Analysiere Region"
 
-#: gtk2_ardour/editor.cc:1636
+#: gtk2_ardour/editor.cc:1735
+#: gtk2_ardour/editor_markers.cc:591
 msgid "Lock"
 msgstr "Sperren"
 
-#: gtk2_ardour/editor.cc:1653
+#: gtk2_ardour/editor.cc:1753
 msgid "Opaque"
 msgstr "Deckend"
 
-#: gtk2_ardour/editor.cc:1662
+#: gtk2_ardour/editor.cc:1763
 msgid "Original position"
 msgstr "Ursprungsposition"
 
-#: gtk2_ardour/editor.cc:1674
+#: gtk2_ardour/editor.cc:1776
 msgid "Reset Envelope"
 msgstr "Lautstärkekurve zurücksetzen"
 
-#: gtk2_ardour/editor.cc:1676
+#: gtk2_ardour/editor.cc:1778
 msgid "Envelope Visible"
 msgstr "Lautstärkekurve sichtbar"
 
-#: gtk2_ardour/editor.cc:1685
+#: gtk2_ardour/editor.cc:1787
 msgid "Envelope Active"
 msgstr "Lautstärkekurve aktiv"
 
-#: gtk2_ardour/editor.cc:1698
+#: gtk2_ardour/editor.cc:1801
 msgid "DeNormalize"
-msgstr "Ardour: Region "
+msgstr "DeNormalisieren"
 
-#: gtk2_ardour/editor.cc:1700
+#: gtk2_ardour/editor.cc:1803
 msgid "Normalize"
 msgstr "Normalisieren"
 
-#: gtk2_ardour/editor.cc:1703
+#: gtk2_ardour/editor.cc:1807
 msgid "Reverse"
 msgstr "Rückwärts"
 
-#: gtk2_ardour/editor.cc:1709
-#: gtk2_ardour/editor.cc:1791
+#: gtk2_ardour/editor.cc:1812
+#: gtk2_ardour/editor.cc:1903
 msgid "Add Range Markers"
 msgstr "Bereichsmarker einfügen"
 
-#: gtk2_ardour/editor.cc:1710
+#: gtk2_ardour/editor.cc:1813
 msgid "Set Range Selection"
 msgstr "Bereich auswählen"
 
-#: gtk2_ardour/editor.cc:1719
+#: gtk2_ardour/editor.cc:1822
 msgid "Nudge fwd"
 msgstr "Schritt nach vorne"
 
-#: gtk2_ardour/editor.cc:1720
+#: gtk2_ardour/editor.cc:1823
 msgid "Nudge bwd"
 msgstr "Schritt nach hinten"
 
-#: gtk2_ardour/editor.cc:1721
+#: gtk2_ardour/editor.cc:1824
 msgid "Nudge fwd by capture offset"
 msgstr "Schritt nach vorne um Aufnahme-Offset"
 
-#: gtk2_ardour/editor.cc:1722
+#: gtk2_ardour/editor.cc:1825
 msgid "Nudge bwd by capture offset"
 msgstr "Schritt nach hinten um Aufnahme-Offset"
 
-#: gtk2_ardour/editor.cc:1724
-#: gtk2_ardour/editor.cc:1889
-#: gtk2_ardour/editor.cc:1945
+#: gtk2_ardour/editor.cc:1827
+#: gtk2_ardour/editor.cc:1998
+#: gtk2_ardour/editor.cc:2054
 msgid "Nudge"
 msgstr "Verschieben"
 
-#: gtk2_ardour/editor.cc:1731
-msgid "Start to edit cursor"
-msgstr "Von Anfang bis Editierzeiger"
+#: gtk2_ardour/editor.cc:1834
+#: gtk2_ardour/editor_actions.cc:253
+msgid "Start to edit point"
+msgstr "Von Anfang bis Arbeitspunkt"
 
-#: gtk2_ardour/editor.cc:1732
-msgid "Edit cursor to end"
-msgstr "Von Editierzeiger bis Ende"
+#: gtk2_ardour/editor.cc:1835
+#: gtk2_ardour/editor_actions.cc:255
+msgid "Edit point to end"
+msgstr "Von Arbeitspunkt bis Ende"
 
-#: gtk2_ardour/editor.cc:1734
-#: gtk2_ardour/gain_meter.cc:168
-#: gtk2_ardour/gain_meter.cc:880
+#: gtk2_ardour/editor.cc:1836
+#: gtk2_ardour/editor_actions.cc:257
+msgid "Trim To Loop"
+msgstr "Auf Schleife kürzen"
+
+#: gtk2_ardour/editor.cc:1837
+#: gtk2_ardour/editor_actions.cc:259
+msgid "Trim To Punch"
+msgstr "Punch-Bereich schneiden"
+
+#: gtk2_ardour/editor.cc:1839
+#: gtk2_ardour/gain_meter.cc:169
+#: gtk2_ardour/gain_meter.cc:903
 #: gtk2_ardour/panner_ui.cc:97
 #: gtk2_ardour/panner_ui.cc:780
 msgid "Trim"
 msgstr "Abschneiden"
 
-#: gtk2_ardour/editor.cc:1737
+#: gtk2_ardour/editor.cc:1842
 msgid "Split"
 msgstr "Teilen"
 
-#: gtk2_ardour/editor.cc:1740
+#: gtk2_ardour/editor.cc:1845
 msgid "Make mono regions"
 msgstr "Zu Mono-Regionen umwandeln"
 
-#: gtk2_ardour/editor.cc:1743
+#: gtk2_ardour/editor.cc:1848
 msgid "Duplicate"
 msgstr "Duplizieren"
 
-#: gtk2_ardour/editor.cc:1744
+#: gtk2_ardour/editor.cc:1849
+msgid "Multi-Duplicate"
+msgstr "Mehrfach duplizieren"
+
+#: gtk2_ardour/editor.cc:1850
 msgid "Fill Track"
 msgstr "Spur auffüllen"
 
-#: gtk2_ardour/editor.cc:1776
+#: gtk2_ardour/editor.cc:1879
 msgid "Play range"
 msgstr "Bereich abspielen"
 
-#: gtk2_ardour/editor.cc:1777
+#: gtk2_ardour/editor.cc:1880
 msgid "Loop range"
 msgstr "Bereich in Schleife abspielen"
 
-#: gtk2_ardour/editor.cc:1781
+#: gtk2_ardour/editor.cc:1884
 msgid "Analyze range"
 msgstr "Bereich analysieren"
 
-#: gtk2_ardour/editor.cc:1785
-msgid "Separate range to track"
-msgstr "Bereich als Spur"
+#: gtk2_ardour/editor.cc:1888
+#: gtk2_ardour/editor_actions.cc:370
+msgid "Extend Range to End of Region"
+msgstr "Bereich vergrößern bis zum Ende der Region "
+
+#: gtk2_ardour/editor.cc:1889
+#: gtk2_ardour/editor_actions.cc:372
+msgid "Extend Range to Start of Region"
+msgstr "Bereich vergrößern bis zum Anfang der Region "
+
+#: gtk2_ardour/editor.cc:1892
+msgid "Convert to region in-place"
+msgstr "Am Rastpunkt der Regionen einrasten"
 
-#: gtk2_ardour/editor.cc:1786
-msgid "Separate range to region list"
+#: gtk2_ardour/editor.cc:1893
+#, fuzzy
+msgid "Convert to region in region list"
 msgstr "Bereich zur Regionenliste hinzufügen"
 
-#: gtk2_ardour/editor.cc:1789
+#: gtk2_ardour/editor.cc:1896
 msgid "Select all in range"
 msgstr "Alles im Bereich auswählen"
 
-#: gtk2_ardour/editor.cc:1792
-#: gtk2_ardour/editor.cc:1837
-msgid "Set range to loop range"
-msgstr "Ausgewählten Bereich als Schleife"
+#: gtk2_ardour/editor.cc:1899
+msgid "Set loop from selection"
+msgstr "Schleife aus Auswahl erstellen"
 
-#: gtk2_ardour/editor.cc:1793
-#: gtk2_ardour/editor.cc:1838
-msgid "Set range to punch range"
-msgstr "Ausgewählten Bereich als Punch-Bereich"
+#: gtk2_ardour/editor.cc:1900
+msgid "Set punch from selection"
+msgstr "Punch-Bereich aus Auswahl erstellen"
 
-#: gtk2_ardour/editor.cc:1795
+#: gtk2_ardour/editor.cc:1905
 msgid "Crop region to range"
 msgstr "Regionen-Editor Ã¶ffnen"
 
-#: gtk2_ardour/editor.cc:1796
+#: gtk2_ardour/editor.cc:1906
 msgid "Fill range with region"
 msgstr "Bereich mit Region ausfüllen"
 
-#: gtk2_ardour/editor.cc:1797
+#: gtk2_ardour/editor.cc:1907
 msgid "Duplicate range"
 msgstr "Bereich Duplizieren"
 
-#: gtk2_ardour/editor.cc:1798
+#: gtk2_ardour/editor.cc:1908
 msgid "Create chunk from range"
 msgstr "Abschnitt aus Bereich erstellen..."
 
-#: gtk2_ardour/editor.cc:1800
+#: gtk2_ardour/editor.cc:1910
 msgid "Bounce range"
 msgstr "Bereich Bouncen"
 
-#: gtk2_ardour/editor.cc:1801
+#: gtk2_ardour/editor.cc:1911
 msgid "Export range"
-msgstr "Bereiche exportieren..."
-
-#: gtk2_ardour/editor.cc:1803
-msgid "Range"
-msgstr "Bereich"
+msgstr "Bereich exportieren"
 
-#: gtk2_ardour/editor.cc:1818
-#: gtk2_ardour/editor.cc:1903
-msgid "Play from edit cursor"
-msgstr "Wiedergabe ab Editierzeiger"
+#: gtk2_ardour/editor.cc:1925
+#: gtk2_ardour/editor.cc:2012
+msgid "Play from edit point"
+msgstr "Wiedergabe ab Arbeitspunkt"
 
-#: gtk2_ardour/editor.cc:1819
-#: gtk2_ardour/editor.cc:1904
+#: gtk2_ardour/editor.cc:1926
+#: gtk2_ardour/editor.cc:2013
 msgid "Play from start"
 msgstr "Wiedergabe ab Anfang"
 
-#: gtk2_ardour/editor.cc:1820
+#: gtk2_ardour/editor.cc:1927
 msgid "Play region"
 msgstr "Region wiedergeben"
 
-#: gtk2_ardour/editor.cc:1822
+#: gtk2_ardour/editor.cc:1929
+#: gtk2_ardour/editor_actions.cc:266
 msgid "Loop Region"
 msgstr "Region in Schleife wiedergeben"
 
-#: gtk2_ardour/editor.cc:1832
-#: gtk2_ardour/editor.cc:1913
+#: gtk2_ardour/editor.cc:1939
+#: gtk2_ardour/editor.cc:2022
 msgid "Select All in track"
 msgstr "Alles in Spur auswählen"
 
-#: gtk2_ardour/editor.cc:1833
-#: gtk2_ardour/editor.cc:1914
-#: gtk2_ardour/redirect_box.cc:1167
+#: gtk2_ardour/editor.cc:1940
+#: gtk2_ardour/editor.cc:2023
+#: gtk2_ardour/editor_actions.cc:137
+#: gtk2_ardour/redirect_box.cc:1194
 msgid "Select All"
 msgstr "Alles Auswählen"
 
-#: gtk2_ardour/editor.cc:1834
-#: gtk2_ardour/editor.cc:1915
+#: gtk2_ardour/editor.cc:1941
+#: gtk2_ardour/editor.cc:2024
 msgid "Invert selection in track"
 msgstr "Auswahl in Spur umkehren"
 
-#: gtk2_ardour/editor.cc:1835
-#: gtk2_ardour/editor.cc:1916
+#: gtk2_ardour/editor.cc:1942
+#: gtk2_ardour/editor.cc:2025
 msgid "Invert selection"
 msgstr "Auswahl umkehren"
 
-#: gtk2_ardour/editor.cc:1840
-#: gtk2_ardour/editor.cc:1918
-msgid "Select all after edit cursor"
-msgstr "Alles nach Editierzeiger auswählen"
+#: gtk2_ardour/editor.cc:1944
+msgid "Set range to loop range"
+msgstr "Ausgewählten Bereich als Schleife"
 
-#: gtk2_ardour/editor.cc:1841
-#: gtk2_ardour/editor.cc:1919
-msgid "Select all before edit cursor"
-msgstr "Alles vor Editierzeiger auswählen"
+#: gtk2_ardour/editor.cc:1945
+msgid "Set range to punch range"
+msgstr "Ausgewählten Bereich als Punch-Bereich"
 
-#: gtk2_ardour/editor.cc:1842
-#: gtk2_ardour/editor.cc:1920
-msgid "Select all after playhead"
-msgstr "Alles nach Positionszeiger auswählen"
+#: gtk2_ardour/editor.cc:1947
+#: gtk2_ardour/editor_actions.cc:143
+msgid "Select All After Edit Point"
+msgstr "Alle Regionen nach dem Arbeitspunkt auswählen"
 
-#: gtk2_ardour/editor.cc:1843
-#: gtk2_ardour/editor.cc:1921
-msgid "Select all before playhead"
-msgstr "Alles vor Positionszeiger auswählen"
+#: gtk2_ardour/editor.cc:1948
+#: gtk2_ardour/editor_actions.cc:145
+msgid "Select All Before Edit Point"
+msgstr "Alle Regionen vor dem Arbeitspunkt auswählen"
+
+#: gtk2_ardour/editor.cc:1949
+#: gtk2_ardour/editor_actions.cc:148
+msgid "Select All After Playhead"
+msgstr "Alle Regionen nach dem Positionszeiger auswählen"
 
-#: gtk2_ardour/editor.cc:1844
-msgid "Select all between cursors"
-msgstr "Alles zwischen Zeigern auswählen"
+#: gtk2_ardour/editor.cc:1950
+#: gtk2_ardour/editor_actions.cc:150
+msgid "Select All Before Playhead"
+msgstr "Alle Regionen vor dem Positionszeiger auswählen"
+
+#: gtk2_ardour/editor.cc:1951
+#: gtk2_ardour/editor_actions.cc:152
+msgid "Select All Between Playhead & Edit Point"
+msgstr "Alle Regionen zwischen Positionszeiger und Arbeitspunkt auswählen"
+
+#: gtk2_ardour/editor.cc:1952
+#: gtk2_ardour/editor_actions.cc:154
+msgid "Select All Within Playhead & Edit Point"
+msgstr "Alle Regionen innerhalb Positionszeiger und Arbeitspunkt auswählen"
+
+#: gtk2_ardour/editor.cc:1953
+#: gtk2_ardour/editor_actions.cc:157
+msgid "Select Range Between Playhead & Edit Point"
+msgstr "Wähle Bereich zwischen Positionszeiger und Arbeitspunkt aus"
 
-#: gtk2_ardour/editor.cc:1847
-#: gtk2_ardour/editor.cc:1923
+#: gtk2_ardour/editor.cc:1957
+#: gtk2_ardour/editor.cc:2032
+#: gtk2_ardour/editor_actions.cc:48
 msgid "Select"
 msgstr "Auswahl"
 
-#: gtk2_ardour/editor.cc:1855
-#: gtk2_ardour/editor.cc:1931
-#: gtk2_ardour/editor_actions.cc:217
-#: gtk2_ardour/redirect_box.cc:1160
+#: gtk2_ardour/editor.cc:1965
+#: gtk2_ardour/editor.cc:2040
+#: gtk2_ardour/editor_actions.cc:334
+#: gtk2_ardour/redirect_box.cc:1183
 msgid "Cut"
 msgstr "Ausschneiden"
 
-#: gtk2_ardour/editor.cc:1856
-#: gtk2_ardour/editor.cc:1932
-#: gtk2_ardour/editor_actions.cc:222
-#: gtk2_ardour/redirect_box.cc:1162
+#: gtk2_ardour/editor.cc:1966
+#: gtk2_ardour/editor.cc:2041
+#: gtk2_ardour/editor_actions.cc:339
+#: gtk2_ardour/redirect_box.cc:1185
 msgid "Copy"
 msgstr "Kopieren"
 
-#: gtk2_ardour/editor.cc:1857
-msgid "Paste at edit cursor"
-msgstr "Am Editierzeiger einfügen"
-
-#: gtk2_ardour/editor.cc:1858
-msgid "Paste at mouse"
-msgstr "An Mausposition einfügen"
+#: gtk2_ardour/editor.cc:1967
+#: gtk2_ardour/editor.cc:2042
+#: gtk2_ardour/editor_actions.cc:341
+#: gtk2_ardour/redirect_box.cc:1191
+msgid "Paste"
+msgstr "Einfügen"
 
-#: gtk2_ardour/editor.cc:1862
+#: gtk2_ardour/editor.cc:1971
 msgid "Align"
 msgstr "Ausrichten"
 
-#: gtk2_ardour/editor.cc:1863
+#: gtk2_ardour/editor.cc:1972
 msgid "Align Relative"
 msgstr "Relativ ausrichten"
 
-#: gtk2_ardour/editor.cc:1867
+#: gtk2_ardour/editor.cc:1976
 msgid "Insert chunk"
 msgstr "Abschnitt einfügen"
 
-#: gtk2_ardour/editor.cc:1874
+#: gtk2_ardour/editor.cc:1983
 msgid "Insert Selected Region"
 msgstr "Ausgewählte Region einfügen"
 
-#: gtk2_ardour/editor.cc:1875
+#: gtk2_ardour/editor.cc:1984
 msgid "Insert Existing Audio"
 msgstr "Audio importieren..."
 
-#: gtk2_ardour/editor.cc:1884
-#: gtk2_ardour/editor.cc:1940
+#: gtk2_ardour/editor.cc:1993
+#: gtk2_ardour/editor.cc:2049
 msgid "Nudge entire track fwd"
 msgstr "Gesamte Spur schrittweise nach vorne"
 
-#: gtk2_ardour/editor.cc:1885
-#: gtk2_ardour/editor.cc:1941
-msgid "Nudge track after edit cursor fwd"
-msgstr "Spur nach Editierzeiger schrittweise nach vorne"
+#: gtk2_ardour/editor.cc:1994
+#: gtk2_ardour/editor.cc:2050
+msgid "Nudge track after edit point fwd"
+msgstr "Spur nach Arbeitspunkt schrittweise nach vorne"
 
-#: gtk2_ardour/editor.cc:1886
-#: gtk2_ardour/editor.cc:1942
+#: gtk2_ardour/editor.cc:1995
+#: gtk2_ardour/editor.cc:2051
 msgid "Nudge entire track bwd"
 msgstr "Gesamte Spur schrittweise nach hinten"
 
-#: gtk2_ardour/editor.cc:1887
-#: gtk2_ardour/editor.cc:1943
-msgid "Nudge track after edit cursor bwd"
-msgstr "Spur nach Editierzeiger schrittweise nach hinten"
+#: gtk2_ardour/editor.cc:1996
+#: gtk2_ardour/editor.cc:2052
+msgid "Nudge track after edit point bwd"
+msgstr "Spur nach Arbeitspunkt schrittweise nach hinten"
 
-#: gtk2_ardour/editor.cc:1933
-#: gtk2_ardour/editor_actions.cc:224
-#: gtk2_ardour/redirect_box.cc:1164
-msgid "Paste"
-msgstr "Einfügen"
+#: gtk2_ardour/editor.cc:2027
+msgid "Select all after edit point"
+msgstr "Alles nach Arbeitspunkt auswählen"
+
+#: gtk2_ardour/editor.cc:2028
+msgid "Select all before edit point"
+msgstr "Alles vor Arbeitspunkt auswählen"
+
+#: gtk2_ardour/editor.cc:2029
+msgid "Select all after playhead"
+msgstr "Alles nach Positionszeiger auswählen"
 
-#: gtk2_ardour/editor.cc:2518
+#: gtk2_ardour/editor.cc:2030
+msgid "Select all before playhead"
+msgstr "Alles vor Positionszeiger auswählen"
+
+#: gtk2_ardour/editor.cc:2684
 msgid "Select/Move Objects"
 msgstr "Objekte auswählen/verschieben"
 
-#: gtk2_ardour/editor.cc:2519
+#: gtk2_ardour/editor.cc:2685
 msgid "Select/Move Ranges"
-msgstr "Bereiche auswählen/verschieben"
+msgstr "Editierbereich auswählen/verschieben"
 
-#: gtk2_ardour/editor.cc:2520
+#: gtk2_ardour/editor.cc:2686
 msgid "Draw Gain Automation"
 msgstr "Lautstärkekurve zeichnen"
 
-#: gtk2_ardour/editor.cc:2521
+#: gtk2_ardour/editor.cc:2687
 msgid "Select Zoom Range"
 msgstr "Zoombereich auswählen"
 
-#: gtk2_ardour/editor.cc:2522
+#: gtk2_ardour/editor.cc:2688
 msgid "Stretch/Shrink Regions"
 msgstr "Regionen vergrößern/verkleinern (Time-Stretch)"
 
-#: gtk2_ardour/editor.cc:2523
+#: gtk2_ardour/editor.cc:2689
 msgid "Listen to Specific Regions"
 msgstr "Ausgewählte Regionen vorhören"
 
-#: gtk2_ardour/editor.cc:2553
-#: gtk2_ardour/editor_actions.cc:143
+#: gtk2_ardour/editor.cc:2719
+#: gtk2_ardour/editor_actions.cc:209
 msgid "Zoom In"
 msgstr "Vergrößern"
 
-#: gtk2_ardour/editor.cc:2559
-#: gtk2_ardour/editor_actions.cc:141
+#: gtk2_ardour/editor.cc:2725
+#: gtk2_ardour/editor_actions.cc:207
 msgid "Zoom Out"
 msgstr "Verkleinern"
 
-#: gtk2_ardour/editor.cc:2565
-#: gtk2_ardour/editor_actions.cc:145
+#: gtk2_ardour/editor.cc:2731
+#: gtk2_ardour/editor_actions.cc:211
 msgid "Zoom to Session"
 msgstr "Auf ganzes Projekt zoomen"
 
-#: gtk2_ardour/editor.cc:2571
+#: gtk2_ardour/editor.cc:2737
 msgid "Zoom focus"
 msgstr "Zoom-Mittelpunkt"
 
-#: gtk2_ardour/editor.cc:2587
-msgid "Unit to snap cursors and ranges to"
-msgstr "Rastereinheit für Zeiger und Bereiche"
+#: gtk2_ardour/editor.cc:2751
+msgid "Snap/Grid Units"
+msgstr "Einrast-Einheiten"
 
-#: gtk2_ardour/editor.cc:2835
-#: gtk2_ardour/editor_actions.cc:207
+#: gtk2_ardour/editor.cc:2754
+msgid "Magnetic Snap"
+msgstr "Magnetisch einrasten"
+
+#: gtk2_ardour/editor.cc:2757
+msgid "Snap/Grid Mode"
+msgstr "Einrastmodus"
+
+#: gtk2_ardour/editor.cc:2763
+msgid "Edit point"
+msgstr "Arbeitspunkt"
+
+#: gtk2_ardour/editor.cc:2913
+msgid "malformed URL passed to drag-n-drop code"
+msgstr ""
+
+#: gtk2_ardour/editor.cc:3032
+#: gtk2_ardour/editor_actions.cc:320
 msgid "Undo"
 msgstr "Rückgängig"
 
-#: gtk2_ardour/editor.cc:2837
+#: gtk2_ardour/editor.cc:3034
 msgid "Undo (%1)"
 msgstr "Rückgängig (%1)"
 
-#: gtk2_ardour/editor.cc:2844
-#: gtk2_ardour/editor_actions.cc:209
+#: gtk2_ardour/editor.cc:3041
+#: gtk2_ardour/editor_actions.cc:322
 msgid "Redo"
 msgstr "Wiederherstellen"
 
-#: gtk2_ardour/editor.cc:2846
+#: gtk2_ardour/editor.cc:3043
 msgid "Redo (%1)"
 msgstr "Wiederherstellen (%1)"
 
-#: gtk2_ardour/editor.cc:2860
+#: gtk2_ardour/editor.cc:3073
 msgid "Duplicate how many times?"
 msgstr "Wie häufig duplizieren?"
 
-#: gtk2_ardour/editor.cc:2942
+#: gtk2_ardour/editor.cc:3175
 msgid "Splice Edit"
 msgstr "Kleben"
 
-#: gtk2_ardour/editor.cc:2944
+#: gtk2_ardour/editor.cc:3177
 msgid "Slide Edit"
 msgstr "Slide Edit"
 
-#: gtk2_ardour/editor.cc:3298
+#: gtk2_ardour/editor.cc:3572
 msgid ""
 "Playlist %1 is currently unused.\n"
 "If left alone, no audio files used by it will be cleaned.\n"
@@ -2884,35 +3175,34 @@ msgstr ""
 "Es können keine Audiodateien aufgeräumt werden, die von ihr verwendet werden.\n"
 "Falls sie gelöscht wird, werden die ausschließlich von ihr verwendeten Audiodateien gelöscht."
 
-#: gtk2_ardour/editor.cc:3308
+#: gtk2_ardour/editor.cc:3582
 msgid "Delete playlist"
 msgstr "Wiedergabeliste löschen"
 
-#: gtk2_ardour/editor.cc:3309
+#: gtk2_ardour/editor.cc:3583
 msgid "Keep playlist"
 msgstr "Wiedergabeliste beibehalten"
 
-#: gtk2_ardour/editor.cc:3310
-#: gtk2_ardour/editor_audio_import.cc:366
-#: gtk2_ardour/editor_ops.cc:1747
-#: gtk2_ardour/editor_timefx.cc:77
-#: gtk2_ardour/export_dialog.cc:973
+#: gtk2_ardour/editor.cc:3584
+#: gtk2_ardour/editor_audio_import.cc:515
+#: gtk2_ardour/editor_timefx.cc:78
+#: gtk2_ardour/export_dialog.cc:1034
 #: gtk2_ardour/io_selector.cc:60
 #: gtk2_ardour/io_selector.cc:748
-#: gtk2_ardour/redirect_box.cc:987
-#: gtk2_ardour/tempo_dialog.cc:22
-#: gtk2_ardour/tempo_dialog.cc:41
-#: gtk2_ardour/tempo_dialog.cc:158
-#: gtk2_ardour/tempo_dialog.cc:176
+#: gtk2_ardour/redirect_box.cc:1022
+#: gtk2_ardour/tempo_dialog.cc:42
+#: gtk2_ardour/tempo_dialog.cc:61
+#: gtk2_ardour/tempo_dialog.cc:256
+#: gtk2_ardour/tempo_dialog.cc:274
 #: gtk2_ardour/connection_editor.cc:59
 msgid "Cancel"
 msgstr "Abbrechen"
 
-#: gtk2_ardour/editor.cc:3478
+#: gtk2_ardour/editor.cc:3752
 msgid "New name of snapshot"
 msgstr "Name für neuen Schnappschuss"
 
-#: gtk2_ardour/editor.cc:3496
+#: gtk2_ardour/editor.cc:3770
 msgid ""
 "Do you really want to remove snapshot \"%1\" ?\n"
 "(cannot be undone)"
@@ -2920,793 +3210,920 @@ msgstr ""
 "Wollen Sie den Schnappschuss \"%1\" wirklich löschen?\n"
 "(Dies kann nicht rückgängig gemacht werden!)"
 
-#: gtk2_ardour/editor.cc:3498
-#: gtk2_ardour/editor_ops.cc:181
-#: gtk2_ardour/editor_ops.cc:3153
-#: gtk2_ardour/route_ui.cc:783
+#: gtk2_ardour/editor.cc:3772
+#: gtk2_ardour/editor_ops.cc:206
+#: gtk2_ardour/editor_ops.cc:3954
+#: gtk2_ardour/route_ui.cc:790
 #: gtk2_ardour/visual_time_axis.cc:282
 msgid "No, do nothing."
 msgstr "Nein, nichts machen."
 
-#: gtk2_ardour/editor.cc:3499
-#: gtk2_ardour/route_ui.cc:784
+#: gtk2_ardour/editor.cc:3773
+#: gtk2_ardour/route_ui.cc:791
 #: gtk2_ardour/visual_time_axis.cc:283
 msgid "Yes, remove it."
 msgstr "Ja, entfernen."
 
-#: gtk2_ardour/editor.cc:3603
+#: gtk2_ardour/editor.cc:3883
 msgid "new playlists"
 msgstr "Neue Wiedergabelisten"
 
-#: gtk2_ardour/editor.cc:3611
+#: gtk2_ardour/editor.cc:3898
 msgid "copy playlists"
 msgstr "Wiedergabelisten kopieren"
 
-#: gtk2_ardour/editor.cc:3619
+#: gtk2_ardour/editor.cc:3913
 msgid "clear playlists"
 msgstr "Wiedergabelisten zurücksetzen"
 
-#: gtk2_ardour/editor_actions.cc:29
-msgid "Select regions"
-msgstr "Region(en) auswählen"
+#: gtk2_ardour/editor_actions.cc:49
+msgid "Select Regions"
+msgstr "Region auswählen"
 
-#: gtk2_ardour/editor_actions.cc:30
-msgid "Select range operations"
-msgstr "Bereich"
+#: gtk2_ardour/editor_actions.cc:50
+msgid "Select Range Operations"
+msgstr "Bereichs"
 
-#: gtk2_ardour/editor_actions.cc:31
-msgid "Move edit cursor"
-msgstr "Editierzeiger bewegen"
+#: gtk2_ardour/editor_actions.cc:51
+msgid "Move Selected Marker"
+msgstr "Ausgewählten Positionsmarker verschieben"
 
-#: gtk2_ardour/editor_actions.cc:32
+#: gtk2_ardour/editor_actions.cc:52
 msgid "Region operations"
 msgstr "Region(en)"
 
-#: gtk2_ardour/editor_actions.cc:33
+#: gtk2_ardour/editor_actions.cc:53
 msgid "Tools"
 msgstr "Werkzeuge"
 
-#: gtk2_ardour/editor_actions.cc:34
+#: gtk2_ardour/editor_actions.cc:54
 msgid "View"
 msgstr "Ansicht"
 
-#: gtk2_ardour/editor_actions.cc:35
+#: gtk2_ardour/editor_actions.cc:55
 msgid "ZoomFocus"
 msgstr "Zoom-Mittelpunkt"
 
-#: gtk2_ardour/editor_actions.cc:36
+#: gtk2_ardour/editor_actions.cc:56
 msgid "Meter hold"
 msgstr "Pegelanzeige halten"
 
-#: gtk2_ardour/editor_actions.cc:37
+#: gtk2_ardour/editor_actions.cc:57
 msgid "Meter falloff"
 msgstr "Abfall der Pegelanzeigen"
 
-#: gtk2_ardour/editor_actions.cc:39
+#: gtk2_ardour/editor_actions.cc:59
 msgid "Crossfades"
 msgstr "Crossfades"
 
-#: gtk2_ardour/editor_actions.cc:40
+#: gtk2_ardour/editor_actions.cc:60
 msgid "Monitoring"
 msgstr "Monitoring"
 
-#: gtk2_ardour/editor_actions.cc:41
+#: gtk2_ardour/editor_actions.cc:61
 msgid "Autoconnect"
 msgstr "Automatisch verbinden"
 
-#: gtk2_ardour/editor_actions.cc:42
+#: gtk2_ardour/editor_actions.cc:62
 msgid "Layering"
 msgstr "Layering"
 
-#: gtk2_ardour/editor_actions.cc:43
+#: gtk2_ardour/editor_actions.cc:63
 msgid "Timecode fps"
 msgstr "Timecode FPS"
 
-#: gtk2_ardour/editor_actions.cc:44
+#: gtk2_ardour/editor_actions.cc:64
 msgid "Pullup / Pulldown"
 msgstr "Pull-Up / Pull-Down"
 
-#: gtk2_ardour/editor_actions.cc:45
+#: gtk2_ardour/editor_actions.cc:65
 msgid "Subframes"
 msgstr "Subframes"
 
-#: gtk2_ardour/editor_actions.cc:46
-msgid "Add Existing Audio"
-msgstr "Audio importieren"
+#: gtk2_ardour/editor_actions.cc:66
+#, fuzzy
+msgid "Locate To Markers"
+msgstr "Positionsmarker"
 
-#: gtk2_ardour/editor_actions.cc:51
+#: gtk2_ardour/editor_actions.cc:70
+msgid "Link Region/Track Selection"
+msgstr "Spurauswahl folgt Auswahl der Region"
+
+#: gtk2_ardour/editor_actions.cc:72
 msgid "Show Editor Mixer"
 msgstr "Mixer-Panel zeigen"
 
-#: gtk2_ardour/editor_actions.cc:56
+#: gtk2_ardour/editor_actions.cc:77
 msgid "Span Entire Overlap"
 msgstr "Gesamte Ãœberlappung"
 
-#: gtk2_ardour/editor_actions.cc:65
+#: gtk2_ardour/editor_actions.cc:86
 msgid "Created Automatically"
 msgstr "Automatisch erzeugen"
 
-#: gtk2_ardour/editor_actions.cc:68
+#: gtk2_ardour/editor_actions.cc:89
+msgid "Playhead to Next Region Boundary"
+msgstr "Positionszeiger zur nächsten Regiongrenze"
+
+#: gtk2_ardour/editor_actions.cc:91
+msgid "Playhead to Previous Region Boundary"
+msgstr "Positionszeiger zur vorherigen Regiongrenze"
+
+#: gtk2_ardour/editor_actions.cc:94
 msgid "Playhead to Next Region Start"
 msgstr "Positionszeiger zum Anfang der nächsten Region"
 
-#: gtk2_ardour/editor_actions.cc:70
+#: gtk2_ardour/editor_actions.cc:96
 msgid "Playhead to Next Region End"
 msgstr "Positionszeiger zum Ende der nächsten Region"
 
-#: gtk2_ardour/editor_actions.cc:72
+#: gtk2_ardour/editor_actions.cc:98
 msgid "Playhead to Next Region Sync"
-msgstr "Positionszeiger zum Sync der nächsten Region"
+msgstr "Positionszeiger zum Einrastpunkt der nächsten Region"
 
-#: gtk2_ardour/editor_actions.cc:75
+#: gtk2_ardour/editor_actions.cc:101
 msgid "Playhead to Previous Region Start"
 msgstr "Positionszeiger zum Anfang der vorherigen Region"
 
-#: gtk2_ardour/editor_actions.cc:77
+#: gtk2_ardour/editor_actions.cc:103
 msgid "Playhead to Previous Region End"
 msgstr "Positionszeiger zum Ende der vorherigen Region"
 
-#: gtk2_ardour/editor_actions.cc:79
+#: gtk2_ardour/editor_actions.cc:105
 msgid "Playhead to Previous Region Sync"
-msgstr "Positionszeiger zum Sync der vorherigen Region"
-
-#: gtk2_ardour/editor_actions.cc:82
-msgid "Edit Cursor to Next Region Start"
-msgstr "Editierzeiger zum Anfang der nächsten Region"
-
-#: gtk2_ardour/editor_actions.cc:84
-msgid "Edit Cursor to Next Region End"
-msgstr "Editierzeiger zum Ende der nächsten Region"
+msgstr "Positionszeiger zum Einrastpunkt der vorherigen Region"
 
-#: gtk2_ardour/editor_actions.cc:86
-msgid "Edit Cursor to Next Region Sync"
-msgstr "Editierzeiger zum Sync der nächsten Region"
+#: gtk2_ardour/editor_actions.cc:108
+msgid "to Next Region Boundary"
+msgstr "zur nächsten Regiongrenze"
 
-#: gtk2_ardour/editor_actions.cc:89
-msgid "Edit Cursor to Previous Region Start"
-msgstr "Editierzeiger zum Anfang der vorherigen Region"
+#: gtk2_ardour/editor_actions.cc:110
+msgid "to Previous Region Boundary"
+msgstr "zur vorherigen Regiongrenze"
 
-#: gtk2_ardour/editor_actions.cc:91
-msgid "Edit Cursor to Previous Region End"
-msgstr "Editierzeiger zum Ende der vorherigen Region"
+#: gtk2_ardour/editor_actions.cc:113
+msgid "to Next Region Start"
+msgstr "zum Anfang der nächsten Region"
 
-#: gtk2_ardour/editor_actions.cc:93
-msgid "Edit Cursor to Previous Region Sync"
-msgstr "Editierzeiger zum Sync der vorherigen Region"
+#: gtk2_ardour/editor_actions.cc:115
+msgid "to Next Region End"
+msgstr "zum Ende der nächsten Region"
 
-#: gtk2_ardour/editor_actions.cc:96
-msgid "Playhead to Range Start"
-msgstr "Positionszeiger zum Anfang der Auswahl"
+#: gtk2_ardour/editor_actions.cc:117
+msgid "to Next Region Sync"
+msgstr "zum Einrastpunkt der nächsten Region"
 
-#: gtk2_ardour/editor_actions.cc:98
-msgid "Playhead to Range End"
-msgstr "Positionszeiger zum Ende der Auswahl"
+#: gtk2_ardour/editor_actions.cc:120
+msgid "to Previous Region Start"
+msgstr "zum Anfang der vorherigen Region"
 
-#: gtk2_ardour/editor_actions.cc:101
-msgid "Edit Cursor to Range Start"
-msgstr "Editierzeiger zum Anfang der Auswahl"
+#: gtk2_ardour/editor_actions.cc:122
+msgid "to Previous Region End"
+msgstr "zum Ende der vorherigen Region"
 
-#: gtk2_ardour/editor_actions.cc:103
-msgid "Edit Cursor to Range End"
-msgstr "Editierzeiger zum Ende der Auswahl"
+#: gtk2_ardour/editor_actions.cc:124
+msgid "to Previous Region Sync"
+msgstr "zum Einrastpunkt der vorherigen Region"
 
-#: gtk2_ardour/editor_actions.cc:106
-#: gtk2_ardour/editor_selection.cc:726
-msgid "select all"
-msgstr "Alle Regionen auswählen"
+#: gtk2_ardour/editor_actions.cc:127
+msgid "to Range Start"
+msgstr "zum Anfang des Auswahlbereichs"
 
-#: gtk2_ardour/editor_actions.cc:108
-msgid "Select All After Edit Cursor"
-msgstr "Alle Regionen nach dem Editierzeiger auswählen"
+#: gtk2_ardour/editor_actions.cc:129
+msgid "to Range End"
+msgstr "zum Ende des Auswahlbereichs"
 
-#: gtk2_ardour/editor_actions.cc:110
-msgid "Select All Before Edit Cursor"
-msgstr "Alle Regionen vor dem Editierzeiger auswählen"
+#: gtk2_ardour/editor_actions.cc:132
+msgid "Playhead to Range Start"
+msgstr "Positionszeiger zum Anfang des Auswahlbereichs"
 
-#: gtk2_ardour/editor_actions.cc:113
-msgid "Select All After Playhead"
-msgstr "Alle Regionen nach dem Positionszeiger auswählen"
+#: gtk2_ardour/editor_actions.cc:134
+msgid "Playhead to Range End"
+msgstr "Positionszeiger zum Ende des Auswahlbereichs"
 
-#: gtk2_ardour/editor_actions.cc:115
-msgid "Select All Before Playhead"
-msgstr "Alle Regionen vor dem Positionszeiger auswählen"
+#: gtk2_ardour/editor_actions.cc:139
+#: gtk2_ardour/redirect_box.cc:1195
+msgid "Deselect All"
+msgstr "Nichts auswählen"
 
-#: gtk2_ardour/editor_actions.cc:117
-msgid "Select All Between Cursors"
-msgstr "Alle Regionen zwischen den Zeigern auswählen"
+#: gtk2_ardour/editor_actions.cc:141
+msgid "Invert Selection"
+msgstr "Auswahl umkehren"
 
-#: gtk2_ardour/editor_actions.cc:120
+#: gtk2_ardour/editor_actions.cc:160
 msgid "Select All in Punch Range"
 msgstr "Alle Regionen im Punch-Bereich auswählen"
 
-#: gtk2_ardour/editor_actions.cc:122
+#: gtk2_ardour/editor_actions.cc:162
 msgid "Select All in Loop Range"
 msgstr "Alle Regionen innerhalb der Schleife auswählen"
 
-#: gtk2_ardour/editor_actions.cc:125
+#: gtk2_ardour/editor_actions.cc:165
+msgid "Select Next Track/Bus"
+msgstr "Nächste Spur/Bus auswählen"
+
+#: gtk2_ardour/editor_actions.cc:167
+msgid "Select Previous Track/Bus"
+msgstr "Vorherige Spur/Bus auswählen"
+
+#: gtk2_ardour/editor_actions.cc:171
+#, fuzzy
+msgid "Locate to Mark 1"
+msgstr "Zu Marker 1 "
+
+#: gtk2_ardour/editor_actions.cc:173
+#, fuzzy
+msgid "Locate to Mark 2"
+msgstr "Positionszeiger zu Marker setzen"
+
+#: gtk2_ardour/editor_actions.cc:175
+#, fuzzy
+msgid "Locate to Mark 3"
+msgstr "Positionszeiger zu Marker setzen"
+
+#: gtk2_ardour/editor_actions.cc:177
+#, fuzzy
+msgid "Locate to Mark 4"
+msgstr "Positionszeiger zu Marker setzen"
+
+#: gtk2_ardour/editor_actions.cc:179
+#, fuzzy
+msgid "Locate to Mark 5"
+msgstr "Positionszeiger zu Marker setzen"
+
+#: gtk2_ardour/editor_actions.cc:181
+#, fuzzy
+msgid "Locate to Mark 6"
+msgstr "Positionszeiger zu Marker setzen"
+
+#: gtk2_ardour/editor_actions.cc:183
+#, fuzzy
+msgid "Locate to Mark 7"
+msgstr "Positionszeiger zu Marker setzen"
+
+#: gtk2_ardour/editor_actions.cc:185
+#, fuzzy
+msgid "Locate to Mark 8"
+msgstr "Positionszeiger zu Marker setzen"
+
+#: gtk2_ardour/editor_actions.cc:187
+#, fuzzy
+msgid "Locate to Mark 9"
+msgstr "Positionszeiger zu Marker setzen"
+
+#: gtk2_ardour/editor_actions.cc:190
 msgid "Jump Forward to Mark"
 msgstr "Zum nächsten Marker springen"
 
-#: gtk2_ardour/editor_actions.cc:127
+#: gtk2_ardour/editor_actions.cc:192
 msgid "Jump Backward to Mark"
 msgstr "Zum vorherigen Marker springen"
 
-#: gtk2_ardour/editor_actions.cc:129
+#: gtk2_ardour/editor_actions.cc:194
 msgid "Add Mark from Playhead"
 msgstr "Marker am Positionszeiger setzen"
 
-#: gtk2_ardour/editor_actions.cc:132
+#: gtk2_ardour/editor_actions.cc:197
 msgid "Nudge Forward"
 msgstr "Schritt nach vorne"
 
-#: gtk2_ardour/editor_actions.cc:134
+#: gtk2_ardour/editor_actions.cc:199
 msgid "Nudge Next Forward"
-msgstr "nächste Region Schritt vorwärts"
+msgstr "Nächste Region Schritt vorwärts"
 
-#: gtk2_ardour/editor_actions.cc:136
+#: gtk2_ardour/editor_actions.cc:201
 msgid "Nudge Backward"
 msgstr "Schritt nach Hinten"
 
-#: gtk2_ardour/editor_actions.cc:138
+#: gtk2_ardour/editor_actions.cc:203
 msgid "Nudge Next Backward"
-msgstr "Nächste Region Schritt nach vorne"
+msgstr "Nächste Region Schritt rückwärts"
 
-#: gtk2_ardour/editor_actions.cc:148
+#: gtk2_ardour/editor_actions.cc:213
+msgid "Zoom to Region"
+msgstr "Auf Region zoomen"
+
+#: gtk2_ardour/editor_actions.cc:215
+msgid "Toggle Zoom State"
+msgstr ""
+
+#: gtk2_ardour/editor_actions.cc:218
 msgid "Scroll Tracks Up"
 msgstr "Spuren nach oben scrollen"
 
-#: gtk2_ardour/editor_actions.cc:150
+#: gtk2_ardour/editor_actions.cc:220
 msgid "Scroll Tracks Down"
 msgstr "Spuren nach unten scrollen"
 
-#: gtk2_ardour/editor_actions.cc:152
+#: gtk2_ardour/editor_actions.cc:222
 msgid "Step Tracks Up"
 msgstr "Spuren langsam nach oben scrollen"
 
-#: gtk2_ardour/editor_actions.cc:154
+#: gtk2_ardour/editor_actions.cc:224
 msgid "Step Tracks Down"
 msgstr "Spuren langsam nach unten scrollen"
 
-#: gtk2_ardour/editor_actions.cc:157
+#: gtk2_ardour/editor_actions.cc:227
 msgid "Scroll Backward"
 msgstr "Vorwärts scrollen"
 
-#: gtk2_ardour/editor_actions.cc:159
+#: gtk2_ardour/editor_actions.cc:229
 msgid "Scroll Forward"
 msgstr "Rückwärts scrollen"
 
-#: gtk2_ardour/editor_actions.cc:161
+#: gtk2_ardour/editor_actions.cc:231
 msgid "goto"
 msgstr "Gehe zu"
 
-#: gtk2_ardour/editor_actions.cc:163
-msgid "Center Playhead"
-msgstr "Ansicht am Positionszeiger zentrieren"
-
-#: gtk2_ardour/editor_actions.cc:165
-msgid "Center Edit Cursor"
-msgstr "Editierzeiger zentrieren"
+#: gtk2_ardour/editor_actions.cc:233
+#: gtk2_ardour/editor_actions.cc:235
+msgid "to Center"
+msgstr "zur Mitte"
 
-#: gtk2_ardour/editor_actions.cc:168
+#: gtk2_ardour/editor_actions.cc:238
 msgid "Playhead forward"
 msgstr "Positionszeiger vorwärts"
 
-#: gtk2_ardour/editor_actions.cc:170
+#: gtk2_ardour/editor_actions.cc:240
 msgid "Playhead Backward"
 msgstr "Positionszeiger rückwärts"
 
-#: gtk2_ardour/editor_actions.cc:173
-msgid "Playhead to Edit"
-msgstr "Positionszeiger zum Editierzeiger setzen"
+#: gtk2_ardour/editor_actions.cc:243
+msgid "to Edit"
+msgstr "Positionszeiger zum Arbeitspunkt"
 
-#: gtk2_ardour/editor_actions.cc:175
-msgid "Edit to Playhead"
-msgstr "Editierzeiger zum Positionszeiger setzen"
+#: gtk2_ardour/editor_actions.cc:245
+msgid "to Playhead"
+msgstr "zum Positionszeiger"
+
+#: gtk2_ardour/editor_actions.cc:248
+msgid "Trim start at edit point"
+msgstr "Schneide Regionanfang am Arbeitspunkt"
+
+#: gtk2_ardour/editor_actions.cc:250
+msgid "Trim end at edit point"
+msgstr "Schneide Regionende am Arbeitspunkt"
+
+#: gtk2_ardour/editor_actions.cc:262
+msgid "Set Loop From Edit Range"
+msgstr "Schleife aus Editierbereich erstellen"
+
+#: gtk2_ardour/editor_actions.cc:264
+msgid "Set Loop From Region"
+msgstr "Schleife aus Region erstellen"
+
+#: gtk2_ardour/editor_actions.cc:268
+msgid "Set Punch From Edit Range"
+msgstr "Punch-Bereich aus Editierbereich erstellen"
 
-#: gtk2_ardour/editor_actions.cc:178
+#: gtk2_ardour/editor_actions.cc:272
+msgid "Transpose"
+msgstr "Transponieren"
+
+#: gtk2_ardour/editor_actions.cc:275
+msgid "Set Fade In Length"
+msgstr "Ändere Fade-In Länge"
+
+#: gtk2_ardour/editor_actions.cc:277
+msgid "Toggle Fade In Active"
+msgstr "Fade-In aktivieren"
+
+#: gtk2_ardour/editor_actions.cc:279
+msgid "Set Fade Out Length"
+msgstr "Fade-Out verändern"
+
+#: gtk2_ardour/editor_actions.cc:281
+msgid "Toggle Fade Out Active"
+msgstr "Fade-Out aktivieren"
+
+#: gtk2_ardour/editor_actions.cc:284
 msgid "Align Regions Start"
 msgstr "Anfang der Regionen ausrichten"
 
-#: gtk2_ardour/editor_actions.cc:180
+#: gtk2_ardour/editor_actions.cc:286
 msgid "Align Regions Start Relative"
 msgstr "Anfang der Regionen relativ ausrichten"
 
-#: gtk2_ardour/editor_actions.cc:182
+#: gtk2_ardour/editor_actions.cc:288
 msgid "Align Regions End"
-msgstr "ardour: Region"
+msgstr "Regionenenden ausrichten"
 
-#: gtk2_ardour/editor_actions.cc:184
+#: gtk2_ardour/editor_actions.cc:290
 msgid "Align Regions End Relative"
 msgstr "Regionenenden relativ ausrichten"
 
-#: gtk2_ardour/editor_actions.cc:187
+#: gtk2_ardour/editor_actions.cc:293
 msgid "Align Regions Sync"
-msgstr "ardour: Region"
+msgstr "Regionen-Einrastpunkt ausrichten"
 
-#: gtk2_ardour/editor_actions.cc:189
+#: gtk2_ardour/editor_actions.cc:295
 msgid "Align Regions Sync Relative"
-msgstr "Regionen-Sync relativ ausrichten"
+msgstr "Regionen-Einrastpunkt relativ ausrichten"
 
-#: gtk2_ardour/editor_actions.cc:192
-msgid "Audition at Mouse"
-msgstr "An Mauszeigerposition vorhören"
+#: gtk2_ardour/editor_actions.cc:298
+msgid "Play From Edit Point"
+msgstr "Wiedergabe ab Arbeitspunkt"
 
-#: gtk2_ardour/editor_actions.cc:194
+#: gtk2_ardour/editor_actions.cc:300
+msgid "Play from Edit Point & Return"
+msgstr "Wiedergabe ab Arbeitspunkt & Return"
+
+#: gtk2_ardour/editor_actions.cc:303
+msgid "Play Edit Range"
+msgstr "Editierbereich wiedergeben"
+
+#: gtk2_ardour/editor_actions.cc:304
+msgid "Play Selected Region(s)"
+msgstr "Ausgewählte Regionen wiedergeben"
+
+#: gtk2_ardour/editor_actions.cc:306
 msgid "Brush at Mouse"
 msgstr "Pinsel an Mausposition (Brush)"
 
-#: gtk2_ardour/editor_actions.cc:196
-msgid "Set Edit Cursor"
-msgstr "Editierzeiger setzen"
-
-#: gtk2_ardour/editor_actions.cc:198
+#: gtk2_ardour/editor_actions.cc:308
 msgid "Mute/Unmute Region"
 msgstr "Region Mute/Unmute"
 
-#: gtk2_ardour/editor_actions.cc:200
+#: gtk2_ardour/editor_actions.cc:311
 msgid "Set Playhead"
 msgstr "Positionszeiger setzen"
 
-#: gtk2_ardour/editor_actions.cc:202
+#: gtk2_ardour/editor_actions.cc:313
+msgid "Set Edit Point"
+msgstr "Arbeitspunkt setzen"
+
+#: gtk2_ardour/editor_actions.cc:315
 msgid "Split Region"
 msgstr "Region teilen (Split)"
 
-#: gtk2_ardour/editor_actions.cc:204
+#: gtk2_ardour/editor_actions.cc:317
 msgid "Set Region Sync Position"
-msgstr "Sync-Position der Region setzen"
+msgstr "Einrastpunkt der Region setzen"
 
-#: gtk2_ardour/editor_actions.cc:212
+#: gtk2_ardour/editor_actions.cc:325
 msgid "Export Session"
-msgstr "Projekt exportieren"
+msgstr "Projekt exportieren..."
 
-#: gtk2_ardour/editor_actions.cc:214
+#: gtk2_ardour/editor_actions.cc:327
 msgid "Export Range"
-msgstr "Bereich exportieren"
+msgstr "Bereiche exportieren..."
 
-#: gtk2_ardour/editor_actions.cc:220
+#: gtk2_ardour/editor_actions.cc:330
+msgid "Separate"
+msgstr "Teilen"
+
+#: gtk2_ardour/editor_actions.cc:332
+#: gtk2_ardour/editor_actions.cc:355
+#, fuzzy
+msgid "Crop"
+msgstr "Kopieren"
+
+#: gtk2_ardour/editor_actions.cc:337
+#: gtk2_ardour/redirect_box.cc:1188
 #: gtk2_ardour/connection_editor.cc:55
 msgid "Delete"
 msgstr "Löschen"
 
-#: gtk2_ardour/editor_actions.cc:226
+#: gtk2_ardour/editor_actions.cc:343
 msgid "Duplicate Region"
 msgstr "Duplizieren"
 
-#: gtk2_ardour/editor_actions.cc:228
+#: gtk2_ardour/editor_actions.cc:345
+msgid "Multi-Duplicate Region"
+msgstr "Region mehrfach Duplizieren"
+
+#: gtk2_ardour/editor_actions.cc:347
 msgid "Duplicate Range"
 msgstr "Bereich duplizieren"
 
-#: gtk2_ardour/editor_actions.cc:230
+#: gtk2_ardour/editor_actions.cc:349
 msgid "Insert Region"
 msgstr "Einfügen"
 
-#: gtk2_ardour/editor_actions.cc:232
+#: gtk2_ardour/editor_actions.cc:351
 msgid "Reverse Region"
 msgstr "Rückwärts"
 
-#: gtk2_ardour/editor_actions.cc:234
+#: gtk2_ardour/editor_actions.cc:353
 msgid "Normalize Region"
 msgstr "Normalisieren"
 
-#: gtk2_ardour/editor_actions.cc:236
-msgid "crop"
-msgstr "Abschneiden"
-
-#: gtk2_ardour/editor_actions.cc:238
+#: gtk2_ardour/editor_actions.cc:357
 msgid "Insert Chunk"
 msgstr "Abschnitt einfügen"
 
-#: gtk2_ardour/editor_actions.cc:241
-msgid "Split at edit cursor"
-msgstr "Am Editierzeiger trennen"
+#: gtk2_ardour/editor_actions.cc:360
+msgid "Split At Edit Point"
+msgstr "Am Arbeitspunkt trennen"
 
-#: gtk2_ardour/editor_actions.cc:244
+#: gtk2_ardour/editor_actions.cc:363
 msgid "Start Range"
-msgstr "Bereich anfangen"
+msgstr "Bereich beginnen"
 
-#: gtk2_ardour/editor_actions.cc:246
+#: gtk2_ardour/editor_actions.cc:365
 msgid "Finish Range"
 msgstr "Bereich beenden"
 
-#: gtk2_ardour/editor_actions.cc:248
+#: gtk2_ardour/editor_actions.cc:367
 msgid "Finish add Range"
 msgstr "Bereich hinzufügen beenden"
 
-#: gtk2_ardour/editor_actions.cc:251
-msgid "Extend Range to End of Region"
-msgstr "Bereich vergrößern bis zum Ende der Region "
-
-#: gtk2_ardour/editor_actions.cc:253
-msgid "Extend Range to Start of Region"
-msgstr "Bereich vergrößern bis zum Anfang der Region "
-
-#: gtk2_ardour/editor_actions.cc:256
+#: gtk2_ardour/editor_actions.cc:375
 msgid "Follow Playhead"
 msgstr "Positionszeiger folgen"
 
-#: gtk2_ardour/editor_actions.cc:264
+#: gtk2_ardour/editor_actions.cc:383
 msgid "Zoom Focus Left"
 msgstr "Am linken Rand ausrichten"
 
-#: gtk2_ardour/editor_actions.cc:266
+#: gtk2_ardour/editor_actions.cc:385
 msgid "Zoom Focus Right"
 msgstr "Am rechten Rand ausrichten"
 
-#: gtk2_ardour/editor_actions.cc:268
+#: gtk2_ardour/editor_actions.cc:387
 msgid "Zoom Focus Center"
 msgstr "Zentriert ausrichten"
 
-#: gtk2_ardour/editor_actions.cc:270
+#: gtk2_ardour/editor_actions.cc:389
 msgid "Zoom Focus Playhead"
 msgstr "Am Positionszeiger ausrichten"
 
-#: gtk2_ardour/editor_actions.cc:272
+#: gtk2_ardour/editor_actions.cc:391
+msgid "Zoom Focus Mouse"
+msgstr "Zoom Fokus zur Maus"
+
+#: gtk2_ardour/editor_actions.cc:393
 msgid "Zoom Focus Edit"
 msgstr "Am Editierzeiger ausrichten"
 
-#: gtk2_ardour/editor_actions.cc:278
+#: gtk2_ardour/editor_actions.cc:399
 msgid "Object Tool"
 msgstr "Objektwerkzeug"
 
-#: gtk2_ardour/editor_actions.cc:279
+#: gtk2_ardour/editor_actions.cc:400
 msgid "Range Tool"
 msgstr "Bereich-Werkzeug (Range)"
 
-#: gtk2_ardour/editor_actions.cc:280
+#: gtk2_ardour/editor_actions.cc:401
 msgid "Gain Tool"
 msgstr "Lautstärkewerkzeug (Gain)"
 
-#: gtk2_ardour/editor_actions.cc:281
+#: gtk2_ardour/editor_actions.cc:402
 msgid "Zoom Tool"
 msgstr "Zoom-Werkzeug"
 
-#: gtk2_ardour/editor_actions.cc:282
-msgid "Timefx Tool"
-msgstr "Zeit-Werkzeug (Time)"
+#: gtk2_ardour/editor_actions.cc:403
+msgid "Timefx Tool"
+msgstr "Zeit-Werkzeug (Time)"
+
+#: gtk2_ardour/editor_actions.cc:410
+msgid "Change edit point"
+msgstr "Arbeitspunkt Ã¤ndern"
+
+#: gtk2_ardour/editor_actions.cc:411
+msgid "Change edit point (w/Marker)"
+msgstr "Setze Arbeitspunkt (über Positionsmarker)"
+
+#: gtk2_ardour/editor_actions.cc:413
+#, fuzzy
+msgid "Splice"
+msgstr "Teilen"
+
+#: gtk2_ardour/editor_actions.cc:414
+#, fuzzy
+msgid "Slide"
+msgstr "Verbergen"
 
-#: gtk2_ardour/editor_actions.cc:284
+#: gtk2_ardour/editor_actions.cc:415
+msgid "Toggle Edit Mode"
+msgstr ""
+
+#: gtk2_ardour/editor_actions.cc:417
 msgid "Snap To"
 msgstr "Raster"
 
-#: gtk2_ardour/editor_actions.cc:285
+#: gtk2_ardour/editor_actions.cc:418
 msgid "Snap Mode"
 msgstr "Einrastmodus"
 
-#: gtk2_ardour/editor_actions.cc:294
-msgid "Snap to frame"
-msgstr "An Frames einrasten"
+#: gtk2_ardour/editor_actions.cc:425
+msgid "Next Snap Mode"
+msgstr "Nächster Einrastmodus"
 
-#: gtk2_ardour/editor_actions.cc:295
+#: gtk2_ardour/editor_actions.cc:426
+msgid "Next Snap Choice"
+msgstr ""
+
+#: gtk2_ardour/editor_actions.cc:431
 msgid "Snap to cd frame"
 msgstr "An CD-Frames einrasten"
 
-#: gtk2_ardour/editor_actions.cc:296
+#: gtk2_ardour/editor_actions.cc:432
 msgid "Snap to SMPTE frame"
 msgstr "An SMPTE-Frames einrasten"
 
-#: gtk2_ardour/editor_actions.cc:297
+#: gtk2_ardour/editor_actions.cc:433
 msgid "Snap to SMPTE seconds"
 msgstr "An SMPTE-Sekunden einrasten"
 
-#: gtk2_ardour/editor_actions.cc:298
+#: gtk2_ardour/editor_actions.cc:434
 msgid "Snap to SMPTE minutes"
 msgstr "An SMPTE-Minuten einrasten"
 
-#: gtk2_ardour/editor_actions.cc:299
+#: gtk2_ardour/editor_actions.cc:435
 msgid "Snap to seconds"
 msgstr "An Sekunden einrasten"
 
-#: gtk2_ardour/editor_actions.cc:300
+#: gtk2_ardour/editor_actions.cc:436
 msgid "Snap to minutes"
 msgstr "An Minuten einrasten"
 
-#: gtk2_ardour/editor_actions.cc:301
+#: gtk2_ardour/editor_actions.cc:437
 msgid "Snap to thirtyseconds"
 msgstr "An halben Minuten einrasten"
 
-#: gtk2_ardour/editor_actions.cc:302
+#: gtk2_ardour/editor_actions.cc:438
 msgid "Snap to asixteenthbeat"
 msgstr "An Sechzehnteln einrasten"
 
-#: gtk2_ardour/editor_actions.cc:303
+#: gtk2_ardour/editor_actions.cc:439
 msgid "Snap to eighths"
 msgstr "An Achteln einrasten"
 
-#: gtk2_ardour/editor_actions.cc:304
+#: gtk2_ardour/editor_actions.cc:440
 msgid "Snap to quarters"
 msgstr "An Vierteln einrasten"
 
-#: gtk2_ardour/editor_actions.cc:305
+#: gtk2_ardour/editor_actions.cc:441
 msgid "Snap to thirds"
 msgstr "An Triolen einrasten"
 
-#: gtk2_ardour/editor_actions.cc:306
+#: gtk2_ardour/editor_actions.cc:442
 msgid "Snap to beat"
 msgstr "An Schlägen einrasten"
 
-#: gtk2_ardour/editor_actions.cc:307
+#: gtk2_ardour/editor_actions.cc:443
 msgid "Snap to bar"
 msgstr "An Takten einrasten"
 
-#: gtk2_ardour/editor_actions.cc:308
+#: gtk2_ardour/editor_actions.cc:444
 msgid "Snap to mark"
 msgstr "An Markern einrasten"
 
-#: gtk2_ardour/editor_actions.cc:309
-msgid "Snap to edit cursor"
-msgstr "Am Editierzeiger einrasten"
-
-#: gtk2_ardour/editor_actions.cc:310
+#: gtk2_ardour/editor_actions.cc:445
 msgid "Snap to region start"
 msgstr "Am Anfang der Regionen einrasten"
 
-#: gtk2_ardour/editor_actions.cc:311
+#: gtk2_ardour/editor_actions.cc:446
 msgid "Snap to region end"
 msgstr "Am Ende der Regionen einrasten"
 
-#: gtk2_ardour/editor_actions.cc:312
+#: gtk2_ardour/editor_actions.cc:447
 msgid "Snap to region sync"
-msgstr "Am Sync der Regionen einrasten"
+msgstr "Am Einrastpunkt der Regionen einrasten"
 
-#: gtk2_ardour/editor_actions.cc:313
+#: gtk2_ardour/editor_actions.cc:448
 msgid "Snap to region boundary"
 msgstr "An Grenzen der Regionen einrasten"
 
-#: gtk2_ardour/editor_actions.cc:322
+#: gtk2_ardour/editor_actions.cc:457
 msgid "Sort"
 msgstr "Sortieren"
 
-#: gtk2_ardour/editor_actions.cc:330
+#: gtk2_ardour/editor_actions.cc:465
 msgid "Show all"
 msgstr "Alle zeigen"
 
-#: gtk2_ardour/editor_actions.cc:331
+#: gtk2_ardour/editor_actions.cc:466
 msgid "Show automatic regions"
 msgstr "Automatische Regionen zeigen"
 
-#: gtk2_ardour/editor_actions.cc:333
+#: gtk2_ardour/editor_actions.cc:468
 msgid "Ascending"
 msgstr "aufsteigend"
 
-#: gtk2_ardour/editor_actions.cc:335
+#: gtk2_ardour/editor_actions.cc:470
 msgid "Descending"
 msgstr "absteigend"
 
-#: gtk2_ardour/editor_actions.cc:338
+#: gtk2_ardour/editor_actions.cc:473
 msgid "By Region Name"
 msgstr "nach Name der Region"
 
-#: gtk2_ardour/editor_actions.cc:340
+#: gtk2_ardour/editor_actions.cc:475
 msgid "By Region Length"
 msgstr "nach Länge der Region"
 
-#: gtk2_ardour/editor_actions.cc:342
+#: gtk2_ardour/editor_actions.cc:477
 msgid "By Region Position"
 msgstr "nach Position der Region"
 
-#: gtk2_ardour/editor_actions.cc:344
+#: gtk2_ardour/editor_actions.cc:479
 msgid "By Region Timestamp"
 msgstr "nach Zeitstempel der Region"
 
-#: gtk2_ardour/editor_actions.cc:346
+#: gtk2_ardour/editor_actions.cc:481
 msgid "By Region Start in File"
 msgstr "nach Anfang der Region in der Datei"
 
-#: gtk2_ardour/editor_actions.cc:348
+#: gtk2_ardour/editor_actions.cc:483
 msgid "By Region End in File"
 msgstr "nach Ende der Region in der Datei"
 
-#: gtk2_ardour/editor_actions.cc:350
+#: gtk2_ardour/editor_actions.cc:485
 msgid "By Source File Name"
 msgstr "nach Namen der Quelldatei"
 
-#: gtk2_ardour/editor_actions.cc:352
+#: gtk2_ardour/editor_actions.cc:487
 msgid "By Source File Length"
 msgstr "nach Länge der Quelldatei"
 
-#: gtk2_ardour/editor_actions.cc:354
+#: gtk2_ardour/editor_actions.cc:489
 msgid "By Source File Creation Date"
 msgstr "nach Erstellungsdatum der Quelldatei"
 
-#: gtk2_ardour/editor_actions.cc:356
+#: gtk2_ardour/editor_actions.cc:491
 msgid "By Source Filesystem"
 msgstr "nach Dateisystem der Quelle"
 
-#: gtk2_ardour/editor_actions.cc:362
+#: gtk2_ardour/editor_actions.cc:497
+msgid "Add Existing Audio"
+msgstr "Audio importieren"
+
+#: gtk2_ardour/editor_actions.cc:499
 msgid "Add External Audio"
 msgstr "Audio importieren..."
 
-#: gtk2_ardour/editor_actions.cc:364
-msgid "as Region(s)"
-msgstr "als Region(en)..."
-
-#: gtk2_ardour/editor_actions.cc:366
-msgid "as Tracks"
-msgstr "als neue Spur(en)..."
-
-#: gtk2_ardour/editor_actions.cc:368
-msgid "as Tape Tracks"
-msgstr "als neue Tape-Spur(en)..."
-
-#: gtk2_ardour/editor_actions.cc:370
-msgid "to Tracks"
-msgstr "in vorhandene Spuren..."
-
-#: gtk2_ardour/editor_actions.cc:373
+#: gtk2_ardour/editor_actions.cc:502
 msgid "Show Waveforms"
 msgstr "Wellenformen zeigen"
 
-#: gtk2_ardour/editor_actions.cc:374
+#: gtk2_ardour/editor_actions.cc:503
 msgid "Show Waveforms While Recording"
 msgstr "Wellenformen beim Aufnehmen zeigen"
 
-#: gtk2_ardour/editor_actions.cc:375
+#: gtk2_ardour/editor_actions.cc:504
 msgid "Show Measures"
 msgstr "Takte zeigen"
 
-#: gtk2_ardour/editor_actions.cc:379
+#: gtk2_ardour/editor_actions.cc:508
+msgid "Show Logo"
+msgstr "Zeige Logo"
+
+#: gtk2_ardour/editor_actions.cc:514
 msgid "Later is Higher"
 msgstr "Neuste nach oben"
 
-#: gtk2_ardour/editor_actions.cc:380
+#: gtk2_ardour/editor_actions.cc:515
 msgid "Most Recently Moved/Added is Higher"
 msgstr "Zuletzt bewegte/hinzugefügte nach oben"
 
-#: gtk2_ardour/editor_actions.cc:381
+#: gtk2_ardour/editor_actions.cc:516
 msgid "Most Recently Added is Higher"
 msgstr "Zuletzt hinzugefügte nach oben"
 
-#: gtk2_ardour/editor_actions.cc:385
+#: gtk2_ardour/editor_actions.cc:520
 msgid "23.976"
-msgstr ""
+msgstr "23,976"
 
-#: gtk2_ardour/editor_actions.cc:386
+#: gtk2_ardour/editor_actions.cc:521
 msgid "24"
-msgstr ""
+msgstr "24"
 
-#: gtk2_ardour/editor_actions.cc:387
+#: gtk2_ardour/editor_actions.cc:522
 msgid "24.976"
-msgstr ""
+msgstr "24,976"
 
-#: gtk2_ardour/editor_actions.cc:388
+#: gtk2_ardour/editor_actions.cc:523
 msgid "25"
-msgstr ""
+msgstr "25"
 
-#: gtk2_ardour/editor_actions.cc:389
+#: gtk2_ardour/editor_actions.cc:524
 msgid "29.97"
-msgstr ""
+msgstr "29,97"
 
-#: gtk2_ardour/editor_actions.cc:390
+#: gtk2_ardour/editor_actions.cc:525
 msgid "29.97 drop"
-msgstr ""
+msgstr "29,97 (drop)"
 
-#: gtk2_ardour/editor_actions.cc:391
+#: gtk2_ardour/editor_actions.cc:526
 msgid "30"
-msgstr ""
+msgstr "30"
 
-#: gtk2_ardour/editor_actions.cc:392
+#: gtk2_ardour/editor_actions.cc:527
 msgid "30 drop"
-msgstr ""
+msgstr "30 (drop)"
 
-#: gtk2_ardour/editor_actions.cc:393
+#: gtk2_ardour/editor_actions.cc:528
 msgid "59.94"
-msgstr ""
+msgstr "59,94"
 
-#: gtk2_ardour/editor_actions.cc:394
+#: gtk2_ardour/editor_actions.cc:529
 msgid "60"
-msgstr ""
+msgstr "60"
 
-#: gtk2_ardour/editor_actions.cc:398
+#: gtk2_ardour/editor_actions.cc:533
 msgid "+4.1667% + 0.1%"
-msgstr ""
+msgstr "+4,1667% + 0,1%"
 
-#: gtk2_ardour/editor_actions.cc:399
+#: gtk2_ardour/editor_actions.cc:534
 msgid "+4.1667%"
-msgstr ""
+msgstr "+4,1667%"
 
-#: gtk2_ardour/editor_actions.cc:400
+#: gtk2_ardour/editor_actions.cc:535
 msgid "+4.1667% - 0.1%"
-msgstr ""
+msgstr "+4,1667% - 0,1%"
 
-#: gtk2_ardour/editor_actions.cc:401
+#: gtk2_ardour/editor_actions.cc:536
 msgid "+ 0.1%"
-msgstr ""
+msgstr "+ 0,1%"
 
-#: gtk2_ardour/editor_actions.cc:403
+#: gtk2_ardour/editor_actions.cc:537
+#: gtk2_ardour/engine_dialog.cc:98
+#: gtk2_ardour/engine_dialog.cc:103
+#: gtk2_ardour/engine_dialog.cc:479
+#: gtk2_ardour/export_dialog.cc:78
+#: gtk2_ardour/export_dialog.cc:92
+#: gtk2_ardour/export_dialog.cc:956
+#: gtk2_ardour/export_dialog.cc:1294
+#: gtk2_ardour/route_ui.cc:513
+msgid "None"
+msgstr "Kein"
+
+#: gtk2_ardour/editor_actions.cc:538
 msgid "- 0.1%"
-msgstr ""
+msgstr "- 0,1%"
 
-#: gtk2_ardour/editor_actions.cc:404
+#: gtk2_ardour/editor_actions.cc:539
 msgid "-4.1667% + 0.1%"
-msgstr ""
+msgstr "-4,1667% + 0,1%"
 
-#: gtk2_ardour/editor_actions.cc:405
+#: gtk2_ardour/editor_actions.cc:540
 msgid "-4.1667%"
-msgstr ""
+msgstr "-4,1667%"
 
-#: gtk2_ardour/editor_actions.cc:406
+#: gtk2_ardour/editor_actions.cc:541
 msgid "-4.1667% - 0.1%"
-msgstr ""
+msgstr "-4,1667% - 0,1%"
 
-#: gtk2_ardour/editor_actions.cc:410
+#: gtk2_ardour/editor_actions.cc:545
 msgid "80 per frame"
 msgstr "80 pro Frame"
 
-#: gtk2_ardour/editor_actions.cc:411
+#: gtk2_ardour/editor_actions.cc:547
 msgid "100 per frame"
 msgstr "100 pro Frame"
 
-#: gtk2_ardour/editor_actions.cc:714
-#: gtk2_ardour/editor_actions.cc:759
-#: gtk2_ardour/editor_actions.cc:770
-#: gtk2_ardour/editor_actions.cc:814
-#: gtk2_ardour/editor_actions.cc:824
+#: gtk2_ardour/editor_actions.cc:863
+#: gtk2_ardour/editor_actions.cc:972
+#: gtk2_ardour/editor_actions.cc:983
+#: gtk2_ardour/editor_actions.cc:1036
+#: gtk2_ardour/editor_actions.cc:1047
+#: gtk2_ardour/editor_actions.cc:1094
+#: gtk2_ardour/editor_actions.cc:1104
 msgid "programming error: %1: %2"
 msgstr "Programmierfehler: %1: %2"
 
-#: gtk2_ardour/editor_actions.cc:985
+#: gtk2_ardour/editor_actions.cc:1265
 msgid "Configuraton is using unhandled subframes per frame value: %1"
 msgstr "Diese Konfiguration benutzt einen unzulässigen Wert für Subframes pro Frame: %1"
 
-#: gtk2_ardour/editor_audio_import.cc:84
+#: gtk2_ardour/editor_audio_import.cc:71
+#: gtk2_ardour/editor_audio_import.cc:92
 msgid "You can't import or embed an audiofile until you have a session loaded."
 msgstr "Sie können keine Audiodatei importieren, solange kein Projekt geladen ist."
 
-#: gtk2_ardour/editor_audio_import.cc:89
-msgid "Add existing audio to session"
+#: gtk2_ardour/editor_audio_import.cc:77
+#: gtk2_ardour/editor_audio_import.cc:110
+msgid "Add existing audio"
 msgstr "Audio importieren"
 
-#: gtk2_ardour/editor_audio_import.cc:176
-msgid "Import as a %1 region"
-msgstr "Importiere als eine %1 Region"
-
-#: gtk2_ardour/editor_audio_import.cc:177
-msgid "multichannel"
-msgstr "Mehrkanal"
-
-#: gtk2_ardour/editor_audio_import.cc:177
-#: gtk2_ardour/export_dialog.cc:86
-msgid "stereo"
-msgstr "Stereo"
-
-#: gtk2_ardour/editor_audio_import.cc:178
-msgid "Import as multiple regions"
-msgstr "In mehrere Regionen aufteilen"
-
-#: gtk2_ardour/editor_audio_import.cc:180
-msgid ""
-"Paired files detected (%1, %2 ...).\n"
-"Do you want to:"
-msgstr ""
-"Zusammenhängende Dateien gefunden (%1, %2 ...).\n"
-"Wollen Sie:"
-
-#: gtk2_ardour/editor_audio_import.cc:226
+#: gtk2_ardour/editor_audio_import.cc:370
 msgid "importing %1"
 msgstr "importiere %1"
 
-#: gtk2_ardour/editor_audio_import.cc:232
+#: gtk2_ardour/editor_audio_import.cc:376
 msgid "Cancel Import"
 msgstr "Importieren Abbrechen"
 
-#: gtk2_ardour/editor_audio_import.cc:332
+#: gtk2_ardour/editor_audio_import.cc:479
 msgid "Editor: cannot open file \"%1\", (%2)"
 msgstr "Editor: kann die Datei \"%1\" nicht Ã¶ffnen (%2)"
 
-#: gtk2_ardour/editor_audio_import.cc:340
+#: gtk2_ardour/editor_audio_import.cc:487
 msgid "Cancel entire import"
 msgstr "Importieren Abbrechen"
 
-#: gtk2_ardour/editor_audio_import.cc:341
+#: gtk2_ardour/editor_audio_import.cc:488
 msgid "Don't embed it"
 msgstr "Nicht einbetten"
 
-#: gtk2_ardour/editor_audio_import.cc:342
+#: gtk2_ardour/editor_audio_import.cc:489
 msgid "Embed all without questions"
 msgstr "Alle Importieren ohne nachzufragen"
 
-#: gtk2_ardour/editor_audio_import.cc:345
-#: gtk2_ardour/editor_audio_import.cc:370
+#: gtk2_ardour/editor_audio_import.cc:492
+#: gtk2_ardour/editor_audio_import.cc:519
 msgid ""
 "%1\n"
 "This audiofile's sample rate doesn't match the session sample rate!"
@@ -3714,52 +4131,44 @@ msgstr ""
 "%1\n"
 "Die Samplerate dieser Audiodatei unterscheidet sich von der Samplerate dieses Projekts."
 
-#: gtk2_ardour/editor_audio_import.cc:367
+#: gtk2_ardour/editor_audio_import.cc:516
 msgid "Embed it anyway"
 msgstr "Trotzdem importieren"
 
-#: gtk2_ardour/editor_audio_import.cc:417
+#: gtk2_ardour/editor_audio_import.cc:561
 msgid "could not open %1"
 msgstr "Konnte \"%s\" nicht Ã¶ffnen."
 
-#: gtk2_ardour/editor_audio_import.cc:464
+#: gtk2_ardour/editor_audio_import.cc:691
 msgid "insert sndfile"
 msgstr "Audiodatei einfügen"
 
-#: gtk2_ardour/editor_canvas.cc:118
+#: gtk2_ardour/editor_canvas.cc:129
 msgid "VerboseCanvasCursor"
 msgstr ""
 
-#: gtk2_ardour/editor_canvas.cc:267
-msgid "edit cursor color not defined, check your ardour.colors file!"
-msgstr "Die Farbe für den Editierzeiger ist nicht definiert, bitte in ardour.colors prüfen!"
-
-#: gtk2_ardour/editor_canvas.cc:272
-msgid "playhead color not defined, check your ardour.colors file!"
-msgstr "Die Farbe für den Wiedergabezeiger ist nicht definiert, bitte in ardour.colors prüfen!"
-
 #: gtk2_ardour/editor_edit_groups.cc:52
-#: gtk2_ardour/mixer_ui.cc:765
+#: gtk2_ardour/mixer_ui.cc:848
 msgid "Activate All"
 msgstr "Alle aktivieren"
 
 #: gtk2_ardour/editor_edit_groups.cc:53
-#: gtk2_ardour/mixer_ui.cc:766
+#: gtk2_ardour/mixer_ui.cc:849
 msgid "Disable All"
 msgstr "Alle deaktivieren"
 
 #: gtk2_ardour/editor_edit_groups.cc:55
-#: gtk2_ardour/mixer_ui.cc:768
+#: gtk2_ardour/mixer_ui.cc:851
 msgid "Add group"
 msgstr "Gruppe hinzufügen"
 
 #: gtk2_ardour/editor_edit_groups.cc:228
-#: gtk2_ardour/mixer_ui.cc:1009
+#: gtk2_ardour/mixer_ui.cc:1092
 msgid "unnamed"
 msgstr "unbenannt"
 
 #: gtk2_ardour/editor_edit_groups.cc:257
-#: gtk2_ardour/mixer_ui.cc:863
+#: gtk2_ardour/mixer_ui.cc:946
 msgid "-all-"
 msgstr "-alle-"
 
@@ -3769,11 +4178,11 @@ msgid ""
 "\n"
 "Select a selection using the range mouse mode"
 msgstr ""
-"Es wurde keine Auswahl zum Exportieren getroffen.\n"
+"Es wurde keine Auswahlbereich zum Exportieren erstellt.\n"
 "\n"
 "Erstellen Sie eine Auswahl mit dem Bereichswerkzeug"
 
-#: gtk2_ardour/editor_export_audio.cc:111
+#: gtk2_ardour/editor_export_audio.cc:109
 msgid ""
 "There are no ranges to export.\n"
 "\n"
@@ -3793,305 +4202,293 @@ msgstr "Programmierfehler: kein ImageFrameView ausgewählt"
 msgid "programming error: no MarkerView selected"
 msgstr "Programmierfehler: kein MarkerView ausgewählt"
 
-#: gtk2_ardour/editor_keyboard.cc:104
+#: gtk2_ardour/editor_keyboard.cc:82
 msgid "mute region"
 msgstr "Region stummschalten"
 
-#: gtk2_ardour/editor_keys.cc:45
-msgid "keyboard selection"
-msgstr "Tastaturauswahl"
-
-#: gtk2_ardour/editor_markers.cc:296
-#: gtk2_ardour/editor_ops.cc:1241
-#: gtk2_ardour/editor_ops.cc:1258
-#: gtk2_ardour/editor_ops.cc:1277
-#: gtk2_ardour/location_ui.cc:782
+#: gtk2_ardour/editor_markers.cc:399
+#: gtk2_ardour/editor_ops.cc:1794
+#: gtk2_ardour/editor_ops.cc:1811
+#: gtk2_ardour/editor_ops.cc:1836
+#: gtk2_ardour/location_ui.cc:821
 msgid "add marker"
 msgstr "Marker hinzufügen"
 
-#: gtk2_ardour/editor_markers.cc:312
-#: gtk2_ardour/editor_markers.cc:376
-#: gtk2_ardour/editor_markers.cc:553
-#: gtk2_ardour/editor_markers.cc:571
-#: gtk2_ardour/editor_markers.cc:589
-#: gtk2_ardour/editor_markers.cc:608
-#: gtk2_ardour/editor_markers.cc:627
-#: gtk2_ardour/editor_markers.cc:657
-#: gtk2_ardour/editor_markers.cc:685
-#: gtk2_ardour/editor_markers.cc:713
-#: gtk2_ardour/editor_markers.cc:752
-#: gtk2_ardour/editor_markers.cc:777
-#: gtk2_ardour/editor_markers.cc:804
-#: gtk2_ardour/editor_markers.cc:827
-#: gtk2_ardour/editor_markers.cc:846
-#: gtk2_ardour/editor_mouse.cc:2015
-#: gtk2_ardour/editor_mouse.cc:4351
+#: gtk2_ardour/editor_markers.cc:423
+#: gtk2_ardour/editor_markers.cc:491
+#: gtk2_ardour/editor_markers.cc:676
+#: gtk2_ardour/editor_markers.cc:694
+#: gtk2_ardour/editor_markers.cc:712
+#: gtk2_ardour/editor_markers.cc:731
+#: gtk2_ardour/editor_markers.cc:750
+#: gtk2_ardour/editor_markers.cc:780
+#: gtk2_ardour/editor_markers.cc:808
+#: gtk2_ardour/editor_markers.cc:836
+#: gtk2_ardour/editor_markers.cc:874
+#: gtk2_ardour/editor_markers.cc:899
+#: gtk2_ardour/editor_markers.cc:926
+#: gtk2_ardour/editor_markers.cc:949
+#: gtk2_ardour/editor_markers.cc:969
+#: gtk2_ardour/editor_markers.cc:993
+#: gtk2_ardour/editor_mouse.cc:2139
+#: gtk2_ardour/editor_mouse.cc:4686
 msgid "programming error: marker canvas item has no marker object pointer!"
 msgstr "Programmierfehler: marker canvas item has no marker object pointer!"
 
-#: gtk2_ardour/editor_markers.cc:326
-#: gtk2_ardour/location_ui.cc:660
+#: gtk2_ardour/editor_markers.cc:441
+#: gtk2_ardour/location_ui.cc:699
 msgid "remove marker"
 msgstr "Marker entfernen"
 
-#: gtk2_ardour/editor_markers.cc:467
-msgid "Locate to Mark"
-msgstr "Positionszeiger zu Marker setzen"
-
-#: gtk2_ardour/editor_markers.cc:468
-msgid "Play from Mark"
-msgstr "Wiedergabe ab Marker"
+#: gtk2_ardour/editor_markers.cc:582
+msgid "Locate to here"
+msgstr "Positionszeiger hierhin setzen"
 
-#: gtk2_ardour/editor_markers.cc:469
-msgid "Set Mark from Playhead"
-msgstr "Marker am Positionszeiger setzen"
+#: gtk2_ardour/editor_markers.cc:583
+msgid "Play from here"
+msgstr "Wiedergabe ab hier"
 
-#: gtk2_ardour/editor_markers.cc:473
-msgid "Hide Mark"
-msgstr "Marker verbergen"
+#: gtk2_ardour/editor_markers.cc:584
+msgid "Move Mark to Playhead"
+msgstr "Marker zum Positionszeiger verschieben"
 
-#: gtk2_ardour/editor_markers.cc:475
-#: gtk2_ardour/editor_markers.cc:864
-msgid "Rename Mark"
-msgstr "Marker umbenennen"
+#: gtk2_ardour/editor_markers.cc:592
+msgid "Unlock"
+msgstr "Entsperren"
 
-#: gtk2_ardour/editor_markers.cc:476
-msgid "Remove Mark"
-msgstr "Marker entfernen"
+#: gtk2_ardour/editor_markers.cc:614
+msgid "Play Range"
+msgstr "Bereich wiedergeben"
 
-#: gtk2_ardour/editor_markers.cc:494
+#: gtk2_ardour/editor_markers.cc:615
 msgid "Locate to Range Mark"
 msgstr "Positionszeiger zu Bereichsmarker"
 
-#: gtk2_ardour/editor_markers.cc:495
+#: gtk2_ardour/editor_markers.cc:616
 msgid "Play from Range Mark"
 msgstr "Wiedergabe ab Bereichsmarker"
 
-#: gtk2_ardour/editor_markers.cc:497
-msgid "Play Range"
-msgstr "Bereich wiedergeben"
-
-#: gtk2_ardour/editor_markers.cc:498
+#: gtk2_ardour/editor_markers.cc:618
 msgid "Loop Range"
 msgstr "Bereich in Schleife wiedergeben"
 
-#: gtk2_ardour/editor_markers.cc:500
+#: gtk2_ardour/editor_markers.cc:620
 msgid "Set Range Mark from Playhead"
 msgstr "Bereichsmarker zum Positionszeiger verschieben"
 
-#: gtk2_ardour/editor_markers.cc:501
+#: gtk2_ardour/editor_markers.cc:622
 msgid "Set Range from Range Selection"
 msgstr "Bereichsmarker zum Auswahlbereich verschieben"
 
-#: gtk2_ardour/editor_markers.cc:505
+#: gtk2_ardour/editor_markers.cc:628
 msgid "Hide Range"
 msgstr "Bereich verbergen"
 
-#: gtk2_ardour/editor_markers.cc:507
-#: gtk2_ardour/editor_markers.cc:866
+#: gtk2_ardour/editor_markers.cc:629
+#: gtk2_ardour/editor_markers.cc:1013
 msgid "Rename Range"
 msgstr "Bereich umbenennen"
 
-#: gtk2_ardour/editor_markers.cc:508
+#: gtk2_ardour/editor_markers.cc:630
 msgid "Remove Range"
 msgstr "Bereich entfernen"
 
-#: gtk2_ardour/editor_markers.cc:513
+#: gtk2_ardour/editor_markers.cc:635
 msgid "Separate Regions in Range"
 msgstr "Regionen an Bereichsgrenzen teilen"
 
-#: gtk2_ardour/editor_markers.cc:514
+#: gtk2_ardour/editor_markers.cc:636
 msgid "Select All in Range"
 msgstr "Alles im Bereich auswählen"
 
-#: gtk2_ardour/editor_markers.cc:515
+#: gtk2_ardour/editor_markers.cc:638
 msgid "Select Range"
 msgstr "Bereich auswählen"
 
-#: gtk2_ardour/editor_markers.cc:541
+#: gtk2_ardour/editor_markers.cc:664
 msgid "Set Loop Range"
 msgstr "Schleife erstellen"
 
-#: gtk2_ardour/editor_markers.cc:542
+#: gtk2_ardour/editor_markers.cc:665
 msgid "Set Punch Range"
 msgstr "Punch-Bereich erstellen"
 
-#: gtk2_ardour/editor_markers.cc:860
+#: gtk2_ardour/editor_markers.cc:1007
 msgid "New Name:"
 msgstr "Neuer Name: "
 
-#: gtk2_ardour/editor_markers.cc:888
+#: gtk2_ardour/editor_markers.cc:1011
+msgid "Rename Mark"
+msgstr "Marker umbenennen"
+
+#: gtk2_ardour/editor_markers.cc:1035
 msgid "rename marker"
 msgstr "Marker umbenennen"
 
-#: gtk2_ardour/editor_markers.cc:914
+#: gtk2_ardour/editor_markers.cc:1059
 msgid "set loop range"
 msgstr "Loop-Bereich festlegen"
 
-#: gtk2_ardour/editor_markers.cc:942
+#: gtk2_ardour/editor_markers.cc:1065
 msgid "set punch range"
 msgstr "Punch-Bereich festlegen"
 
-#: gtk2_ardour/editor_mouse.cc:105
+#: gtk2_ardour/editor_mouse.cc:144
 msgid "Editor::event_frame() used on unhandled event type %1"
 msgstr ""
 
-#: gtk2_ardour/editor_mouse.cc:1539
+#: gtk2_ardour/editor_mouse.cc:1696
 msgid "programming error: start_grab called without drag item"
 msgstr "Programmierfehler: start_grab called without drag item"
 
-#: gtk2_ardour/editor_mouse.cc:1766
+#: gtk2_ardour/editor_mouse.cc:1898
 msgid "change fade in length"
 msgstr "Ändere Fade-In Länge"
 
-#: gtk2_ardour/editor_mouse.cc:1798
+#: gtk2_ardour/editor_mouse.cc:1930
 msgid "programming error: fade out canvas item has no regionview data pointer!"
 msgstr "Programmierfehler: fade out canvas item has no regionview data pointer!"
 
-#: gtk2_ardour/editor_mouse.cc:1883
+#: gtk2_ardour/editor_mouse.cc:2014
 msgid "change fade out length"
 msgstr "Fade-Out verändern"
 
-#: gtk2_ardour/editor_mouse.cc:1915
+#: gtk2_ardour/editor_mouse.cc:2046
 msgid "programming error: cursor canvas item has no cursor data pointer!"
 msgstr "Programmierfehler: cursor canvas item has no cursor data pointer!"
 
-#: gtk2_ardour/editor_mouse.cc:2150
+#: gtk2_ardour/editor_mouse.cc:2301
 msgid "move marker"
 msgstr "Marker bewegen"
 
-#: gtk2_ardour/editor_mouse.cc:2178
-#: gtk2_ardour/editor_mouse.cc:2209
-#: gtk2_ardour/editor_tempodisplay.cc:500
+#: gtk2_ardour/editor_mouse.cc:2334
+#: gtk2_ardour/editor_mouse.cc:2366
+#: gtk2_ardour/editor_tempodisplay.cc:505
 msgid "programming error: meter marker canvas item has no marker object pointer!"
 msgstr "pProgrammierfehler: meter marker canvas item has no marker object pointer!"
 
-#: gtk2_ardour/editor_mouse.cc:2277
+#: gtk2_ardour/editor_mouse.cc:2434
 msgid "copy meter mark"
 msgstr "Taktmarker kopieren"
 
-#: gtk2_ardour/editor_mouse.cc:2288
+#: gtk2_ardour/editor_mouse.cc:2445
 msgid "move meter mark"
 msgstr "Taktwechsel bewegen"
 
-#: gtk2_ardour/editor_mouse.cc:2304
-#: gtk2_ardour/editor_mouse.cc:2337
-#: gtk2_ardour/editor_tempodisplay.cc:369
-#: gtk2_ardour/editor_tempodisplay.cc:449
-#: gtk2_ardour/editor_tempodisplay.cc:468
+#: gtk2_ardour/editor_mouse.cc:2461
+#: gtk2_ardour/editor_mouse.cc:2495
+#: gtk2_ardour/editor_tempodisplay.cc:373
+#: gtk2_ardour/editor_tempodisplay.cc:454
+#: gtk2_ardour/editor_tempodisplay.cc:473
 msgid "programming error: tempo marker canvas item has no marker object pointer!"
 msgstr "Programmierfehler: tempo marker canvas item has no marker object pointer!"
 
-#: gtk2_ardour/editor_mouse.cc:2309
-#: gtk2_ardour/editor_mouse.cc:2342
-#: gtk2_ardour/editor_tempodisplay.cc:374
-#: gtk2_ardour/editor_tempodisplay.cc:454
+#: gtk2_ardour/editor_mouse.cc:2466
+#: gtk2_ardour/editor_mouse.cc:2500
+#: gtk2_ardour/editor_tempodisplay.cc:378
+#: gtk2_ardour/editor_tempodisplay.cc:459
 msgid "programming error: marker for tempo is not a tempo marker!"
 msgstr "Programmierfehler: marker for tempo is not a tempo marker!"
 
-#: gtk2_ardour/editor_mouse.cc:2409
+#: gtk2_ardour/editor_mouse.cc:2567
 msgid "copy tempo mark"
 msgstr "Tempomarker kopieren"
 
-#: gtk2_ardour/editor_mouse.cc:2420
+#: gtk2_ardour/editor_mouse.cc:2578
 msgid "move tempo mark"
 msgstr "Tempowechsel bewegen"
 
-#: gtk2_ardour/editor_mouse.cc:2435
-#: gtk2_ardour/editor_mouse.cc:2454
-#: gtk2_ardour/editor_mouse.cc:2467
+#: gtk2_ardour/editor_mouse.cc:2593
+#: gtk2_ardour/editor_mouse.cc:2612
+#: gtk2_ardour/editor_mouse.cc:2625
 msgid "programming error: control point canvas item has no control point object pointer!"
 msgstr "Programmierfehler: control point canvas item has no control point object pointer!"
 
-#: gtk2_ardour/editor_mouse.cc:2573
+#: gtk2_ardour/editor_mouse.cc:2761
 msgid "programming error: line canvas item has no line pointer!"
 msgstr "Programmierfehler:  line canvas item has no line pointer!"
 
-#: gtk2_ardour/editor_mouse.cc:2682
+#: gtk2_ardour/editor_mouse.cc:2900
 msgid "move region(s)"
 msgstr "Region(en) bewegen"
 
-#: gtk2_ardour/editor_mouse.cc:2746
+#: gtk2_ardour/editor_mouse.cc:2964
 msgid "Drag region brush"
 msgstr "Region Brush ziehen"
 
-#: gtk2_ardour/editor_mouse.cc:3274
+#: gtk2_ardour/editor_mouse.cc:3595
 msgid "fixed time region copy"
 msgstr "Region zeitgleich kopieren"
 
-#: gtk2_ardour/editor_mouse.cc:3276
+#: gtk2_ardour/editor_mouse.cc:3597
 msgid "region copy"
 msgstr "Region kopieren"
 
-#: gtk2_ardour/editor_mouse.cc:3280
+#: gtk2_ardour/editor_mouse.cc:3601
 msgid "fixed time region drag"
 msgstr "Region zeitgleich verschieben"
 
-#: gtk2_ardour/editor_mouse.cc:3282
+#: gtk2_ardour/editor_mouse.cc:3603
 msgid "region drag"
 msgstr "Region verschieben"
 
-#: gtk2_ardour/editor_mouse.cc:3670
+#: gtk2_ardour/editor_mouse.cc:4007
 msgid "selection grab"
 msgstr "Auswählen"
 
-#: gtk2_ardour/editor_mouse.cc:3712
-msgid "cancel selection"
-msgstr "Auswahl abbrechen"
-
-#: gtk2_ardour/editor_mouse.cc:3822
+#: gtk2_ardour/editor_mouse.cc:4157
 msgid "range selection"
-msgstr "Bereichsauswahl"
+msgstr "Auswahlbereich"
 
-#: gtk2_ardour/editor_mouse.cc:3838
+#: gtk2_ardour/editor_mouse.cc:4173
 msgid "trim selection start"
 msgstr "Anfangspunkt der Auswahl abschneiden"
 
-#: gtk2_ardour/editor_mouse.cc:3854
+#: gtk2_ardour/editor_mouse.cc:4189
 msgid "trim selection end"
 msgstr "Endpunkt der Auswahl abschneiden"
 
-#: gtk2_ardour/editor_mouse.cc:3871
+#: gtk2_ardour/editor_mouse.cc:4206
 msgid "move selection"
 msgstr "Auswahl bewegen"
 
-#: gtk2_ardour/editor_mouse.cc:4260
+#: gtk2_ardour/editor_mouse.cc:4595
 msgid "Start point trim"
 msgstr "Anfangspunkt verändern"
 
-#: gtk2_ardour/editor_mouse.cc:4292
+#: gtk2_ardour/editor_mouse.cc:4627
 msgid "End point trim"
 msgstr "Endpunkt verändern"
 
-#: gtk2_ardour/editor_mouse.cc:4335
+#: gtk2_ardour/editor_mouse.cc:4670
 msgid "trimmed region"
 msgstr "Abgeschnittene Region"
 
-#: gtk2_ardour/editor_mouse.cc:4478
+#: gtk2_ardour/editor_mouse.cc:4817
 msgid "new range marker"
 msgstr "Neuer Bereich"
 
-#: gtk2_ardour/editor_mouse.cc:4720
+#: gtk2_ardour/editor_mouse.cc:5065
 msgid "rubberband selection"
 msgstr "Bereichsauswahl"
 
-#: gtk2_ardour/editor_mouse.cc:4750
+#: gtk2_ardour/editor_mouse.cc:5095
 msgid "Name for region:"
 msgstr "Name für Region:"
 
-#: gtk2_ardour/editor_mouse.cc:4814
+#: gtk2_ardour/editor_mouse.cc:5168
 msgid "timestretch"
 msgstr "Time-Stretch"
 
-#: gtk2_ardour/editor_ops.cc:116
+#: gtk2_ardour/editor_ops.cc:114
 msgid "split"
 msgstr "Teile"
 
-#: gtk2_ardour/editor_ops.cc:155
+#: gtk2_ardour/editor_ops.cc:180
 msgid "remove region"
 msgstr "Region(en) löschen"
 
-#: gtk2_ardour/editor_ops.cc:175
+#: gtk2_ardour/editor_ops.cc:200
 msgid ""
 " This is destructive, will possibly delete audio files\n"
 "It cannot be undone\n"
@@ -4101,177 +4498,188 @@ msgstr ""
 "Dies kann nicht rückgängig gemacht werden\n"
 "Wollen Sie %1 wirklich löschen ?"
 
-#: gtk2_ardour/editor_ops.cc:179
+#: gtk2_ardour/editor_ops.cc:204
 msgid "these regions"
 msgstr "diese Region"
 
-#: gtk2_ardour/editor_ops.cc:179
+#: gtk2_ardour/editor_ops.cc:204
 msgid "this region"
 msgstr "diese Region"
 
-#: gtk2_ardour/editor_ops.cc:184
+#: gtk2_ardour/editor_ops.cc:209
 msgid "Yes, destroy them."
 msgstr "Ja, entfernen."
 
-#: gtk2_ardour/editor_ops.cc:186
-#: gtk2_ardour/editor_ops.cc:3154
+#: gtk2_ardour/editor_ops.cc:211
+#: gtk2_ardour/editor_ops.cc:3955
 msgid "Yes, destroy it."
 msgstr "Ja, entfernen."
 
-#: gtk2_ardour/editor_ops.cc:272
-#: gtk2_ardour/editor_ops.cc:300
+#: gtk2_ardour/editor_ops.cc:297
+#: gtk2_ardour/editor_ops.cc:325
 msgid "extend selection"
 msgstr "Auswahl erweitern"
 
-#: gtk2_ardour/editor_ops.cc:316
-#: gtk2_ardour/editor_ops.cc:351
-#: gtk2_ardour/editor_ops.cc:396
-#: gtk2_ardour/editor_ops.cc:423
+#: gtk2_ardour/editor_ops.cc:341
+msgid "nudge regions forward"
+msgstr "Regionen Schritt vorwärts"
+
+#: gtk2_ardour/editor_ops.cc:368
+#: gtk2_ardour/editor_ops.cc:445
+msgid "nudge location forward"
+msgstr "Position Schritt vorwärts"
+
+#: gtk2_ardour/editor_ops.cc:414
+msgid "nudge regions backward"
+msgstr "Regionen Schritt nach hinten"
+
+#: gtk2_ardour/editor_ops.cc:497
+#: gtk2_ardour/editor_ops.cc:524
 msgid "nudge forward"
 msgstr "Schritt vorwärts"
 
-#: gtk2_ardour/editor_ops.cc:488
+#: gtk2_ardour/editor_ops.cc:591
 msgid "build_region_boundary_cache called with snap_type = %1"
 msgstr ""
 
-#: gtk2_ardour/editor_ops.cc:1398
+#: gtk2_ardour/editor_ops.cc:1634
+#: gtk2_ardour/editor_ops.cc:4709
+msgid "cannot set loop: no region selected"
+msgstr "Kann keine Schleife erstellen: keine Region ausgewählt"
+
+#: gtk2_ardour/editor_ops.cc:1957
 msgid "clear markers"
 msgstr "Marker zurücksetzen"
 
-#: gtk2_ardour/editor_ops.cc:1411
+#: gtk2_ardour/editor_ops.cc:1970
 msgid "clear ranges"
 msgstr "Bereiche zurücksetzen"
 
-#: gtk2_ardour/editor_ops.cc:1431
+#: gtk2_ardour/editor_ops.cc:1990
 msgid "clear locations"
 msgstr "Positionen zurücksetzen"
 
-#: gtk2_ardour/editor_ops.cc:1504
+#: gtk2_ardour/editor_ops.cc:2063
 msgid "insert dragged region"
 msgstr "Region ziehen"
 
-#: gtk2_ardour/editor_ops.cc:1547
+#: gtk2_ardour/editor_ops.cc:2110
 msgid "insert region"
 msgstr "Region einfügen"
 
-#: gtk2_ardour/editor_ops.cc:1746
-#: gtk2_ardour/io_selector.cc:59
-#: gtk2_ardour/io_selector.cc:747
-#: gtk2_ardour/connection_editor.cc:85
-msgid "OK"
-msgstr "OK"
-
-#: gtk2_ardour/editor_ops.cc:1754
+#: gtk2_ardour/editor_ops.cc:2321
 msgid "Rename Region"
 msgstr "Region umbenennen"
 
-#: gtk2_ardour/editor_ops.cc:1996
-#: gtk2_ardour/editor_ops.cc:2055
+#: gtk2_ardour/editor_ops.cc:2325
+msgid "New name:"
+msgstr "Neuer Name: "
+
+#: gtk2_ardour/editor_ops.cc:2624
 msgid "separate"
 msgstr "Teilen"
 
-#: gtk2_ardour/editor_ops.cc:2119
+#: gtk2_ardour/editor_ops.cc:2759
 msgid "trim to selection"
 msgstr "Auf Auswahl kürzen"
 
-#: gtk2_ardour/editor_ops.cc:2164
+#: gtk2_ardour/editor_ops.cc:2804
 msgid "region fill"
 msgstr "Region füllen"
 
-#: gtk2_ardour/editor_ops.cc:2228
+#: gtk2_ardour/editor_ops.cc:2868
 msgid "fill selection"
 msgstr "Auswahl füllen"
 
-#: gtk2_ardour/editor_ops.cc:2249
-msgid "Programming error. that region doesn't cover that position"
-msgstr "Programmierfehler: that region doesn't cover that position"
-
-#: gtk2_ardour/editor_ops.cc:2252
-msgid "set region sync position"
-msgstr "Sync-Position setzen"
-
-#: gtk2_ardour/editor_ops.cc:2268
-msgid "Place the edit cursor at the desired sync point"
-msgstr "Positionieren sie den Arbeits-Cursor am gewünschten Synchronisationspunkt"
-
-#: gtk2_ardour/editor_ops.cc:2273
-msgid "set sync from edit cursor"
-msgstr "Sync-Position an Editierzeiger setzen"
+#: gtk2_ardour/editor_ops.cc:2906
+msgid "set sync point"
+msgstr "Einrastpunkt definieren"
 
-#: gtk2_ardour/editor_ops.cc:2286
+#: gtk2_ardour/editor_ops.cc:2926
 msgid "remove sync"
-msgstr "Synchronisationspunkt entfernen"
+msgstr "Einrastpunkt entfernen"
 
-#: gtk2_ardour/editor_ops.cc:2301
+#: gtk2_ardour/editor_ops.cc:2941
 msgid "naturalize"
 msgstr "zur Ursprungsposition setzen"
 
-#: gtk2_ardour/editor_ops.cc:2366
+#: gtk2_ardour/editor_ops.cc:3026
 msgid "align selection (relative)"
 msgstr "Auswahl relativ ausrichten"
 
-#: gtk2_ardour/editor_ops.cc:2395
+#: gtk2_ardour/editor_ops.cc:3055
 msgid "align selection"
 msgstr "Auswahl ausrichten"
 
-#: gtk2_ardour/editor_ops.cc:2407
+#: gtk2_ardour/editor_ops.cc:3067
 msgid "align region"
 msgstr "Region ausrichten"
 
-#: gtk2_ardour/editor_ops.cc:2455
-#: gtk2_ardour/editor_ops.cc:2481
-msgid "trim to edit"
-msgstr "Am Editierzeiger abschneiden"
+#: gtk2_ardour/editor_ops.cc:3104
+msgid "trim to loop"
+msgstr "Auf Schleife kürzen"
+
+#: gtk2_ardour/editor_ops.cc:3114
+msgid "trim to punch"
+msgstr "Auf Punch-Bereich kürzen"
+
+#: gtk2_ardour/editor_ops.cc:3174
+msgid "trim region start to edit point"
+msgstr "Regionanfang bis Arbeitspunkt abschneiden"
 
-#: gtk2_ardour/editor_ops.cc:2540
+#: gtk2_ardour/editor_ops.cc:3216
+msgid "trim region end to edit point"
+msgstr "Regionende bis Arbeitspunkt abschneiden"
+
+#: gtk2_ardour/editor_ops.cc:3303
 msgid "Cancel Freeze"
 msgstr "Einfrieren abbrechen"
 
-#: gtk2_ardour/editor_ops.cc:2583
+#: gtk2_ardour/editor_ops.cc:3346
 msgid "bounce range"
 msgstr "Bereich Bouncen"
 
-#: gtk2_ardour/editor_ops.cc:2635
+#: gtk2_ardour/editor_ops.cc:3398
 msgid "cut"
 msgstr "Ausschneiden"
 
-#: gtk2_ardour/editor_ops.cc:2638
+#: gtk2_ardour/editor_ops.cc:3401
 msgid "copy"
 msgstr "Kopieren"
 
-#: gtk2_ardour/editor_ops.cc:2651
+#: gtk2_ardour/editor_ops.cc:3429
 msgid " objects"
 msgstr "Objekte"
 
-#: gtk2_ardour/editor_ops.cc:2677
+#: gtk2_ardour/editor_ops.cc:3469
 msgid " range"
 msgstr "Bereich"
 
-#: gtk2_ardour/editor_ops.cc:2906
+#: gtk2_ardour/editor_ops.cc:3698
 msgid "paste"
 msgstr "Einfügen"
 
-#: gtk2_ardour/editor_ops.cc:2948
+#: gtk2_ardour/editor_ops.cc:3747
 msgid "paste chunk"
 msgstr "Abschnitt einfügen"
 
-#: gtk2_ardour/editor_ops.cc:2991
+#: gtk2_ardour/editor_ops.cc:3791
 msgid "duplicate region"
 msgstr "Region duplizieren"
 
-#: gtk2_ardour/editor_ops.cc:3036
+#: gtk2_ardour/editor_ops.cc:3839
 msgid "duplicate selection"
 msgstr "Auswahl duplizieren"
 
-#: gtk2_ardour/editor_ops.cc:3092
+#: gtk2_ardour/editor_ops.cc:3893
 msgid "clear playlist"
 msgstr "Wiedergabeliste zurücksetzen"
 
-#: gtk2_ardour/editor_ops.cc:3122
+#: gtk2_ardour/editor_ops.cc:3923
 msgid "nudge track"
 msgstr "Spur verschieben"
 
-#: gtk2_ardour/editor_ops.cc:3150
+#: gtk2_ardour/editor_ops.cc:3951
 msgid ""
 "Do you really want to destroy the last capture?\n"
 "(This is destructive and cannot be undone)"
@@ -4279,161 +4687,228 @@ msgstr ""
 "Wollen Sie wirklich die letzte Aufnahme rückgängig machen?\n"
 "(Dies kann nicht rückgängig gemacht werden!)"
 
-#: gtk2_ardour/editor_ops.cc:3178
+#: gtk2_ardour/editor_ops.cc:3979
 msgid "normalize"
 msgstr "Normalisieren"
 
-#: gtk2_ardour/editor_ops.cc:3231
+#: gtk2_ardour/editor_ops.cc:4032
 msgid "reverse regions"
 msgstr "Regionen umkehren"
 
-#: gtk2_ardour/editor_ops.cc:3344
+#: gtk2_ardour/editor_ops.cc:4145
 msgid "reset region gain"
 msgstr "Lautstärkekurve zurücksetzen"
 
-#: gtk2_ardour/editor_ops.cc:3433
+#: gtk2_ardour/editor_ops.cc:4258
+msgid "set fade in length"
+msgstr "Ändere Fade-In Länge"
+
+#: gtk2_ardour/editor_ops.cc:4265
+msgid "set fade out length"
+msgstr "Ändere Fade-Out Länge"
+
+#: gtk2_ardour/editor_ops.cc:4305
+msgid "toggle fade in active"
+msgstr "Fade-In aktivieren"
+
+#: gtk2_ardour/editor_ops.cc:4305
+msgid "toggle fade out active"
+msgstr "Fade-Out aktivieren"
+
+#: gtk2_ardour/editor_ops.cc:4343
 msgid "set fade in shape"
 msgstr "Fade-In Kurve bearbeiten"
 
-#: gtk2_ardour/editor_ops.cc:3457
+#: gtk2_ardour/editor_ops.cc:4367
 msgid "set fade out shape"
 msgstr "Fade-Out Kurve Ã¤ndern"
 
-#: gtk2_ardour/editor_ops.cc:3481
+#: gtk2_ardour/editor_ops.cc:4391
 msgid "set fade in active"
 msgstr "Fade-In aktivieren"
 
-#: gtk2_ardour/editor_ops.cc:3505
+#: gtk2_ardour/editor_ops.cc:4415
 msgid "set fade out active"
 msgstr "Fade-Out aktivieren"
 
-#: gtk2_ardour/editor_region_list.cc:108
-#: gtk2_ardour/editor_region_list.cc:114
-#: gtk2_ardour/editor_region_list.cc:117
+#: gtk2_ardour/editor_ops.cc:4589
+msgid "trim front"
+msgstr "vorne abschneiden"
+
+#: gtk2_ardour/editor_ops.cc:4589
+msgid "trim back"
+msgstr "hinten Abschneiden"
+
+#: gtk2_ardour/editor_ops.cc:4670
+msgid "set loop range from selection"
+msgstr "Schleife aus Auswahl erstellen"
+
+#: gtk2_ardour/editor_ops.cc:4692
+msgid "set loop range from edit range"
+msgstr "Schleife aus Editierbereich erstellen"
+
+#: gtk2_ardour/editor_ops.cc:4722
+msgid "set loop range from region"
+msgstr "Schleife aus Region erstellen"
+
+#: gtk2_ardour/editor_ops.cc:4740
+msgid "set punch range from selection"
+msgstr "Punch-Bereich aus Auswahl erstellen"
+
+#: gtk2_ardour/editor_ops.cc:4757
+msgid "set punch range from edit range"
+msgstr "Punch-Bereich aus Editierbereich erstellen"
+
+#: gtk2_ardour/editor_region_list.cc:109
+#: gtk2_ardour/editor_region_list.cc:113
+#: gtk2_ardour/editor_region_list.cc:116
 #: gtk2_ardour/location_ui.cc:57
 msgid "Hidden"
 msgstr "Versteckt"
 
-#: gtk2_ardour/editor_region_list.cc:172
+#: gtk2_ardour/editor_region_list.cc:159
 msgid " (MISSING)"
 msgstr "(FEHLT)"
 
-#: gtk2_ardour/editor_route_list.cc:101
-#: gtk2_ardour/editor_route_list.cc:102
-#: gtk2_ardour/editor_route_list.cc:252
+#: gtk2_ardour/editor_route_list.cc:77
+#: gtk2_ardour/editor_route_list.cc:78
+#: gtk2_ardour/editor_route_list.cc:264
 msgid "editor"
 msgstr "Editor"
 
-#: gtk2_ardour/editor_route_list.cc:320
-#: gtk2_ardour/mixer_ui.cc:728
+#: gtk2_ardour/editor_route_list.cc:338
+#: gtk2_ardour/mixer_ui.cc:811
 msgid "Show All"
 msgstr "Alles zeigen"
 
-#: gtk2_ardour/editor_route_list.cc:321
-#: gtk2_ardour/mixer_ui.cc:729
+#: gtk2_ardour/editor_route_list.cc:339
+#: gtk2_ardour/mixer_ui.cc:812
 msgid "Hide All"
 msgstr "Alle verbergen"
 
-#: gtk2_ardour/editor_route_list.cc:322
-#: gtk2_ardour/mixer_ui.cc:730
+#: gtk2_ardour/editor_route_list.cc:340
+#: gtk2_ardour/mixer_ui.cc:813
 msgid "Show All Audio Tracks"
 msgstr "Zeige alle Audio-Spuren"
 
-#: gtk2_ardour/editor_route_list.cc:323
-#: gtk2_ardour/mixer_ui.cc:731
+#: gtk2_ardour/editor_route_list.cc:341
+#: gtk2_ardour/mixer_ui.cc:814
 msgid "Hide All Audio Tracks"
 msgstr "Verberge alle Audio-Spuren"
 
-#: gtk2_ardour/editor_route_list.cc:324
-#: gtk2_ardour/mixer_ui.cc:732
+#: gtk2_ardour/editor_route_list.cc:342
+#: gtk2_ardour/mixer_ui.cc:815
 msgid "Show All Audio Busses"
 msgstr "Zeige alle Audio-Busse"
 
-#: gtk2_ardour/editor_route_list.cc:325
-#: gtk2_ardour/mixer_ui.cc:733
+#: gtk2_ardour/editor_route_list.cc:343
+#: gtk2_ardour/mixer_ui.cc:816
 msgid "Hide All Audio Busses"
 msgstr "Verberge alle Audio-Busse"
 
-#: gtk2_ardour/editor_rulers.cc:345
+#: gtk2_ardour/editor_rulers.cc:366
 msgid "New location marker"
 msgstr "Neuer Positionsmarker"
 
-#: gtk2_ardour/editor_rulers.cc:346
+#: gtk2_ardour/editor_rulers.cc:367
 msgid "Clear all locations"
 msgstr "Alle Positionsmarker entfernen"
 
-#: gtk2_ardour/editor_rulers.cc:347
+#: gtk2_ardour/editor_rulers.cc:368
 msgid "Unhide locations"
 msgstr "Positionen anzeigen"
 
-#: gtk2_ardour/editor_rulers.cc:352
+#: gtk2_ardour/editor_rulers.cc:373
 msgid "Clear all ranges"
 msgstr "Alle Bereiche entfernen"
 
-#: gtk2_ardour/editor_rulers.cc:353
+#: gtk2_ardour/editor_rulers.cc:374
 msgid "Unhide ranges"
 msgstr "Bereiche anzeigen"
 
-#: gtk2_ardour/editor_rulers.cc:362
+#: gtk2_ardour/editor_rulers.cc:384
+msgid "New CD track marker"
+msgstr "Neuer CD-Track Marker"
+
+#: gtk2_ardour/editor_rulers.cc:389
 msgid "New Tempo"
 msgstr "Tempowechsel einfügen..."
 
-#: gtk2_ardour/editor_rulers.cc:363
+#: gtk2_ardour/editor_rulers.cc:390
 msgid "Clear tempo"
 msgstr "Tempo zurücksetzen"
 
-#: gtk2_ardour/editor_rulers.cc:368
+#: gtk2_ardour/editor_rulers.cc:395
 msgid "New Meter"
 msgstr "Taktwechsel einfügen..."
 
-#: gtk2_ardour/editor_rulers.cc:369
+#: gtk2_ardour/editor_rulers.cc:396
 msgid "Clear meter"
 msgstr "Taktart zurücksetzen"
 
-#: gtk2_ardour/editor_rulers.cc:377
+#: gtk2_ardour/editor_rulers.cc:404
 msgid "Min:Secs"
 msgstr "Min:Sek"
 
-#: gtk2_ardour/editor_selection.cc:564
-#: gtk2_ardour/editor_selection.cc:613
+#: gtk2_ardour/editor_selection.cc:740
 msgid "set selected regions"
 msgstr "Regionen auswählen"
 
-#: gtk2_ardour/editor_selection.cc:810
+#: gtk2_ardour/editor_selection.cc:850
+msgid "select all"
+msgstr "Alle Regionen auswählen"
+
+#: gtk2_ardour/editor_selection.cc:939
 msgid "select all within"
 msgstr "Alle im Bereich auswählen"
 
-#: gtk2_ardour/editor_selection.cc:840
+#: gtk2_ardour/editor_selection.cc:970
 msgid "set selection from region"
-msgstr "Auswahl von Region wählen"
+msgstr "Auswahlbereich von Region erstellen"
 
-#: gtk2_ardour/editor_selection.cc:873
+#: gtk2_ardour/editor_selection.cc:1003
 msgid "set selection from range"
-msgstr "Auswahl von Bereich wählen"
+msgstr "Auswahlbereich von Bereich erstellen"
 
-#: gtk2_ardour/editor_selection.cc:903
+#: gtk2_ardour/editor_selection.cc:1033
 msgid "select all from range"
 msgstr "Alle im Bereich auswählen"
 
-#: gtk2_ardour/editor_selection.cc:925
+#: gtk2_ardour/editor_selection.cc:1055
 msgid "select all from punch"
 msgstr "Alle im Punch-Bereich auswählen"
 
-#: gtk2_ardour/editor_selection.cc:947
+#: gtk2_ardour/editor_selection.cc:1077
 msgid "select all from loop"
 msgstr "Alle im Loop-Bereich auswählen"
 
-#: gtk2_ardour/editor_selection.cc:961
+#: gtk2_ardour/editor_selection.cc:1091
 msgid "select all after cursor"
 msgstr "Alle nach Positionszeiger auswählen"
 
-#: gtk2_ardour/editor_selection.cc:966
+#: gtk2_ardour/editor_selection.cc:1096
 msgid "select all before cursor"
 msgstr "Alle vor Positionszeiger auswählen"
 
-#: gtk2_ardour/editor_selection.cc:996
-msgid "select all between cursors"
-msgstr "Alle zwischen den Zeigern auswählen"
+#: gtk2_ardour/editor_selection.cc:1122
+msgid "select all after edit"
+msgstr "Alles nach Arbeitspunkt auswählen"
+
+#: gtk2_ardour/editor_selection.cc:1127
+msgid "select all before edit"
+msgstr "Alles vor Arbeitspunkt auswählen"
+
+#: gtk2_ardour/editor_selection.cc:1237
+msgid "No edit range defined"
+msgstr "Kein Editierbereich definiert"
+
+#: gtk2_ardour/editor_selection.cc:1243
+msgid ""
+"the edit point is Selected Marker\n"
+"but there is no selected marker."
+msgstr ""
+"der Arbeitspunkt ist der gewählte Positionsmarker,\n"
+"es ist aber kein Positionsmarker ausgewählt."
 
 #: gtk2_ardour/editor_selection_list.cc:180
 msgid "Name for Chunk:"
@@ -4451,157 +4926,399 @@ msgstr "Abbrechen"
 msgid "No selectable material found in the currently selected time range"
 msgstr "Konnte im ausgewählten Bereich kein auswählbares Material finden"
 
-#: gtk2_ardour/editor_tempodisplay.cc:290
-#: gtk2_ardour/editor_tempodisplay.cc:331
+#: gtk2_ardour/editor_tempodisplay.cc:293
+#: gtk2_ardour/editor_tempodisplay.cc:335
 msgid "add"
 msgstr "Hinzufügen"
 
-#: gtk2_ardour/editor_tempodisplay.cc:312
+#: gtk2_ardour/editor_tempodisplay.cc:316
 msgid "add tempo mark"
 msgstr "Tempowechsel einfügen"
 
-#: gtk2_ardour/editor_tempodisplay.cc:353
+#: gtk2_ardour/editor_tempodisplay.cc:357
 msgid "add meter mark"
 msgstr "Taktwechsel einfügen"
 
-#: gtk2_ardour/editor_tempodisplay.cc:386
-#: gtk2_ardour/editor_tempodisplay.cc:415
+#: gtk2_ardour/editor_tempodisplay.cc:390
+#: gtk2_ardour/editor_tempodisplay.cc:419
 msgid "done"
 msgstr "Fertig"
 
-#: gtk2_ardour/editor_tempodisplay.cc:404
-#: gtk2_ardour/editor_tempodisplay.cc:433
+#: gtk2_ardour/editor_tempodisplay.cc:408
+#: gtk2_ardour/editor_tempodisplay.cc:438
 msgid "replace tempo mark"
 msgstr "Tempowechsel ersetzen"
 
-#: gtk2_ardour/editor_tempodisplay.cc:473
-#: gtk2_ardour/editor_tempodisplay.cc:505
+#: gtk2_ardour/editor_tempodisplay.cc:478
+#: gtk2_ardour/editor_tempodisplay.cc:510
 msgid "programming error: marker for meter is not a meter marker!"
 msgstr "Programmierfehler: marker for meter is not a meter marker!"
 
-#: gtk2_ardour/editor_tempodisplay.cc:483
-#: gtk2_ardour/editor_tempodisplay.cc:517
+#: gtk2_ardour/editor_tempodisplay.cc:488
+#: gtk2_ardour/editor_tempodisplay.cc:522
 msgid "remove tempo mark"
 msgstr "Tempowechsel entfernen"
 
-#: gtk2_ardour/editor_timefx.cc:54
+#: gtk2_ardour/editor_timefx.cc:63
 msgid "Quick but Ugly"
 msgstr "Quick but Ugly"
 
-#: gtk2_ardour/editor_timefx.cc:55
+#: gtk2_ardour/editor_timefx.cc:64
 msgid "Skip Anti-aliasing"
 msgstr "Ãœberspringe Anti-Aliasing"
 
-#: gtk2_ardour/editor_timefx.cc:59
-msgid "TimeStretchDialog"
+#: gtk2_ardour/editor_timefx.cc:68
+msgid "TimeFXDialog"
 msgstr ""
 
-#: gtk2_ardour/editor_timefx.cc:62
-msgid "Timestretch"
+#: gtk2_ardour/editor_timefx.cc:72
+msgid "Pitch Shift"
+msgstr "Pitch-Shift"
+
+#: gtk2_ardour/editor_timefx.cc:74
+msgid "Time Stretch"
 msgstr "Time-Stretch"
 
-#: gtk2_ardour/editor_timefx.cc:76
-msgid "Stretch/Shrink it"
-msgstr "Time-Stretch ausführen"
+#: gtk2_ardour/editor_timefx.cc:92
+msgid "Octaves"
+msgstr "Oktaven"
 
-#: gtk2_ardour/editor_timefx.cc:79
-#: gtk2_ardour/editor_timefx.cc:80
-msgid "TimeStretchButton"
+#: gtk2_ardour/editor_timefx.cc:96
+msgid "Semitones (12TET)"
+msgstr "Halbtöne"
+
+#: gtk2_ardour/editor_timefx.cc:100
+msgid "Cents"
+msgstr "Cents"
+
+#: gtk2_ardour/editor_timefx.cc:106
+msgid "Shift"
+msgstr "Shift"
+
+#: gtk2_ardour/editor_timefx.cc:116
+msgid "Stretch/Shrink"
+msgstr "Stretch/Shrink"
+
+#: gtk2_ardour/editor_timefx.cc:119
+#: gtk2_ardour/editor_timefx.cc:120
+msgid "TimeFXButton"
 msgstr ""
 
-#: gtk2_ardour/editor_timefx.cc:81
-msgid "TimeStretchProgress"
+#: gtk2_ardour/editor_timefx.cc:121
+msgid "TimeFXProgress"
 msgstr ""
 
-#: gtk2_ardour/editor_timefx.cc:145
-msgid "timestretch cannot be started - thread creation error"
+#: gtk2_ardour/editor_timefx.cc:234
+#, fuzzy
+msgid "timefx cannot be started - thread creation error"
 msgstr "Time-Stretch konnte nicht gestartet werden - Fehler beim erstellen des Threads"
 
+#: gtk2_ardour/editor_timefx.cc:315
+msgid "pitch shift"
+msgstr "pitch-shift"
+
+#: gtk2_ardour/editor_timefx.cc:315
+msgid "time stretch"
+msgstr "Time-Stretch"
+
+#: gtk2_ardour/engine_dialog.cc:46
+msgid "Realtime"
+msgstr "Realtime"
+
+#: gtk2_ardour/engine_dialog.cc:47
+msgid "Do not lock memory"
+msgstr "Speicherzugriff nicht sperren"
+
+#: gtk2_ardour/engine_dialog.cc:48
+msgid "Unlock memory"
+msgstr "Speicherzugriff Ã¶ffnen"
+
+#: gtk2_ardour/engine_dialog.cc:49
+msgid "No zombies"
+msgstr "Keine Zombies (Soft Mode)"
+
+#: gtk2_ardour/engine_dialog.cc:50
+msgid "Provide monitor ports"
+msgstr "Monitor-Ports erstellen"
+
+#: gtk2_ardour/engine_dialog.cc:51
+msgid "Force 16 bit"
+msgstr "Erzwinge 16 Bit"
+
+#: gtk2_ardour/engine_dialog.cc:52
+msgid "H/W monitoring"
+msgstr "Hardware Monitoring"
+
+#: gtk2_ardour/engine_dialog.cc:53
+msgid "H/W metering"
+msgstr "Hardware-Pegelanzeige"
+
+#: gtk2_ardour/engine_dialog.cc:54
+msgid "Verbose output"
+msgstr "Ausführliche Statusmeldungen"
+
+#: gtk2_ardour/engine_dialog.cc:55
+msgid "Start"
+msgstr "Start"
+
+#: gtk2_ardour/engine_dialog.cc:74
+msgid "8000Hz"
+msgstr "8000 Hz"
+
+#: gtk2_ardour/engine_dialog.cc:75
+msgid "22050Hz"
+msgstr "22050 Hz"
+
+#: gtk2_ardour/engine_dialog.cc:76
+msgid "44100Hz"
+msgstr "44100 Hz"
+
+#: gtk2_ardour/engine_dialog.cc:77
+msgid "48000Hz"
+msgstr "48000 Hz"
+
+#: gtk2_ardour/engine_dialog.cc:78
+msgid "88200Hz"
+msgstr "88200 Hz"
+
+#: gtk2_ardour/engine_dialog.cc:79
+msgid "96000Hz"
+msgstr "96000 Hz"
+
+#: gtk2_ardour/engine_dialog.cc:80
+msgid "192000Hz"
+msgstr "192000 Hz"
+
+#: gtk2_ardour/engine_dialog.cc:99
+#: gtk2_ardour/engine_dialog.cc:480
+#: gtk2_ardour/export_dialog.cc:81
+#: gtk2_ardour/export_dialog.cc:1298
+msgid "Triangular"
+msgstr "dreieckig"
+
+#: gtk2_ardour/engine_dialog.cc:100
+#: gtk2_ardour/engine_dialog.cc:482
+#: gtk2_ardour/export_dialog.cc:79
+#: gtk2_ardour/export_dialog.cc:1296
+msgid "Rectangular"
+msgstr "rechteckig"
+
+#: gtk2_ardour/engine_dialog.cc:101
+#: gtk2_ardour/engine_dialog.cc:484
+msgid "Shaped"
+msgstr "shaped"
+
+#: gtk2_ardour/engine_dialog.cc:129
+#: gtk2_ardour/engine_dialog.cc:435
+#: gtk2_ardour/engine_dialog.cc:803
+msgid "Playback/Recording on 1 Device"
+msgstr "Wiedergabe/Aufnahme mit einem Gerät"
+
+#: gtk2_ardour/engine_dialog.cc:130
+#: gtk2_ardour/engine_dialog.cc:439
+#: gtk2_ardour/engine_dialog.cc:464
+#: gtk2_ardour/engine_dialog.cc:806
+msgid "Playback/Recording on 2 Devices"
+msgstr "Wiedergabe/Aufnahme mit zwei Geräten"
+
+#: gtk2_ardour/engine_dialog.cc:131
+#: gtk2_ardour/engine_dialog.cc:446
+#: gtk2_ardour/engine_dialog.cc:809
+msgid "Playback only"
+msgstr "Nur Wiedergabe"
+
+#: gtk2_ardour/engine_dialog.cc:132
+#: gtk2_ardour/engine_dialog.cc:448
+#: gtk2_ardour/engine_dialog.cc:811
+msgid "Recording only"
+msgstr "Nur Aufnahme"
+
+#: gtk2_ardour/engine_dialog.cc:141
+msgid "Driver"
+msgstr "Treiber"
+
+#: gtk2_ardour/engine_dialog.cc:146
+msgid "Interface"
+msgstr "Gerät / Interface"
+
+#: gtk2_ardour/engine_dialog.cc:151
+#: gtk2_ardour/export_dialog.cc:108
+msgid "Sample Rate"
+msgstr "Samplerate"
+
+#: gtk2_ardour/engine_dialog.cc:156
+msgid "Buffer size"
+msgstr "Größe Buffer"
+
+#: gtk2_ardour/engine_dialog.cc:162
+msgid "Number of buffers"
+msgstr "Anzahl Buffer"
+
+#: gtk2_ardour/engine_dialog.cc:169
+msgid "Approximate latency"
+msgstr "Latenz (ca.)"
+
+#: gtk2_ardour/engine_dialog.cc:183
+msgid "Audio Mode"
+msgstr "Audio-Modus"
+
+#: gtk2_ardour/engine_dialog.cc:222
+msgid "Realtime Priority"
+msgstr "Realtime Priorität"
+
+#: gtk2_ardour/engine_dialog.cc:251
+#: gtk2_ardour/engine_dialog.cc:374
+msgid "Ignore"
+msgstr "ignorieren"
+
+#: gtk2_ardour/engine_dialog.cc:259
+msgid "Client timeout"
+msgstr "Client Timeout"
+
+#: gtk2_ardour/engine_dialog.cc:265
+msgid "Number of ports"
+msgstr "Anzahl Ports"
+
+#: gtk2_ardour/engine_dialog.cc:272
+msgid "Dither"
+msgstr "Dithering"
+
+#: gtk2_ardour/engine_dialog.cc:282
+msgid "No JACK server found anywhere on this system. Please install JACK and restart"
+msgstr "Es wurde kein JACK Server auf diesem System gefunden. Bitte installieren Sie JACK und starten Sie ardour neu."
+
+#: gtk2_ardour/engine_dialog.cc:290
+#, fuzzy
+msgid "Server:"
+msgstr "Stereo"
+
+#: gtk2_ardour/engine_dialog.cc:303
+msgid "Input device"
+msgstr "Eingangsgerät"
+
+#: gtk2_ardour/engine_dialog.cc:308
+msgid "Output device"
+msgstr "Ausgabegerät"
+
+#: gtk2_ardour/engine_dialog.cc:314
+msgid "Input channels"
+msgstr "Eingangskanäle"
+
+#: gtk2_ardour/engine_dialog.cc:319
+msgid "Output channels"
+msgstr "Ausgangskanäle"
+
+#: gtk2_ardour/engine_dialog.cc:324
+msgid "Hardware input latency (samples)"
+msgstr "Hardware Eingangslatenz (Samples)"
+
+#: gtk2_ardour/engine_dialog.cc:329
+msgid "Hardware output latency (samples)"
+msgstr "Hardware Ausgangslatenz (Samples)"
+
+#: gtk2_ardour/engine_dialog.cc:342
+msgid "Device"
+msgstr "Gerät"
+
+#: gtk2_ardour/engine_dialog.cc:344
+msgid "Advanced"
+msgstr "Erweitert"
+
+#: gtk2_ardour/engine_dialog.cc:537
+msgid "cannot open JACK rc file %1 to store parameters"
+msgstr "kann die JACK rc-Datei %1 nicht Ã¶ffnen, um die Parameter zu sichern"
+
+#: gtk2_ardour/engine_dialog.cc:842
+msgid "JACK appears to be missing from the Ardour bundle"
+msgstr ""
+
+#: gtk2_ardour/engine_dialog.cc:1026
+msgid "AudioSetup value for %1 is missing data"
+msgstr ""
+
+#: gtk2_ardour/engine_dialog.cc:1106
+msgid "configuration files contain a JACK server path that doesn't exist (%1)"
+msgstr "die Konfiguration enthält einen JACK-Serverpfad, der nicht existiert (%1)"
+
 #: gtk2_ardour/export_dialog.cc:59
-#: gtk2_ardour/export_dialog.cc:401
-#: gtk2_ardour/export_dialog.cc:1029
-#: gtk2_ardour/export_dialog.cc:1197
+#: gtk2_ardour/export_dialog.cc:423
+#: gtk2_ardour/export_dialog.cc:1090
+#: gtk2_ardour/export_dialog.cc:1260
 msgid "22.05kHz"
-msgstr ""
+msgstr "22,05 kHz"
 
 #: gtk2_ardour/export_dialog.cc:60
-#: gtk2_ardour/export_dialog.cc:404
-#: gtk2_ardour/export_dialog.cc:419
-#: gtk2_ardour/export_dialog.cc:1031
-#: gtk2_ardour/export_dialog.cc:1199
+#: gtk2_ardour/export_dialog.cc:426
+#: gtk2_ardour/export_dialog.cc:441
+#: gtk2_ardour/export_dialog.cc:1092
+#: gtk2_ardour/export_dialog.cc:1262
 msgid "44.1kHz"
-msgstr ""
+msgstr "44,1 kHz"
 
 #: gtk2_ardour/export_dialog.cc:61
-#: gtk2_ardour/export_dialog.cc:407
-#: gtk2_ardour/export_dialog.cc:1033
-#: gtk2_ardour/export_dialog.cc:1201
+#: gtk2_ardour/export_dialog.cc:429
+#: gtk2_ardour/export_dialog.cc:1094
+#: gtk2_ardour/export_dialog.cc:1264
 msgid "48kHz"
 msgstr "4"
 
 #: gtk2_ardour/export_dialog.cc:62
-#: gtk2_ardour/export_dialog.cc:410
-#: gtk2_ardour/export_dialog.cc:1035
-#: gtk2_ardour/export_dialog.cc:1203
+#: gtk2_ardour/export_dialog.cc:432
+#: gtk2_ardour/export_dialog.cc:1096
+#: gtk2_ardour/export_dialog.cc:1266
 msgid "88.2kHz"
-msgstr ""
+msgstr "88,2 kHz"
 
 #: gtk2_ardour/export_dialog.cc:63
-#: gtk2_ardour/export_dialog.cc:413
-#: gtk2_ardour/export_dialog.cc:1037
-#: gtk2_ardour/export_dialog.cc:1205
+#: gtk2_ardour/export_dialog.cc:435
+#: gtk2_ardour/export_dialog.cc:1098
+#: gtk2_ardour/export_dialog.cc:1268
 msgid "96kHz"
-msgstr ""
+msgstr "96 kHz"
 
 #: gtk2_ardour/export_dialog.cc:64
-#: gtk2_ardour/export_dialog.cc:416
-#: gtk2_ardour/export_dialog.cc:1039
-#: gtk2_ardour/export_dialog.cc:1207
+#: gtk2_ardour/export_dialog.cc:438
+#: gtk2_ardour/export_dialog.cc:1100
+#: gtk2_ardour/export_dialog.cc:1270
 msgid "192kHz"
-msgstr ""
+msgstr "192 kHz"
 
 #: gtk2_ardour/export_dialog.cc:69
 msgid "best"
 msgstr "bestmöglich"
 
 #: gtk2_ardour/export_dialog.cc:70
-#: gtk2_ardour/export_dialog.cc:1214
+#: gtk2_ardour/export_dialog.cc:1280
 msgid "fastest"
 msgstr "schnellstmöglich"
 
 #: gtk2_ardour/export_dialog.cc:71
-#: gtk2_ardour/export_dialog.cc:1216
+#: gtk2_ardour/export_dialog.cc:1282
 msgid "linear"
 msgstr "Linear"
 
 #: gtk2_ardour/export_dialog.cc:72
-#: gtk2_ardour/export_dialog.cc:1218
+#: gtk2_ardour/export_dialog.cc:1284
 msgid "better"
 msgstr "besser"
 
 #: gtk2_ardour/export_dialog.cc:73
-#: gtk2_ardour/export_dialog.cc:1220
+#: gtk2_ardour/export_dialog.cc:1286
 msgid "intermediate"
 msgstr "mittelmäßig"
 
-#: gtk2_ardour/export_dialog.cc:79
-#: gtk2_ardour/export_dialog.cc:1229
-msgid "Rectangular"
-msgstr "rechteckig"
-
 #: gtk2_ardour/export_dialog.cc:80
 msgid "Shaped Noise"
 msgstr "Shaped Noise"
 
-#: gtk2_ardour/export_dialog.cc:81
-#: gtk2_ardour/export_dialog.cc:1231
-msgid "Triangular"
-msgstr "dreieckig"
+#: gtk2_ardour/export_dialog.cc:86
+msgid "stereo"
+msgstr "Stereo"
 
 #: gtk2_ardour/export_dialog.cc:87
-#: gtk2_ardour/export_dialog.cc:488
-#: gtk2_ardour/export_dialog.cc:1057
-#: gtk2_ardour/export_dialog.cc:1179
+#: gtk2_ardour/export_dialog.cc:510
+#: gtk2_ardour/export_dialog.cc:1118
+#: gtk2_ardour/export_dialog.cc:1240
 msgid "mono"
 msgstr "Mono"
 
@@ -4610,6 +5327,7 @@ msgid "CUE"
 msgstr "CUE"
 
 #: gtk2_ardour/export_dialog.cc:94
+#: gtk2_ardour/export_dialog.cc:926
 msgid "TOC"
 msgstr "TOC"
 
@@ -4637,10 +5355,6 @@ msgstr "Sampleformat"
 msgid "Sample Endianness"
 msgstr "Bytefolge"
 
-#: gtk2_ardour/export_dialog.cc:108
-msgid "Sample Rate"
-msgstr "Samplerate"
-
 #: gtk2_ardour/export_dialog.cc:109
 msgid "Conversion Quality"
 msgstr "Qualität"
@@ -4654,8 +5368,8 @@ msgid "Export CD Marker File Only"
 msgstr "Nur CD-Marker exportieren"
 
 #: gtk2_ardour/export_dialog.cc:112
-#: gtk2_ardour/option_editor.cc:84
-#: gtk2_ardour/option_editor.cc:85
+#: gtk2_ardour/option_editor.cc:98
+#: gtk2_ardour/option_editor.cc:99
 msgid "Browse"
 msgstr "Durchsuchen"
 
@@ -4665,40 +5379,49 @@ msgstr "Alle Spuren..."
 
 #: gtk2_ardour/export_dialog.cc:141
 #: gtk2_ardour/export_dialog.cc:157
-#: gtk2_ardour/mixer_strip.cc:124
-#: gtk2_ardour/mixer_strip.cc:739
+#: gtk2_ardour/mixer_strip.cc:127
+#: gtk2_ardour/mixer_strip.cc:733
 msgid "Output"
 msgstr "Ausgang"
 
-#: gtk2_ardour/export_dialog.cc:635
+#: gtk2_ardour/export_dialog.cc:656
 msgid "Editor: cannot open \"%1\" as export file for CD toc file"
 msgstr "Editor: Kann \"%1\" nicht nicht zum Export für CD-Inhaltsverzeichnis (TOC) Ã¶ffnen."
 
-#: gtk2_ardour/export_dialog.cc:761
+#: gtk2_ardour/export_dialog.cc:790
 msgid "Editor: cannot open \"%1\" as export file for CD cue file"
 msgstr "Editor: Kann \"%1\" nicht zum Export für CD CUE-Datei Ã¶ffnen."
 
-#: gtk2_ardour/export_dialog.cc:780
+#: gtk2_ardour/export_dialog.cc:809
 msgid "WAV"
 msgstr "WAV"
 
-#: gtk2_ardour/export_dialog.cc:914
+#: gtk2_ardour/export_dialog.cc:941
+#, fuzzy
+msgid "Not connected to audioengine"
+msgstr "Nicht mit JACK verbunden - konnte die Aufnahme nicht starten"
+
+#: gtk2_ardour/export_dialog.cc:945
+msgid "Ardour cannot export audio when disconnected"
+msgstr "Ardour kann nicht exportieren, wenn keine Verbindung zu JACK besteht."
+
+#: gtk2_ardour/export_dialog.cc:975
 msgid "Stop Export"
 msgstr "Export Abbrechen"
 
-#: gtk2_ardour/export_dialog.cc:1133
+#: gtk2_ardour/export_dialog.cc:1194
 msgid "Please enter a valid filename."
 msgstr "Bitte geben Sie einen gültigen Dateinamen ein."
 
-#: gtk2_ardour/export_dialog.cc:1143
+#: gtk2_ardour/export_dialog.cc:1204
 msgid "Please specify a complete filename for the audio file."
 msgstr "Bitte geben Sie einen kompletten Dateinamen für die Audiodatei ein."
 
-#: gtk2_ardour/export_dialog.cc:1149
+#: gtk2_ardour/export_dialog.cc:1210
 msgid "File already exists, do you want to overwrite it?"
 msgstr "Datei existiert bereits, wollen Sie sie Ã¼berschreiben?"
 
-#: gtk2_ardour/export_dialog.cc:1161
+#: gtk2_ardour/export_dialog.cc:1222
 #: gtk2_ardour/export_range_markers_dialog.cc:160
 msgid "Cannot write file in: "
 msgstr "Konnte Datei nicht in Verzeichnis  schreiben:"
@@ -4734,57 +5457,74 @@ msgstr ""
 msgid "add gain automation event"
 msgstr "Punkt in die Lautstärkekurve einfügen"
 
-#: gtk2_ardour/gain_meter.cc:112
-#: gtk2_ardour/gain_meter.cc:330
-#: gtk2_ardour/gain_meter.cc:519
-#: gtk2_ardour/gain_meter.cc:590
+#: gtk2_ardour/gain_meter.cc:114
+#: gtk2_ardour/gain_meter.cc:345
+#: gtk2_ardour/gain_meter.cc:541
+#: gtk2_ardour/gain_meter.cc:612
 msgid "-inf"
 msgstr "-inf"
 
-#: gtk2_ardour/gain_meter.cc:123
+#: gtk2_ardour/gain_meter.cc:125
 msgid "Fader automation mode"
 msgstr "Fader Automationsmodus"
 
-#: gtk2_ardour/gain_meter.cc:124
+#: gtk2_ardour/gain_meter.cc:126
 msgid "Fader automation type"
 msgstr "Fader-Automationstyp"
 
-#: gtk2_ardour/gain_meter.cc:169
-#: gtk2_ardour/gain_meter.cc:884
+#: gtk2_ardour/gain_meter.cc:170
+#: gtk2_ardour/gain_meter.cc:907
 #: gtk2_ardour/panner_ui.cc:98
 #: gtk2_ardour/panner_ui.cc:784
 msgid "Abs"
 msgstr "Abs"
 
-#: gtk2_ardour/gain_meter.cc:497
+#: gtk2_ardour/gain_meter.cc:519
 msgid "-Inf"
 msgstr "-Inf"
 
-#: gtk2_ardour/gain_meter.cc:700
-#: gtk2_ardour/gain_meter.cc:715
+#: gtk2_ardour/gain_meter.cc:723
+#: gtk2_ardour/gain_meter.cc:738
 msgid "meter point change"
 msgstr "Taktwechsel Ã¤ndern"
 
-#: gtk2_ardour/gain_meter.cc:848
-#: gtk2_ardour/mixer_strip.cc:449
+#: gtk2_ardour/gain_meter.cc:871
+#: gtk2_ardour/mixer_strip.cc:443
 #: gtk2_ardour/panner_ui.cc:748
 msgid "M"
 msgstr "M"
 
-#: gtk2_ardour/gain_meter.cc:851
+#: gtk2_ardour/gain_meter.cc:874
 #: gtk2_ardour/panner_ui.cc:751
 msgid "P"
 msgstr "P"
 
-#: gtk2_ardour/gain_meter.cc:854
+#: gtk2_ardour/gain_meter.cc:877
 #: gtk2_ardour/panner_ui.cc:754
 msgid "T"
 msgstr "T"
 
-#: gtk2_ardour/gain_meter.cc:857
-#: gtk2_ardour/panner_ui.cc:757
-msgid "W"
-msgstr "W"
+#: gtk2_ardour/gain_meter.cc:880
+#: gtk2_ardour/panner_ui.cc:757
+msgid "W"
+msgstr "W"
+
+#: gtk2_ardour/generic_pluginui.cc:77
+msgid "<span size=\"large\">Presets</span>"
+msgstr "<span size=\"large\">Voreinstellungen</span>"
+
+#: gtk2_ardour/generic_pluginui.cc:205
+msgid "Plugin Editor: could not build control element for port %1"
+msgstr "Plugin Editor: konnte kein Steuerelement für Port %1 erzeugen"
+
+#: gtk2_ardour/generic_pluginui.cc:295
+msgid "Automation control"
+msgstr "Automation"
+
+#: gtk2_ardour/generic_pluginui.cc:302
+#, fuzzy
+msgid "Mgnual"
+msgstr "Manuell"
 
 #: gtk2_ardour/gtk-custom-ruler.c:126
 msgid "Lower"
@@ -4877,6 +5617,12 @@ msgstr ""
 msgid "Rename Track"
 msgstr "Spur umbenennen"
 
+#: gtk2_ardour/io_selector.cc:59
+#: gtk2_ardour/io_selector.cc:747
+#: gtk2_ardour/connection_editor.cc:85
+msgid "OK"
+msgstr "OK"
+
 #: gtk2_ardour/io_selector.cc:61
 #: gtk2_ardour/io_selector.cc:749
 #: gtk2_ardour/connection_editor.cc:60
@@ -4935,22 +5681,29 @@ msgstr "Es sind keine weiteren JACK Ports verfügbar."
 msgid "ardour: "
 msgstr "ardour: "
 
-#: gtk2_ardour/ladspa_pluginui.cc:77
-msgid "<span size=\"large\">Presets</span>"
-msgstr "<span size=\"large\">Voreinstellungen</span>"
+#: gtk2_ardour/keyeditor.cc:25
+msgid "Keybinding Editor"
+msgstr ""
 
-#: gtk2_ardour/ladspa_pluginui.cc:205
-msgid "Plugin Editor: could not build control element for port %1"
-msgstr "Plugin Editor: konnte kein Steuerelement für Port %1 erzeugen"
+#: gtk2_ardour/keyeditor.cc:33
+msgid "Action"
+msgstr "Aktion"
 
-#: gtk2_ardour/ladspa_pluginui.cc:295
-msgid "Automation control"
-msgstr "Automation"
+#: gtk2_ardour/keyeditor.cc:34
+msgid "Binding"
+msgstr "Zugewiesene Taste"
 
-#: gtk2_ardour/ladspa_pluginui.cc:302
-#, fuzzy
-msgid "Mgnual"
-msgstr "Manuell"
+#: gtk2_ardour/keyeditor.cc:188
+msgid "Command-"
+msgstr "Befehl-"
+
+#: gtk2_ardour/keyeditor.cc:189
+msgid "Option-"
+msgstr "Option-"
+
+#: gtk2_ardour/keyeditor.cc:190
+msgid "Shift-"
+msgstr ""
 
 #: gtk2_ardour/location_ui.cc:49
 #: gtk2_ardour/location_ui.cc:52
@@ -4974,77 +5727,43 @@ msgstr "SCMS"
 msgid "Pre-Emphasis"
 msgstr "Präemphase"
 
-#: gtk2_ardour/location_ui.cc:571
+#: gtk2_ardour/location_ui.cc:430
+msgid "You cannot put a CD marker at the start of the session"
+msgstr "Sie können keinen CD-Marker am Anfang des Projekts erstellen"
+
+#: gtk2_ardour/location_ui.cc:605
 msgid "Add New Location"
 msgstr "Neue Position hinzufügen"
 
-#: gtk2_ardour/location_ui.cc:572
+#: gtk2_ardour/location_ui.cc:606
 msgid "Add New Range"
 msgstr "Neuen Bereich hinzufügen"
 
-#: gtk2_ardour/location_ui.cc:608
+#: gtk2_ardour/location_ui.cc:642
 msgid "Location (CD Index) Markers"
 msgstr "Positionsmarker (CD Index)"
 
-#: gtk2_ardour/location_ui.cc:628
+#: gtk2_ardour/location_ui.cc:662
 msgid "Range (CD Track) Markers"
 msgstr "Bereiche (CD Tracks)"
 
-#: gtk2_ardour/location_ui.cc:801
+#: gtk2_ardour/location_ui.cc:840
 msgid "add range marker"
 msgstr "Bereich hinzufügen"
 
-#: gtk2_ardour/main.cc:75
-msgid ""
-"Without a UI style file, ardour will look strange.\n"
-" Please set ARDOUR2_UI_RC to point to a valid UI style file"
-msgstr ""
-"Ohne UI-Definitionsdatei wird ardour merkwürdig aussehen.\n"
-" Bitte setzen Sie ARDOUR_UI_RC auf eine gültige UI-Definitionsdatei"
-
-#: gtk2_ardour/main.cc:96
-msgid "Ardour could not connect to JACK."
-msgstr "ardour konnte nicht zu JACK verbinden."
-
-#: gtk2_ardour/main.cc:100
-msgid ""
-"There are several possible reasons:\n"
-"\n"
-"1) JACK is not running.\n"
-"2) JACK is running as another user, perhaps root.\n"
-"3) There is already another client called \"ardour\".\n"
-"\n"
-"Please consider the possibilities, and perhaps (re)start JACK."
-msgstr ""
-"Dafür kann es verschiedene Gründe geben:\n"
-"\n"
-"1) JACK läuft nicht.\n"
-"2) JACK wurde unter einem anderen Benutzer gestartet, möglicherweise als root.\n"
-"3) Es gibt bereits einen anderen Client mit der Bezeichnung \"ardour\".\n"
-"\n"
-"Betrachten Sie bitte diese Möglichkeiten und starten Sie JACK neu, wenn dies notwendig sein sollte."
-
-#: gtk2_ardour/main.cc:144
-msgid "could not load command line session \"%1\""
-msgstr "Konnte das per Kommandozeile Ã¼bergebene Projekt nicht laden: \"%1\""
+#: gtk2_ardour/main.cc:153
+msgid "cannot open pango.rc file %1"
+msgstr "kann die Datei pango.rc nicht Ã¶ffnen %1"
 
-#: gtk2_ardour/main.cc:152
-msgid ""
-"\n"
-"\n"
-"No session named \"%1\" exists.\n"
-"To create it from the command line, start ardour as \"ardour --new %1"
+#: gtk2_ardour/main.cc:230
+msgid "Key bindings file \"%1\" not found. Default bindings used instead"
 msgstr ""
-"\n"
-"\n"
-"Es existiert kein Projekt mit dem Namen \"%1\".\n"
-"Um sie von der Kommandozeile aus zu erstellen, starten Sie ardour mit \"ardour --new %1"
 
-#: gtk2_ardour/main.cc:225
+#: gtk2_ardour/main.cc:292
 msgid "Ardour/GTK "
 msgstr "Ardour/GTK "
 
-#: gtk2_ardour/main.cc:227
+#: gtk2_ardour/main.cc:294
 msgid ""
 "\n"
 "   (built using "
@@ -5052,47 +5771,39 @@ msgstr ""
 "\n"
 "   (kompiliert mit Version "
 
-#: gtk2_ardour/main.cc:230
+#: gtk2_ardour/main.cc:297
 msgid " and GCC version "
 msgstr " und GCC Version"
 
-#: gtk2_ardour/main.cc:240
+#: gtk2_ardour/main.cc:307
 msgid "Copyright (C) 1999-2007 Paul Davis"
 msgstr "Copyright (C) 1999-2007 Paul Davis"
 
-#: gtk2_ardour/main.cc:241
+#: gtk2_ardour/main.cc:308
 msgid "Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker"
 msgstr "Einige Teile Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker"
 
-#: gtk2_ardour/main.cc:243
+#: gtk2_ardour/main.cc:310
 msgid "Ardour comes with ABSOLUTELY NO WARRANTY"
 msgstr "Ardour wird Ihnen ohne jegliche Gewährleistung und ausdrücklich ohne die Zusicherung"
 
-#: gtk2_ardour/main.cc:244
+#: gtk2_ardour/main.cc:311
 msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
 msgstr "für allgemeine oder spezielle Gebrauchstauglichkeit zur Verfügung gestellt."
 
-#: gtk2_ardour/main.cc:245
+#: gtk2_ardour/main.cc:312
 msgid "This is free software, and you are welcome to redistribute it "
 msgstr "Dies ist freie Software und Sie dürfen sie gerne weiterverbreiten,"
 
-#: gtk2_ardour/main.cc:246
+#: gtk2_ardour/main.cc:313
 msgid "under certain conditions; see the source for copying conditions."
 msgstr "solange Sie sich an die Bedingungen, die in der Datei COPYING aufgeführt sind halten."
 
-#: gtk2_ardour/main.cc:257
+#: gtk2_ardour/main.cc:324
 msgid "could not create ARDOUR GUI"
 msgstr "konnte das grafische Ardour User Interface nicht erstellen"
 
-#: gtk2_ardour/main.cc:282
-msgid "Could not connect to JACK server as  \"%1\""
-msgstr "Konnte nicht zu JACK Server als \"%1\" verbinden"
-
-#: gtk2_ardour/main.cc:289
-msgid "could not initialize Ardour."
-msgstr "Konnte ardour nicht initialisieren."
-
-#: gtk2_ardour/marker.cc:243
+#: gtk2_ardour/marker.cc:244
 msgid "MarkerText"
 msgstr ""
 
@@ -5100,295 +5811,330 @@ msgstr ""
 msgid "Remove Marker"
 msgstr "Marker entfernen"
 
-#: gtk2_ardour/marker_time_axis.cc:255
-msgid "Marker"
-msgstr "Marker"
+#: gtk2_ardour/midi_port_dialog.cc:22
+msgid "Port name"
+msgstr "Port Name"
 
-#: gtk2_ardour/mixer_strip.cc:95
-#: gtk2_ardour/mixer_strip.cc:140
-#: gtk2_ardour/mixer_strip.cc:1211
+#: gtk2_ardour/mixer_strip.cc:97
+#: gtk2_ardour/mixer_strip.cc:143
+#: gtk2_ardour/mixer_strip.cc:1217
 msgid "pre"
 msgstr "Pre"
 
-#: gtk2_ardour/mixer_strip.cc:96
-#: gtk2_ardour/mixer_strip.cc:789
+#: gtk2_ardour/mixer_strip.cc:98
+#: gtk2_ardour/mixer_strip.cc:786
 msgid "Comments"
 msgstr "Kommentare"
 
-#: gtk2_ardour/mixer_strip.cc:119
+#: gtk2_ardour/mixer_strip.cc:122
 msgid "Input"
 msgstr "Eingang"
 
-#: gtk2_ardour/mixer_strip.cc:136
-#: gtk2_ardour/mixer_strip.cc:1207
+#: gtk2_ardour/mixer_strip.cc:139
+#: gtk2_ardour/mixer_strip.cc:1213
+#: gtk2_ardour/option_editor.cc:707
 msgid "input"
 msgstr "Input"
 
-#: gtk2_ardour/mixer_strip.cc:144
-#: gtk2_ardour/mixer_strip.cc:1215
+#: gtk2_ardour/mixer_strip.cc:147
+#: gtk2_ardour/mixer_strip.cc:1221
 msgid "post"
 msgstr "Post"
 
-#: gtk2_ardour/mixer_strip.cc:151
+#: gtk2_ardour/mixer_strip.cc:154
 msgid "tupni"
 msgstr ""
 
-#: gtk2_ardour/mixer_strip.cc:199
+#: gtk2_ardour/mixer_strip.cc:202
 msgid "Varispeed"
 msgstr "Varispeed"
 
-#: gtk2_ardour/mixer_strip.cc:225
-#: gtk2_ardour/mixer_strip.cc:805
+#: gtk2_ardour/mixer_strip.cc:228
+#: gtk2_ardour/mixer_strip.cc:802
 msgid "Click to Add/Edit Comments"
 msgstr "Kommentare hinzufügen/ändern"
 
-#: gtk2_ardour/mixer_strip.cc:380
-msgid "unknown strip width \"%1\" in XML GUI information"
-msgstr "Unbekannte Mixerkanalbreite \"%1\" in der XML GUI Information"
-
-#: gtk2_ardour/mixer_strip.cc:423
+#: gtk2_ardour/mixer_strip.cc:419
 msgid "record"
 msgstr "Aufnahme"
 
-#: gtk2_ardour/mixer_strip.cc:430
+#: gtk2_ardour/mixer_strip.cc:426
 msgid "comments"
 msgstr "Kommentare"
 
-#: gtk2_ardour/mixer_strip.cc:433
+#: gtk2_ardour/mixer_strip.cc:429
 msgid "*comments*"
 msgstr "*Kommentare*"
 
-#: gtk2_ardour/mixer_strip.cc:447
+#: gtk2_ardour/mixer_strip.cc:441
 msgid "Rec"
 msgstr "Rec"
 
-#: gtk2_ardour/mixer_strip.cc:450
+#: gtk2_ardour/mixer_strip.cc:444
 msgid "S"
 msgstr "S"
 
-#: gtk2_ardour/mixer_strip.cc:454
-#: gtk2_ardour/mixer_strip.cc:799
+#: gtk2_ardour/mixer_strip.cc:448
+#: gtk2_ardour/mixer_strip.cc:796
 msgid "Cmt"
 msgstr "Kmt"
 
-#: gtk2_ardour/mixer_strip.cc:457
-#: gtk2_ardour/mixer_strip.cc:796
+#: gtk2_ardour/mixer_strip.cc:451
+#: gtk2_ardour/mixer_strip.cc:793
 msgid "*Cmt*"
 msgstr "*Kmt*"
 
-#: gtk2_ardour/mixer_strip.cc:496
-#: gtk2_ardour/mixer_strip.cc:562
-#: gtk2_ardour/redirect_box.cc:1102
+#: gtk2_ardour/mixer_strip.cc:490
+#: gtk2_ardour/mixer_strip.cc:556
+#: gtk2_ardour/redirect_box.cc:1124
 msgid "Not connected to JACK - no I/O changes are possible"
 msgstr "Nicht mit Jack verbunden - es sind keine Ã„nderungen an Ein-/Ausgängen möglich"
 
-#: gtk2_ardour/mixer_strip.cc:596
-#: gtk2_ardour/mixer_strip.cc:612
+#: gtk2_ardour/mixer_strip.cc:590
+#: gtk2_ardour/mixer_strip.cc:606
 msgid "could not register new ports required for that connection"
 msgstr "Konnte die Ports, die diese Verbindung benötigt nicht registrieren"
 
-#: gtk2_ardour/mixer_strip.cc:719
+#: gtk2_ardour/mixer_strip.cc:713
 msgid " Input"
 msgstr "Eingang"
 
-#: gtk2_ardour/mixer_strip.cc:722
+#: gtk2_ardour/mixer_strip.cc:716
 msgid "I"
 msgstr "I"
 
-#: gtk2_ardour/mixer_strip.cc:742
+#: gtk2_ardour/mixer_strip.cc:736
 msgid "O"
 msgstr "O"
 
-#: gtk2_ardour/mixer_strip.cc:786
+#: gtk2_ardour/mixer_strip.cc:783
 msgid "*Comments*"
 msgstr "*Kommentare*"
 
-#: gtk2_ardour/mixer_strip.cc:841
+#: gtk2_ardour/mixer_strip.cc:838
 msgid ": comment editor"
 msgstr "Kommentare bearbeiten"
 
-#: gtk2_ardour/mixer_strip.cc:936
+#: gtk2_ardour/mixer_strip.cc:933
 msgid "Grp"
 msgstr "Grp"
 
-#: gtk2_ardour/mixer_strip.cc:939
+#: gtk2_ardour/mixer_strip.cc:936
 msgid "~G"
 msgstr "~G"
 
-#: gtk2_ardour/mixer_strip.cc:988
+#: gtk2_ardour/mixer_strip.cc:984
 msgid "Invert Polarity"
 msgstr "Polarität umkehren"
 
-#: gtk2_ardour/mixer_ui.cc:82
+#: gtk2_ardour/mixer_strip.cc:987
+msgid "Protect against denormals"
+msgstr "Schutz vor Denormals"
+
+#: gtk2_ardour/mixer_ui.cc:89
 msgid "Strips"
 msgstr "Spur"
 
-#: gtk2_ardour/mixer_ui.cc:107
+#: gtk2_ardour/mixer_ui.cc:115
 msgid "Group"
 msgstr "Gruppe"
 
-#: gtk2_ardour/mixer_ui.cc:207
-#: gtk2_ardour/mixer_ui.cc:362
-#: gtk2_ardour/mixer_ui.cc:394
+#: gtk2_ardour/mixer_ui.cc:215
+#: gtk2_ardour/mixer_ui.cc:425
+#: gtk2_ardour/mixer_ui.cc:457
 msgid "Mixer"
 msgstr "Mixer"
 
-#: gtk2_ardour/mixer_ui.cc:601
-msgid "signal"
-msgstr "Signal"
-
-#: gtk2_ardour/mixer_ui.cc:752
+#: gtk2_ardour/mixer_ui.cc:835
 msgid "track display list item for renamed strip not found!"
 msgstr "Konnte Bezeichnung für umbenannten Mixerkanal nicht in der Spurliste finden!"
 
-#: gtk2_ardour/new_session_dialog.cc:44
+#: gtk2_ardour/new_session_dialog.cc:46
 msgid "Name :"
 msgstr "Name :"
 
-#: gtk2_ardour/new_session_dialog.cc:48
-#: gtk2_ardour/new_session_dialog.cc:49
 #: gtk2_ardour/new_session_dialog.cc:50
 #: gtk2_ardour/new_session_dialog.cc:51
+#: gtk2_ardour/new_session_dialog.cc:52
+#: gtk2_ardour/new_session_dialog.cc:53
 msgid "channels"
 msgstr "Kanäle"
 
-#: gtk2_ardour/new_session_dialog.cc:69
+#: gtk2_ardour/new_session_dialog.cc:71
 msgid "<b>Busses</b>"
 msgstr "<b>Busse</b>"
 
-#: gtk2_ardour/new_session_dialog.cc:70
+#: gtk2_ardour/new_session_dialog.cc:72
 msgid "<b>Inputs</b>"
 msgstr "<b>Eingänge</b>"
 
-#: gtk2_ardour/new_session_dialog.cc:71
+#: gtk2_ardour/new_session_dialog.cc:73
 msgid "<b>Outputs</b>"
 msgstr "<b>Ausgänge</b>"
 
-#: gtk2_ardour/new_session_dialog.cc:73
+#: gtk2_ardour/new_session_dialog.cc:75
 msgid "Create Folder In :"
 msgstr "Verzeichnis erstellen in:"
 
-#: gtk2_ardour/new_session_dialog.cc:75
+#: gtk2_ardour/new_session_dialog.cc:77
 msgid "Template :"
 msgstr "Vorlage :"
 
-#: gtk2_ardour/new_session_dialog.cc:77
+#: gtk2_ardour/new_session_dialog.cc:79
 msgid "Create Monitor Bus"
 msgstr "Monitor Bus erstellen"
 
-#: gtk2_ardour/new_session_dialog.cc:84
+#: gtk2_ardour/new_session_dialog.cc:86
 msgid "Create Master Bus"
 msgstr "Master Bus erstellen"
 
-#: gtk2_ardour/new_session_dialog.cc:86
+#: gtk2_ardour/new_session_dialog.cc:88
 msgid "Automatically Connect to Physical Inputs"
-msgstr "Eingänge automatisch mit Soundkarteneingängen verbinden"
+msgstr "Eingänge automatisch mit Audioeingängen verbinden"
 
-#: gtk2_ardour/new_session_dialog.cc:87
-#: gtk2_ardour/new_session_dialog.cc:100
+#: gtk2_ardour/new_session_dialog.cc:89
+#: gtk2_ardour/new_session_dialog.cc:102
 msgid "Use only"
 msgstr "Benutze nur"
 
-#: gtk2_ardour/new_session_dialog.cc:99
+#: gtk2_ardour/new_session_dialog.cc:101
 msgid "Automatically Connect Outputs"
 msgstr "Ausgänge automatisch verbinden"
 
-#: gtk2_ardour/new_session_dialog.cc:108
+#: gtk2_ardour/new_session_dialog.cc:110
 msgid "... to Master Bus"
 msgstr "... mit Master Bus"
 
-#: gtk2_ardour/new_session_dialog.cc:109
+#: gtk2_ardour/new_session_dialog.cc:111
 msgid "... to Physical Outputs"
-msgstr "... mit Soundkartenausgängen"
+msgstr "... mit Audioausgängen"
 
-#: gtk2_ardour/new_session_dialog.cc:115
+#: gtk2_ardour/new_session_dialog.cc:117
 msgid "Advanced Options"
 msgstr "Erweiterte Einstellungen"
 
-#: gtk2_ardour/new_session_dialog.cc:123
+#: gtk2_ardour/new_session_dialog.cc:125
 msgid "Recent:"
 msgstr "Zuletzt verwendet:"
 
-#: gtk2_ardour/new_session_dialog.cc:160
+#: gtk2_ardour/new_session_dialog.cc:162
 msgid "Browse:"
 msgstr "Durchsuchen:"
 
-#: gtk2_ardour/new_session_dialog.cc:338
-msgid "New Session"
-msgstr "Neues Projekt"
-
-#: gtk2_ardour/new_session_dialog.cc:340
-msgid "Open Session"
-msgstr "Projekt Ã¶ffnen"
-
-#: gtk2_ardour/new_session_dialog.cc:347
+#: gtk2_ardour/new_session_dialog.cc:350
 msgid "Session Control"
 msgstr "Projektübersicht"
 
-#: gtk2_ardour/new_session_dialog.cc:390
+#: gtk2_ardour/new_session_dialog.cc:393
 msgid "select template"
 msgstr "Vorlage auswählen"
 
-#: gtk2_ardour/new_session_dialog.cc:396
+#: gtk2_ardour/new_session_dialog.cc:399
 msgid "select session file"
 msgstr "Projektdatei auswählen"
 
-#: gtk2_ardour/new_session_dialog.cc:405
+#: gtk2_ardour/new_session_dialog.cc:408
 msgid "select directory"
 msgstr "Verzeichnis auswählen"
 
-#: gtk2_ardour/option_editor.cc:74
+#: gtk2_ardour/new_session_dialog.cc:468
+msgid "Audio Setup"
+msgstr "Audio-Einstellungen"
+
+#: gtk2_ardour/new_session_dialog.cc:492
+msgid "New Session"
+msgstr "Neues Projekt"
+
+#: gtk2_ardour/new_session_dialog.cc:497
+msgid "Open Session"
+msgstr "Projekt Ã¶ffnen"
+
+#: gtk2_ardour/option_editor.cc:77
+msgid "Limit undo history"
+msgstr "Begrenze Aktionsliste"
+
+#: gtk2_ardour/option_editor.cc:78
+msgid "Save undo history"
+msgstr "Aktionsliste speichern"
+
+#: gtk2_ardour/option_editor.cc:83
 msgid "SMPTE offset is negative"
 msgstr "Negatives SMPTE-Offset"
 
-#: gtk2_ardour/option_editor.cc:131
+#: gtk2_ardour/option_editor.cc:84
+msgid "Timecode source is sample-clock synced"
+msgstr ""
+
+#: gtk2_ardour/option_editor.cc:93
+msgid "Add new MIDI port"
+msgstr "Neuen MIDI-Port hinzufügen"
+
+#: gtk2_ardour/option_editor.cc:145
 msgid "Paths/Files"
 msgstr "Pfade"
 
-#: gtk2_ardour/option_editor.cc:132
+#: gtk2_ardour/option_editor.cc:146
 msgid "Kbd/Mouse"
 msgstr "Tastatur/Maus"
 
-#: gtk2_ardour/option_editor.cc:135
-msgid "Layers & Fades"
-msgstr "Layer & Fades"
+#: gtk2_ardour/option_editor.cc:149
+msgid "Misc"
+msgstr "Sonstiges"
 
-#: gtk2_ardour/option_editor.cc:139
+#: gtk2_ardour/option_editor.cc:152
 msgid "MIDI"
 msgstr "MIDI"
 
-#: gtk2_ardour/option_editor.cc:227
+#: gtk2_ardour/option_editor.cc:222
 msgid "session RAID path"
 msgstr "Projektverzeichnis (RAID)"
 
-#: gtk2_ardour/option_editor.cc:243
-#: gtk2_ardour/option_editor.cc:249
-#: gtk2_ardour/option_editor.cc:671
-#: gtk2_ardour/option_editor.cc:691
+#: gtk2_ardour/option_editor.cc:238
+#: gtk2_ardour/option_editor.cc:244
+#: gtk2_ardour/option_editor.cc:933
+#: gtk2_ardour/option_editor.cc:953
 msgid "internal"
 msgstr "intern"
 
-#: gtk2_ardour/option_editor.cc:262
+#: gtk2_ardour/option_editor.cc:257
 msgid "Short crossfade length (msecs)"
 msgstr "Länge für kurze Crossfades (ms)"
 
-#: gtk2_ardour/option_editor.cc:274
+#: gtk2_ardour/option_editor.cc:269
 msgid "Destructive crossfade length (msecs)"
 msgstr "Länge für destruktive Crossfades (ms)"
 
-#: gtk2_ardour/option_editor.cc:334
+#: gtk2_ardour/option_editor.cc:288
+msgid "History depth (commands)"
+msgstr "Anzahl der Befehle, die rückgängig gemacht werden können"
+
+#: gtk2_ardour/option_editor.cc:309
+msgid "Saved history depth (commands)"
+msgstr "Anzahl der Befehle, die im Verlauf gespeichert werden"
+
+#: gtk2_ardour/option_editor.cc:407
 msgid "SMPTE Offset"
 msgstr "SMPTE Offset"
 
-#: gtk2_ardour/option_editor.cc:382
+#: gtk2_ardour/option_editor.cc:480
+#, fuzzy
+msgid "Inbound MMC Device ID"
+msgstr "MMC Gerät ID"
+
+#: gtk2_ardour/option_editor.cc:490
+#, fuzzy
+msgid "Outbound MMC Device ID"
+msgstr "MMC Gerät ID"
+
+#: gtk2_ardour/option_editor.cc:522
 msgid "Port"
 msgstr "Port"
 
-#: gtk2_ardour/option_editor.cc:383
+#: gtk2_ardour/option_editor.cc:526
 msgid "Offline"
 msgstr "Offline"
 
-#: gtk2_ardour/option_editor.cc:384
+#: gtk2_ardour/option_editor.cc:530
 msgid ""
 "Trace\n"
 "Input"
@@ -5396,7 +6142,7 @@ msgstr ""
 "Verfolge\n"
 "Eingang"
 
-#: gtk2_ardour/option_editor.cc:385
+#: gtk2_ardour/option_editor.cc:534
 msgid ""
 "Trace\n"
 "Output"
@@ -5404,15 +6150,15 @@ msgstr ""
 "Verfolge\n"
 "Ausgang"
 
-#: gtk2_ardour/option_editor.cc:386
+#: gtk2_ardour/option_editor.cc:538
 msgid "MTC"
 msgstr "MTC"
 
-#: gtk2_ardour/option_editor.cc:387
+#: gtk2_ardour/option_editor.cc:542
 msgid "MMC"
 msgstr "MMC"
 
-#: gtk2_ardour/option_editor.cc:388
+#: gtk2_ardour/option_editor.cc:546
 msgid ""
 "MIDI Parameter\n"
 "Control"
@@ -5420,40 +6166,40 @@ msgstr ""
 "MIDI Parameter\n"
 "Steuerung"
 
-#: gtk2_ardour/option_editor.cc:394
-msgid "MMC Device ID"
-msgstr "MMC Gerät ID"
-
-#: gtk2_ardour/option_editor.cc:406
-#: gtk2_ardour/option_editor.cc:413
-#: gtk2_ardour/option_editor.cc:416
-#: gtk2_ardour/option_editor.cc:561
+#: gtk2_ardour/option_editor.cc:585
+#: gtk2_ardour/option_editor.cc:592
+#: gtk2_ardour/option_editor.cc:595
+#: gtk2_ardour/option_editor.cc:808
 msgid "online"
 msgstr "Online"
 
-#: gtk2_ardour/option_editor.cc:413
-#: gtk2_ardour/option_editor.cc:414
-#: gtk2_ardour/option_editor.cc:558
+#: gtk2_ardour/option_editor.cc:592
+#: gtk2_ardour/option_editor.cc:593
+#: gtk2_ardour/option_editor.cc:805
 msgid "offline"
 msgstr "Offline"
 
-#: gtk2_ardour/option_editor.cc:624
+#: gtk2_ardour/option_editor.cc:709
+msgid "output"
+msgstr "Ausgang"
+
+#: gtk2_ardour/option_editor.cc:880
 msgid "Choose Click"
 msgstr "Click auswählen"
 
-#: gtk2_ardour/option_editor.cc:643
+#: gtk2_ardour/option_editor.cc:902
 msgid "Choose Click Emphasis"
 msgstr "Click-Betonung auswählen"
 
-#: gtk2_ardour/option_editor.cc:743
+#: gtk2_ardour/option_editor.cc:1005
 msgid "Click audio file"
 msgstr "Audiodatei für Click"
 
-#: gtk2_ardour/option_editor.cc:749
+#: gtk2_ardour/option_editor.cc:1011
 msgid "Click emphasis audiofile"
-msgstr "Audiodatei für betonten Click "
+msgstr "Audiodatei für Click-Betonung"
 
-#: gtk2_ardour/option_editor.cc:786
+#: gtk2_ardour/option_editor.cc:1048
 msgid ""
 "The auditioner is a dedicated mixer strip used\n"
 "for listening to specific regions outside the context\n"
@@ -5466,72 +6212,80 @@ msgstr ""
 "Dieser Bus lässt sich wie jeder andere Mixer-Kanal\n"
 "verbinden."
 
-#: gtk2_ardour/option_editor.cc:859
+#: gtk2_ardour/option_editor.cc:1139
 msgid "Edit using"
 msgstr "Bearbeiten mit"
 
-#: gtk2_ardour/option_editor.cc:866
-#: gtk2_ardour/option_editor.cc:893
+#: gtk2_ardour/option_editor.cc:1146
+#: gtk2_ardour/option_editor.cc:1173
 msgid "+ button"
 msgstr "und Maustaste"
 
-#: gtk2_ardour/option_editor.cc:886
+#: gtk2_ardour/option_editor.cc:1166
 msgid "Delete using"
 msgstr "Entfernen mit"
 
-#: gtk2_ardour/option_editor.cc:913
+#: gtk2_ardour/option_editor.cc:1193
 msgid "Ignore snap using"
 msgstr "Einrasten Ã¼bergehen mit"
 
-#: gtk2_ardour/opts.cc:46
+#: gtk2_ardour/opts.cc:49
 msgid "Usage: "
 msgstr "Aufruf:"
 
-#: gtk2_ardour/opts.cc:47
+#: gtk2_ardour/opts.cc:50
 msgid "  -v, --version                    Show version information\n"
 msgstr "  -v, --version                    Versionsinformation ausgeben\n"
 
-#: gtk2_ardour/opts.cc:48
+#: gtk2_ardour/opts.cc:51
 msgid "  -h, --help                       Print this message\n"
 msgstr "  -h, --help                       Diese Hinweise\n"
 
-#: gtk2_ardour/opts.cc:49
+#: gtk2_ardour/opts.cc:52
 msgid "  -b, --bindings                   Print all possible keyboard binding names\n"
 msgstr "  -b, --bindings                   Alle möglichen Tastenzuweisungsnamen ausgeben\n"
 
-#: gtk2_ardour/opts.cc:50
+#: gtk2_ardour/opts.cc:53
+msgid "  -c, --name  name                 Use a specific jack client name, default is ardour\n"
+msgstr "  -c, --name  name                 Benutze spezielle JACK-Clientkennung, Standard: ardour\n"
+
+#: gtk2_ardour/opts.cc:54
+msgid "  -d, --disable-plugins            Disable all plugins in an existing session\n"
+msgstr ""
+
+#: gtk2_ardour/opts.cc:55
 msgid "  -n, --show-splash                Show splash screen\n"
 msgstr "  -n, --show-splash               Zeige Splashscreen\n"
 
-#: gtk2_ardour/opts.cc:51
-msgid "  -c, --name  name                 Use a specific jack client name, default is ardour\n"
-msgstr "  -c, --name  name                 Benutze spezielle JACK-Clientkennung, Standard: ardour\n"
+#: gtk2_ardour/opts.cc:56
+msgid "  -m, --menus file                 Use \"file\" for Ardour menus\n"
+msgstr "  -m, --menus file                 Benutze \"file\" für Ardour-Menüs\n"
 
-#: gtk2_ardour/opts.cc:52
+#: gtk2_ardour/opts.cc:57
 msgid "  -N, --new session-name           Create a new session from the command line\n"
 msgstr "  -N, --new session-name           Erstelle neues Projekt aus der Kommandozeile\n"
 
-#: gtk2_ardour/opts.cc:53
+#: gtk2_ardour/opts.cc:58
 msgid "  -O, --no-hw-optimizations        Disable h/w specific optimizations\n"
 msgstr "  -O, --no-hw-optimizations        Hardwarespezifische Optimierungen deaktivieren\n"
 
-#: gtk2_ardour/opts.cc:54
-msgid "  -S, --sync\t                   Draw the gui synchronously \n"
-msgstr "  -S, --sync\t                   Zeichne die GUI synchron \n"
+#: gtk2_ardour/opts.cc:59
+msgid "  -S, --sync\t                      Draw the gui synchronously \n"
+msgstr "  -S, --sync\t                      Zeichne die GUI synchron \n"
 
-#: gtk2_ardour/opts.cc:56
+#: gtk2_ardour/opts.cc:61
 msgid "  -V, --novst                      Do not use VST support\n"
 msgstr "  -V, --novst                      VST-Unterstützung ausschalten\n"
 
-#: gtk2_ardour/opts.cc:58
+#: gtk2_ardour/opts.cc:63
 msgid "  [session-name]                   Name of session to load\n"
 msgstr "  [session-name]                   Name des zu ladenden Projekts\n"
 
-#: gtk2_ardour/opts.cc:59
+#: gtk2_ardour/opts.cc:64
 msgid "  -C, --curvetest filename         Curve algorithm debugger\n"
 msgstr "  -C, --curvetest filename         Kurvenalgorithmus debuggen\n"
 
-#: gtk2_ardour/opts.cc:60
+#: gtk2_ardour/opts.cc:65
 msgid "  -k, --keybindings filename       Name of key bindings to load (default is ~/.ardour2/ardour.bindings)\n"
 msgstr "  -k, --keybindings filename       Dateiname für die Tastaturbelegungen (Standard: ~/.ardour2/ardour.bindings)\n"
 
@@ -5545,14 +6299,14 @@ msgstr "Pan-Automationspunkt einfügen"
 
 #: gtk2_ardour/panner2d.cc:588
 #: gtk2_ardour/panner_ui.cc:412
-#: gtk2_ardour/plugin_ui.cc:152
+#: gtk2_ardour/plugin_ui.cc:221
 msgid "Bypass"
 msgstr "Bypass"
 
 #: gtk2_ardour/panner_ui.cc:58
 #: gtk2_ardour/panner_ui.cc:217
 msgid "link"
-msgstr "verb"
+msgstr "link"
 
 #: gtk2_ardour/panner_ui.cc:69
 msgid "Pan automation mode"
@@ -5603,72 +6357,88 @@ msgstr "Andere Spuren"
 msgid "unassigned"
 msgstr "nicht zugewiesen"
 
-#: gtk2_ardour/plugin_selector.cc:43
+#: gtk2_ardour/plugin_selector.cc:50
+#: gtk2_ardour/plugin_selector.cc:190
+msgid "Name contains"
+msgstr "Name enthält"
+
+#: gtk2_ardour/plugin_selector.cc:51
+#: gtk2_ardour/plugin_selector.cc:192
+msgid "Type contains"
+msgstr ""
+
+#: gtk2_ardour/plugin_selector.cc:52
+#: gtk2_ardour/plugin_selector.cc:194
+msgid "Author contains"
+msgstr "Autor enthält"
+
+#: gtk2_ardour/plugin_selector.cc:53
+#: gtk2_ardour/plugin_selector.cc:196
+msgid "Library contains"
+msgstr ""
+
+#: gtk2_ardour/plugin_selector.cc:58
 msgid "ardour: plugins"
 msgstr "ardour: Plugins"
 
-#: gtk2_ardour/plugin_selector.cc:56
-msgid "Available LADSPA Plugins"
-msgstr "Verfügbare LADSPA Plugins"
+#: gtk2_ardour/plugin_selector.cc:70
+msgid "Available Plugins"
+msgstr "Verfügbare Plugins"
 
-#: gtk2_ardour/plugin_selector.cc:57
+#: gtk2_ardour/plugin_selector.cc:71
 msgid "Type"
 msgstr "Typ"
 
-#: gtk2_ardour/plugin_selector.cc:58
-#: gtk2_ardour/plugin_selector.cc:81
-#: gtk2_ardour/plugin_selector.cc:99
+#: gtk2_ardour/plugin_selector.cc:72
+msgid "Category"
+msgstr ""
+
+#: gtk2_ardour/plugin_selector.cc:73
+msgid "Creator"
+msgstr "Ersteller"
+
+#: gtk2_ardour/plugin_selector.cc:74
 msgid "# Inputs"
 msgstr "Eingänge"
 
-#: gtk2_ardour/plugin_selector.cc:59
-#: gtk2_ardour/plugin_selector.cc:82
-#: gtk2_ardour/plugin_selector.cc:100
+#: gtk2_ardour/plugin_selector.cc:75
 msgid "# Outputs"
 msgstr "Ausgänge"
 
-#: gtk2_ardour/plugin_selector.cc:68
-msgid "Plugins to be Connected to Insert"
-msgstr "Plugins, die als Insert verbunden werden"
+#: gtk2_ardour/plugin_selector.cc:85
+msgid "Plugins to be connected"
+msgstr "Plugins, die verbunden werden"
 
-#: gtk2_ardour/plugin_selector.cc:80
 #: gtk2_ardour/plugin_selector.cc:98
-msgid "Available plugins"
-msgstr "Verfügbare VST-Plugins"
-
-#: gtk2_ardour/plugin_selector.cc:117
 msgid "Add a plugin to the effect list"
 msgstr "Plugin zur Effektliste hinzufügen"
 
-#: gtk2_ardour/plugin_selector.cc:121
+#: gtk2_ardour/plugin_selector.cc:102
 msgid "Remove a plugin from the effect list"
 msgstr "Plugin aus der Effektliste entfernen"
 
-#: gtk2_ardour/plugin_selector.cc:123
+#: gtk2_ardour/plugin_selector.cc:104
 msgid "Update available plugins"
 msgstr "Verfügbare Plugins auffrischen"
 
-#: gtk2_ardour/plugin_selector.cc:146
-msgid "LADSPA"
-msgstr "LADSPA"
-
-#: gtk2_ardour/plugin_selector.cc:150
-msgid "VST"
-msgstr "VST"
+#: gtk2_ardour/plugin_selector.cc:141
+msgid "Insert Plugin(s)"
+msgstr "Plugin(s) einfügen"
 
-#: gtk2_ardour/plugin_selector.cc:155
-msgid "AudioUnit"
+#: gtk2_ardour/plugin_ui.cc:81
+msgid "Eh? LADSPA plugins don't have editors!"
 msgstr ""
 
-#: gtk2_ardour/plugin_ui.cc:84
+#: gtk2_ardour/plugin_ui.cc:85
+#: gtk2_ardour/plugin_ui.cc:141
 msgid "unknown type of editor-supplying plugin (note: no VST support in this version of ardour)"
 msgstr "Unbekannter Plugintyp (Hinweis: diese ardour-Version unterstützt keine VST-Plugins)"
 
-#: gtk2_ardour/plugin_ui.cc:172
+#: gtk2_ardour/plugin_ui.cc:241
 msgid "Plugin preset %1 not found"
 msgstr "Plugin Preset %1 nicht gefunden"
 
-#: gtk2_ardour/plugin_ui.cc:182
+#: gtk2_ardour/plugin_ui.cc:251
 msgid "Name of New Preset:"
 msgstr "Name für neue Voreinstellung:"
 
@@ -5688,12 +6458,12 @@ msgstr "Neuer Send"
 msgid "Show send controls"
 msgstr "Zeige Send-Steuerung"
 
-#: gtk2_ardour/redirect_box.cc:412
-#: gtk2_ardour/redirect_box.cc:707
+#: gtk2_ardour/redirect_box.cc:413
+#: gtk2_ardour/redirect_box.cc:708
 msgid "ardour: weird plugin dialog"
-msgstr "ardour: Plugins"
+msgstr "ardour: Merkwürdiger Plugin-Dialog"
 
-#: gtk2_ardour/redirect_box.cc:419
+#: gtk2_ardour/redirect_box.cc:420
 msgid ""
 "You attempted to add a plugin (%1).\n"
 "The plugin has %2 inputs\n"
@@ -5711,7 +6481,7 @@ msgstr ""
 "Das ist nicht möglich - es würden Teile\n"
 "des Signals fehlen."
 
-#: gtk2_ardour/redirect_box.cc:431
+#: gtk2_ardour/redirect_box.cc:432
 msgid ""
 "You attempted to add a plugin (%1).\n"
 "The plugin has %2 inputs\n"
@@ -5731,7 +6501,7 @@ msgstr ""
 "Side-Chain-Eingänge unterstützt. Dies wird in einer\n"
 "der nächsten Versionen von ardour möglich sein."
 
-#: gtk2_ardour/redirect_box.cc:444
+#: gtk2_ardour/redirect_box.cc:445
 msgid ""
 "You attempted to add a plugin (%1).\n"
 "\n"
@@ -5753,15 +6523,15 @@ msgstr ""
 "\n"
 "Ardour kann mit dieser Situation nicht umgehen.\n"
 
-#: gtk2_ardour/redirect_box.cc:541
+#: gtk2_ardour/redirect_box.cc:542
 msgid "Pre-fader inserts, sends & plugins:"
 msgstr "Pre-Fader Inserts, Sends & Plugins:"
 
-#: gtk2_ardour/redirect_box.cc:544
+#: gtk2_ardour/redirect_box.cc:545
 msgid "Post-fader inserts, sends & plugins:"
 msgstr "Post-Fader Inserts, Sends & Plugins:"
 
-#: gtk2_ardour/redirect_box.cc:710
+#: gtk2_ardour/redirect_box.cc:711
 msgid ""
 "You cannot reorder this set of redirects\n"
 "in that way because the inputs and\n"
@@ -5771,12 +6541,12 @@ msgstr ""
 "nicht auf diese Weise verändern, denn\n"
 "die Ein-/Ausgänge arbeiten ncht korrekt."
 
-#: gtk2_ardour/redirect_box.cc:823
+#: gtk2_ardour/redirect_box.cc:858
 msgid "rename redirect"
 msgstr "Redirect umbenennen"
 
-#: gtk2_ardour/redirect_box.cc:899
-#: gtk2_ardour/redirect_box.cc:948
+#: gtk2_ardour/redirect_box.cc:934
+#: gtk2_ardour/redirect_box.cc:983
 msgid ""
 "Copying the set of redirects on the clipboard failed,\n"
 "probably because the I/O configuration of the plugins\n"
@@ -5786,7 +6556,7 @@ msgstr ""
 "Zwischenablage kopieren. Wahrscheinlich passt die\n"
 "Ein-/Ausgangskonfiguration des Plugins nicht zu dieser Spur."
 
-#: gtk2_ardour/redirect_box.cc:971
+#: gtk2_ardour/redirect_box.cc:1006
 msgid ""
 "Do you really want to remove all pre-fader redirects from this track?\n"
 "(this cannot be undone)"
@@ -5794,7 +6564,7 @@ msgstr ""
 "Wollen Sie wirklich alle Pre-Fader-Redirects von dieser Spur entfernen?\n"
 "(Dies kann nicht rückgängig gemacht werden)"
 
-#: gtk2_ardour/redirect_box.cc:974
+#: gtk2_ardour/redirect_box.cc:1009
 msgid ""
 "Do you really want to remove all post-fader redirects from this track?\n"
 "(this cannot be undone)"
@@ -5802,7 +6572,7 @@ msgstr ""
 "Wollen Sie wirklich alle Post-Fader-Redirects von dieser Spur entfernen?\n"
 "(Dies kann nicht rückgängig gemacht werden)"
 
-#: gtk2_ardour/redirect_box.cc:979
+#: gtk2_ardour/redirect_box.cc:1014
 msgid ""
 "Do you really want to remove all pre-fader redirects from this bus?\n"
 "(this cannot be undone)"
@@ -5810,7 +6580,7 @@ msgstr ""
 "Wollen Sie wirklich alle Pre-Fader-Redirects von diesem Bus entfernen?\n"
 "(Dies kann nicht rückgängig gemacht werden)"
 
-#: gtk2_ardour/redirect_box.cc:982
+#: gtk2_ardour/redirect_box.cc:1017
 msgid ""
 "Do you really want to remove all post-fader redirects from this bus?\n"
 "(this cannot be undone)"
@@ -5818,38 +6588,33 @@ msgstr ""
 "Wollen Sie wirklich alle Post-Fader-Redirects von diesem Bus entfernen?\n"
 "(Dies kann nicht rückgängig gemacht werden)"
 
-#: gtk2_ardour/redirect_box.cc:988
+#: gtk2_ardour/redirect_box.cc:1023
 msgid "Yes, remove them all"
 msgstr "Ja, alle löschen"
 
-#: gtk2_ardour/redirect_box.cc:1150
+#: gtk2_ardour/redirect_box.cc:1173
 msgid "New Plugin ..."
 msgstr "Plugin einfügen..."
 
-#: gtk2_ardour/redirect_box.cc:1152
+#: gtk2_ardour/redirect_box.cc:1175
 msgid "New Insert"
 msgstr "Insert einfügen"
 
-#: gtk2_ardour/redirect_box.cc:1154
+#: gtk2_ardour/redirect_box.cc:1177
 msgid "New Send ..."
 msgstr "Send einfügen..."
 
-#: gtk2_ardour/redirect_box.cc:1168
-msgid "Deselect All"
-msgstr "Nichts auswählen"
-
-#: gtk2_ardour/redirect_box.cc:1175
+#: gtk2_ardour/redirect_box.cc:1202
 msgid "Activate all"
 msgstr "Alle aktivieren"
 
-#: gtk2_ardour/redirect_box.cc:1176
+#: gtk2_ardour/redirect_box.cc:1203
 msgid "Deactivate all"
 msgstr "Alle deaktivieren"
 
-#: gtk2_ardour/redirect_box.cc:1359
-#, fuzzy
+#: gtk2_ardour/redirect_box.cc:1396
 msgid "%1: %2 (by %3)"
-msgstr "ardour: %1: %2 (by %3)"
+msgstr "%1: %2 (by %3)"
 
 #: gtk2_ardour/audio_region_editor.cc:48
 msgid "NAME:"
@@ -5891,7 +6656,7 @@ msgstr "Endposition der Region Ã¤ndern"
 msgid "change region length"
 msgstr "Länge der Region verändern"
 
-#: gtk2_ardour/audio_region_view.cc:911
+#: gtk2_ardour/audio_region_view.cc:922
 msgid "add gain control point"
 msgstr "Lautstärkekurve bearbeiten"
 
@@ -5920,62 +6685,61 @@ msgstr "KEINE SPUR"
 msgid "No Route Selected"
 msgstr "Keine Route ausgewählt"
 
-#: gtk2_ardour/route_ui.cc:154
+#: gtk2_ardour/route_ui.cc:156
 msgid "mute change"
 msgstr "Mute Ã¤ndern"
 
-#: gtk2_ardour/route_ui.cc:232
-#: gtk2_ardour/route_ui.cc:243
+#: gtk2_ardour/route_ui.cc:234
+#: gtk2_ardour/route_ui.cc:245
 msgid "solo change"
 msgstr "Solo Ã¤ndern"
 
-#: gtk2_ardour/route_ui.cc:301
+#: gtk2_ardour/route_ui.cc:303
 msgid "Not connected to JACK - cannot engage record"
 msgstr "Nicht mit JACK verbunden - konnte die Aufnahme nicht starten"
 
-#: gtk2_ardour/route_ui.cc:314
+#: gtk2_ardour/route_ui.cc:317
 msgid "rec-enable change"
 msgstr "Aufnahmestatus Ã¤ndern"
 
-#: gtk2_ardour/route_ui.cc:548
-#, fuzzy
+#: gtk2_ardour/route_ui.cc:555
 msgid "Solo-safe"
-msgstr "solo"
+msgstr "Solo-Safe"
 
-#: gtk2_ardour/route_ui.cc:570
+#: gtk2_ardour/route_ui.cc:577
 msgid "Pre Fader"
 msgstr "Pre Fader"
 
-#: gtk2_ardour/route_ui.cc:577
+#: gtk2_ardour/route_ui.cc:584
 msgid "Post Fader"
 msgstr "Post Fader"
 
-#: gtk2_ardour/route_ui.cc:584
+#: gtk2_ardour/route_ui.cc:591
 msgid "Control Outs"
 msgstr "Vorhörausgang"
 
-#: gtk2_ardour/route_ui.cc:591
+#: gtk2_ardour/route_ui.cc:598
 msgid "Main Outs"
 msgstr "Main Ausgänge"
 
-#: gtk2_ardour/route_ui.cc:628
+#: gtk2_ardour/route_ui.cc:635
 msgid "mix group solo  change"
 msgstr "Mixergruppe Solo-Status Ã¤ndern"
 
-#: gtk2_ardour/route_ui.cc:667
+#: gtk2_ardour/route_ui.cc:674
 msgid "mix group mute change"
 msgstr "Mixergruppe Mute-Status Ã¤ndern"
 
-#: gtk2_ardour/route_ui.cc:684
+#: gtk2_ardour/route_ui.cc:691
 msgid "mix group rec-enable change"
 msgstr "Mixergruppe Aufnahmestatus Ã¤ndern"
 
-#: gtk2_ardour/route_ui.cc:702
+#: gtk2_ardour/route_ui.cc:709
 #: gtk2_ardour/visual_time_axis.cc:241
 msgid "ardour: color selection"
 msgstr "ardour: Farbe auswählen"
 
-#: gtk2_ardour/route_ui.cc:778
+#: gtk2_ardour/route_ui.cc:785
 msgid ""
 "Do you really want to remove track \"%1\" ?\n"
 "\n"
@@ -5987,7 +6751,7 @@ msgstr ""
 "Sie werden auch die Wiedergabeliste, die diese Spur benutzt verlieren.\n"
 "(Dies kann nicht rückgängig gemacht werden!)"
 
-#: gtk2_ardour/route_ui.cc:780
+#: gtk2_ardour/route_ui.cc:787
 msgid ""
 "Do you really want to remove bus \"%1\" ?\n"
 "(cannot be undone)"
@@ -5995,247 +6759,371 @@ msgstr ""
 "Wollen Sie den Bus \"%1\" wirklich löschen?\n"
 "(Dies kann nicht rückgängig gemacht werden!)"
 
-#: gtk2_ardour/route_ui.cc:805
+#: gtk2_ardour/route_ui.cc:812
 msgid "New Name: "
 msgstr "Neuer Name: "
 
-#: gtk2_ardour/sfdb_ui.cc:63
-msgid "Apply"
-msgstr "Ãœbernehmen"
+#: gtk2_ardour/sfdb_ui.cc:81
+#, fuzzy
+msgid "programming error: unknown import mode string %1"
+msgstr "Programmierfehler: unbekanntes Fernsteuerungsmodell in ARDOUR_UI::set_remote_model: %1"
+
+#: gtk2_ardour/sfdb_ui.cc:91
+#: gtk2_ardour/sfdb_ui.cc:100
+msgid "as new tracks"
+msgstr "als neue Spuren"
+
+#: gtk2_ardour/sfdb_ui.cc:93
+msgid "to selected tracks"
+msgstr "zu ausgewählten Spuren"
+
+#: gtk2_ardour/sfdb_ui.cc:95
+msgid "to region list"
+msgstr "zur Liste der Regionen"
 
-#: gtk2_ardour/sfdb_ui.cc:69
-msgid "Soundfile Info"
-msgstr "Eigenschaften der Audiodatei"
+#: gtk2_ardour/sfdb_ui.cc:97
+msgid "as new tape tracks"
+msgstr "als neue Tape-Spuren"
 
-#: gtk2_ardour/sfdb_ui.cc:72
-msgid "comma seperated tags"
-msgstr "Stichworte (durch Komma getrennt)"
+#: gtk2_ardour/sfdb_ui.cc:109
+msgid "Auto-play"
+msgstr "Auto-Play"
+
+#: gtk2_ardour/sfdb_ui.cc:118
+#: gtk2_ardour/sfdb_ui.cc:228
+msgid "<b>Soundfile Info</b>"
+msgstr "<b>Eigenschaften der Audiodatei</b>"
+
+#: gtk2_ardour/sfdb_ui.cc:129
+msgid "Length:"
+msgstr "Länge:"
 
 #: gtk2_ardour/sfdb_ui.cc:130
-msgid "Length: n/a"
-msgstr "Länge: n/a"
+msgid "Timestamp:"
+msgstr "Zeitstempel:"
 
 #: gtk2_ardour/sfdb_ui.cc:131
-msgid "Format: n/a"
-msgstr "Format: n/a"
+msgid "Format:"
+msgstr "Format:"
 
 #: gtk2_ardour/sfdb_ui.cc:132
-msgid "Channels: n/a"
-msgstr "Channels: n/a"
+msgid "Channels:"
+msgstr "Kanäle:"
 
 #: gtk2_ardour/sfdb_ui.cc:133
-msgid "Samplerate: n/a"
-msgstr "Samplerate: n/a"
-
-#: gtk2_ardour/sfdb_ui.cc:134
-msgid "Timecode: n/a"
-msgstr "Timecode: n/a"
-
-#: gtk2_ardour/sfdb_ui.cc:144
-msgid "Length: %1"
-msgstr "Länge: %1"
+#: gtk2_ardour/sfdb_ui.cc:248
+#: gtk2_ardour/sfdb_ui.cc:253
+msgid "Sample rate:"
+msgstr "Samplerate:"
 
-#: gtk2_ardour/sfdb_ui.cc:146
-msgid "Channels: %1"
-msgstr "Kanäle: %1"
+#: gtk2_ardour/sfdb_ui.cc:165
+msgid "Tags:"
+msgstr "Stichworte:"
 
-#: gtk2_ardour/sfdb_ui.cc:147
-msgid "Samplerate: %1"
-msgstr "Samplerate: %1"
+#: gtk2_ardour/sfdb_ui.cc:175
+msgid "Play (double click)"
+msgstr "Wiedergabe (Doppelklick)"
 
-#: gtk2_ardour/sfdb_ui.cc:148
-msgid "Timecode: %1"
-msgstr "Timecode: %1"
+#: gtk2_ardour/sfdb_ui.cc:229
+#: gtk2_ardour/sfdb_ui.cc:230
+#: gtk2_ardour/sfdb_ui.cc:231
+msgid "n/a"
+msgstr ""
 
-#: gtk2_ardour/sfdb_ui.cc:188
+#: gtk2_ardour/sfdb_ui.cc:306
 msgid "Could not read file: %1 (%2)."
 msgstr "Konnte Datei nicht lesen: %1 (%2)."
 
-#: gtk2_ardour/sfdb_ui.cc:206
+#: gtk2_ardour/sfdb_ui.cc:326
 msgid "Could not access soundfile: "
 msgstr "Konnte auf Audiodatei nicht zugreifen: "
 
-#: gtk2_ardour/sfdb_ui.cc:255
+#: gtk2_ardour/sfdb_ui.cc:372
 msgid "SoundFileBox: Could not tokenize string: "
 msgstr ""
 
-#: gtk2_ardour/sfdb_ui.cc:275
-msgid "Add to Region list"
-msgstr "Zur Liste der Regionen hinzufügen"
-
-#: gtk2_ardour/sfdb_ui.cc:276
-msgid "Add to selected Track(s)"
-msgstr "Zu ausgewählten Spuren hinzufügen"
-
-#: gtk2_ardour/sfdb_ui.cc:277
-msgid "Add as new Track(s)"
-msgstr "Als neue Spur(en) hinzufügen"
-
-#: gtk2_ardour/sfdb_ui.cc:278
-msgid "Add as new Tape Track(s)"
-msgstr "Als neue Tape-Spuren hinzufügen"
-
-#: gtk2_ardour/sfdb_ui.cc:287
+#: gtk2_ardour/sfdb_ui.cc:392
 msgid "Search"
 msgstr "Suchen"
 
-#: gtk2_ardour/sfdb_ui.cc:302
+#: gtk2_ardour/sfdb_ui.cc:421
 msgid "Paths"
 msgstr "Pfade"
 
-#: gtk2_ardour/sfdb_ui.cc:304
-msgid "Files"
-msgstr "Dateien"
+#: gtk2_ardour/sfdb_ui.cc:425
+msgid "Browse Files"
+msgstr "Durchsuchen"
+
+#: gtk2_ardour/sfdb_ui.cc:426
+msgid "Search Tags"
+msgstr "Stichwortsuche"
+
+#: gtk2_ardour/sfdb_ui.cc:434
+msgid "Audio files"
+msgstr "Audiodateien"
 
-#: gtk2_ardour/sfdb_ui.cc:305
-msgid "Tags"
-msgstr "Stichworte"
+#: gtk2_ardour/sfdb_ui.cc:437
+msgid "All files"
+msgstr "Alle Dateien"
 
-#: gtk2_ardour/sfdb_ui.cc:374
+#: gtk2_ardour/sfdb_ui.cc:598
 msgid "SoundFileBrowser: Could not tokenize string: "
 msgstr ""
 
-#: gtk2_ardour/sfdb_ui.cc:432
-msgid "Split Channels"
-msgstr "Kanäle aufteilen"
+#: gtk2_ardour/sfdb_ui.cc:766
+#: gtk2_ardour/sfdb_ui.cc:1049
+#: gtk2_ardour/sfdb_ui.cc:1091
+msgid "one track per file"
+msgstr "eine Spur pro Datei"
 
-#: gtk2_ardour/sfdb_ui.cc:435
-msgid "Create a region for each channel"
-msgstr "Erstellt aus jedem Kanal eine eigene Region"
+#: gtk2_ardour/sfdb_ui.cc:769
+#: gtk2_ardour/sfdb_ui.cc:1092
+msgid "one track per channel"
+msgstr "eine Spur pro Kanal"
 
-#: gtk2_ardour/sfdb_ui.cc:437
-msgid "Embed"
-msgstr "Einbetten"
+#: gtk2_ardour/sfdb_ui.cc:777
+#: gtk2_ardour/sfdb_ui.cc:1094
+#, fuzzy
+msgid "sequence files"
+msgstr "aufgeräumte Dateien"
+
+#: gtk2_ardour/sfdb_ui.cc:780
+#: gtk2_ardour/sfdb_ui.cc:794
+#: gtk2_ardour/sfdb_ui.cc:1098
+msgid "all files in one region"
+msgstr "alle Dateien in einer Region"
+
+#: gtk2_ardour/sfdb_ui.cc:786
+#: gtk2_ardour/sfdb_ui.cc:1096
+msgid "one region per file"
+msgstr "eine Region pro Datei"
+
+#: gtk2_ardour/sfdb_ui.cc:789
+#: gtk2_ardour/sfdb_ui.cc:1097
+msgid "one region per channel"
+msgstr "eine Region pro Kanal"
+
+#: gtk2_ardour/sfdb_ui.cc:847
+msgid ""
+"One or more of the selected files\n"
+"cannot be used by Ardour"
+msgstr ""
+"Eine oder mehrere der ausgewählten Dateien\n"
+"können nicht von Ardour benutzt werden"
+
+#: gtk2_ardour/sfdb_ui.cc:978
+msgid "Copy files to session"
+msgstr "Kopiere Dateien zum Projekt"
+
+#: gtk2_ardour/sfdb_ui.cc:994
+#: gtk2_ardour/sfdb_ui.cc:1129
+msgid "use file timestamp"
+msgstr "verwende Datei-Zeitstempel"
+
+#: gtk2_ardour/sfdb_ui.cc:995
+#: gtk2_ardour/sfdb_ui.cc:1131
+msgid "at edit point"
+msgstr "am Arbeitspunkt"
+
+#: gtk2_ardour/sfdb_ui.cc:996
+#: gtk2_ardour/sfdb_ui.cc:1133
+msgid "at playhead"
+msgstr "am Positionszeiger"
+
+#: gtk2_ardour/sfdb_ui.cc:997
+msgid "at session start"
+msgstr "am Projektanfang"
+
+#: gtk2_ardour/sfdb_ui.cc:1002
+msgid "Add files:"
+msgstr "Dateien hinzufügen:"
 
-#: gtk2_ardour/sfdb_ui.cc:439
-msgid "Link to an external file"
-msgstr "Bettet eine externe Datei ein, ohne sie zu ins Verzeichnis des Projekts zu importieren"
+#: gtk2_ardour/sfdb_ui.cc:1024
+msgid "Insert:"
+msgstr "Einfügen:"
 
-#: gtk2_ardour/sfdb_ui.cc:441
-msgid "Import"
-msgstr "Importieren"
+#: gtk2_ardour/sfdb_ui.cc:1037
+msgid "Mapping:"
+msgstr ""
+
+#: gtk2_ardour/sfdb_ui.cc:1055
+msgid "Conversion Quality:"
+msgstr "Konvertierungsqualität:"
+
+#: gtk2_ardour/sfdb_ui.cc:1067
+#: gtk2_ardour/sfdb_ui.cc:1145
+msgid "Best"
+msgstr "bestmöglich"
 
-#: gtk2_ardour/sfdb_ui.cc:443
-msgid "Copy a file to the session folder"
-msgstr "Kopiert eine Datei in das Verzeichnis des Projekts"
+#: gtk2_ardour/sfdb_ui.cc:1068
+#: gtk2_ardour/sfdb_ui.cc:1147
+msgid "Good"
+msgstr "gut"
 
-#: gtk2_ardour/tempo_dialog.cc:17
+#: gtk2_ardour/sfdb_ui.cc:1069
+#: gtk2_ardour/sfdb_ui.cc:1149
+msgid "Quick"
+msgstr "schnell"
+
+#: gtk2_ardour/sfdb_ui.cc:1093
+msgid "merge files"
+msgstr "Dateien zusammenfügen"
+
+#: gtk2_ardour/sfdb_ui.cc:1170
+msgid "programming error: %1 (%2)"
+msgstr "Programmierfehler: %1 (%2)"
+
+#: gtk2_ardour/tempo_dialog.cc:36
 msgid "edit tempo"
 msgstr "Tempo bearbeiten"
 
-#: gtk2_ardour/tempo_dialog.cc:20
 #: gtk2_ardour/tempo_dialog.cc:39
+#: gtk2_ardour/tempo_dialog.cc:59
 msgid "Beats per minute"
 msgstr "Schläge pro Minute"
 
-#: gtk2_ardour/tempo_dialog.cc:23
-#: gtk2_ardour/tempo_dialog.cc:42
-#: gtk2_ardour/tempo_dialog.cc:159
-#: gtk2_ardour/tempo_dialog.cc:177
+#: gtk2_ardour/tempo_dialog.cc:40
+msgid "BPM denominator"
+msgstr "BPM Zählzeit"
+
+#: gtk2_ardour/tempo_dialog.cc:43
+#: gtk2_ardour/tempo_dialog.cc:62
+#: gtk2_ardour/tempo_dialog.cc:257
+#: gtk2_ardour/tempo_dialog.cc:275
 msgid "Bar"
 msgstr "Takt"
 
-#: gtk2_ardour/tempo_dialog.cc:24
-#: gtk2_ardour/tempo_dialog.cc:43
-#: gtk2_ardour/tempo_dialog.cc:160
-#: gtk2_ardour/tempo_dialog.cc:178
+#: gtk2_ardour/tempo_dialog.cc:44
+#: gtk2_ardour/tempo_dialog.cc:63
+#: gtk2_ardour/tempo_dialog.cc:258
+#: gtk2_ardour/tempo_dialog.cc:276
 msgid "Beat"
 msgstr "Schlag"
 
-#: gtk2_ardour/tempo_dialog.cc:26
-#: gtk2_ardour/tempo_dialog.cc:45
-#: gtk2_ardour/tempo_dialog.cc:161
-#: gtk2_ardour/tempo_dialog.cc:179
+#: gtk2_ardour/tempo_dialog.cc:46
+#: gtk2_ardour/tempo_dialog.cc:65
+#: gtk2_ardour/tempo_dialog.cc:259
+#: gtk2_ardour/tempo_dialog.cc:277
 msgid "Location"
 msgstr "Position"
 
-#: gtk2_ardour/tempo_dialog.cc:155
-#: gtk2_ardour/tempo_dialog.cc:173
-msgid "Meter denominator"
-msgstr "Takteinteilung"
-
-#: gtk2_ardour/tempo_dialog.cc:156
-#: gtk2_ardour/tempo_dialog.cc:174
-msgid "Beats per bar"
-msgstr "Schläge pro Takt"
-
-#: gtk2_ardour/tempo_dialog.cc:192
-#: gtk2_ardour/tempo_dialog.cc:203
+#: gtk2_ardour/tempo_dialog.cc:78
+#: gtk2_ardour/tempo_dialog.cc:95
+#: gtk2_ardour/tempo_dialog.cc:290
+#: gtk2_ardour/tempo_dialog.cc:308
 msgid "whole (1)"
 msgstr "Ganze (1)"
 
-#: gtk2_ardour/tempo_dialog.cc:193
-#: gtk2_ardour/tempo_dialog.cc:205
+#: gtk2_ardour/tempo_dialog.cc:79
+#: gtk2_ardour/tempo_dialog.cc:97
+#: gtk2_ardour/tempo_dialog.cc:291
+#: gtk2_ardour/tempo_dialog.cc:310
 msgid "second (2)"
 msgstr "Halbe (2)"
 
-#: gtk2_ardour/tempo_dialog.cc:194
-#: gtk2_ardour/tempo_dialog.cc:207
+#: gtk2_ardour/tempo_dialog.cc:80
+#: gtk2_ardour/tempo_dialog.cc:99
+#: gtk2_ardour/tempo_dialog.cc:292
+#: gtk2_ardour/tempo_dialog.cc:312
 msgid "third (3)"
 msgstr "Triolen (3)"
 
-#: gtk2_ardour/tempo_dialog.cc:195
-#: gtk2_ardour/tempo_dialog.cc:209
-#: gtk2_ardour/tempo_dialog.cc:217
+#: gtk2_ardour/tempo_dialog.cc:81
+#: gtk2_ardour/tempo_dialog.cc:101
+#: gtk2_ardour/tempo_dialog.cc:109
+#: gtk2_ardour/tempo_dialog.cc:293
+#: gtk2_ardour/tempo_dialog.cc:314
+#: gtk2_ardour/tempo_dialog.cc:322
 msgid "quarter (4)"
 msgstr "Viertel (4)"
 
-#: gtk2_ardour/tempo_dialog.cc:196
-#: gtk2_ardour/tempo_dialog.cc:211
+#: gtk2_ardour/tempo_dialog.cc:82
+#: gtk2_ardour/tempo_dialog.cc:103
+#: gtk2_ardour/tempo_dialog.cc:294
+#: gtk2_ardour/tempo_dialog.cc:316
 msgid "eighth (8)"
 msgstr "Achtel (8)"
 
-#: gtk2_ardour/tempo_dialog.cc:197
-#: gtk2_ardour/tempo_dialog.cc:213
+#: gtk2_ardour/tempo_dialog.cc:83
+#: gtk2_ardour/tempo_dialog.cc:105
+#: gtk2_ardour/tempo_dialog.cc:295
+#: gtk2_ardour/tempo_dialog.cc:318
 msgid "sixteenth (16)"
 msgstr "Sechzehntel (16)"
 
-#: gtk2_ardour/tempo_dialog.cc:198
-#: gtk2_ardour/tempo_dialog.cc:215
+#: gtk2_ardour/tempo_dialog.cc:84
+#: gtk2_ardour/tempo_dialog.cc:107
+#: gtk2_ardour/tempo_dialog.cc:296
+#: gtk2_ardour/tempo_dialog.cc:320
 msgid "thirty-second (32)"
 msgstr "Zweiunddreissigstel (32)"
 
-#: gtk2_ardour/tempo_dialog.cc:376
+#: gtk2_ardour/tempo_dialog.cc:225
+#: gtk2_ardour/tempo_dialog.cc:479
 msgid "garbaged note type entry (%1)"
 msgstr "Fehlerhafter Notentyp (%1)"
 
-#: gtk2_ardour/tempo_dialog.cc:386
+#: gtk2_ardour/tempo_dialog.cc:235
+#: gtk2_ardour/tempo_dialog.cc:489
 msgid "incomprehensible note type entry (%1)"
 msgstr "Unverständlicher Notentyp (%1)"
 
+#: gtk2_ardour/tempo_dialog.cc:253
+#: gtk2_ardour/tempo_dialog.cc:271
+msgid "Meter denominator"
+msgstr "Takteinteilung"
+
+#: gtk2_ardour/tempo_dialog.cc:254
+#: gtk2_ardour/tempo_dialog.cc:272
+msgid "Beats per bar"
+msgstr "Schläge pro Takt"
+
+#: gtk2_ardour/tempo_dialog.cc:303
+#, fuzzy
+msgid "thirtq-second (32)"
+msgstr "Zweiunddreissigstel (32)"
+
+#: gtk2_ardour/theme_manager.cc:51
+msgid "Object"
+msgstr ""
+
+#: gtk2_ardour/theme_manager.cc:182
+msgid "Unable to find UI style file %1. Ardour will look strange"
+msgstr "Kann die UI-Style Datei %1 nicht finden. Ardour wird merkwürdig aussehen."
+
 #: gtk2_ardour/time_axis_view.cc:111
 msgid "gTortnam"
 msgstr ""
 
-#: gtk2_ardour/time_axis_view.cc:586
+#: gtk2_ardour/time_axis_view.cc:589
 msgid "Largest"
 msgstr "Am größten"
 
-#: gtk2_ardour/time_axis_view.cc:587
+#: gtk2_ardour/time_axis_view.cc:590
 msgid "Large"
 msgstr "Groß"
 
-#: gtk2_ardour/time_axis_view.cc:588
+#: gtk2_ardour/time_axis_view.cc:591
 msgid "Larger"
 msgstr "Größer"
 
-#: gtk2_ardour/time_axis_view.cc:590
+#: gtk2_ardour/time_axis_view.cc:593
 msgid "Smaller"
 msgstr "Kleiner"
 
-#: gtk2_ardour/time_axis_view.cc:591
+#: gtk2_ardour/time_axis_view.cc:594
 msgid "Small"
 msgstr "Klein"
 
-#: gtk2_ardour/time_axis_view.cc:906
+#: gtk2_ardour/time_axis_view.cc:909
 msgid "unknown track height name \"%1\" in XML GUI information"
 msgstr "Unbekannte Spurhöhe \"%1\" in der XML GUI Information"
 
-#: gtk2_ardour/time_axis_view_item.cc:78
+#: gtk2_ardour/time_axis_view_item.cc:80
 msgid "TimeAxisViewItemName"
 msgstr ""
 
-#: gtk2_ardour/time_axis_view_item.cc:330
+#: gtk2_ardour/time_axis_view_item.cc:332
 msgid "new duration %1 frames is out of bounds for %2"
 msgstr "Neue Dauer %1 Frames ist außerhalb des erlaubten Bereichs %2"
 
@@ -6243,16 +7131,52 @@ msgstr "Neue Dauer %1 Frames ist außerhalb des erlaubten Bereichs %2"
 msgid "programming error: request for non-existent audio range (%1)!"
 msgstr "Programmierfehler: request for non-existent audio range (%1)!"
 
-#: gtk2_ardour/utils.cc:131
-#: gtk2_ardour/utils.cc:174
+#: gtk2_ardour/ui_config.cc:68
+msgid "loading default ui configuration file %1"
+msgstr "lade voreingestellte UI-Konfigurationsdatei %1"
+
+#: gtk2_ardour/ui_config.cc:71
+msgid "Ardour: cannot read default ui configuration file \"%1\""
+msgstr "Ardour: kann die voreingestellte UI-Konfigurationsdatei \"%1\" nicht lesen"
+
+#: gtk2_ardour/ui_config.cc:76
+msgid "Ardour: default ui configuration file \"%1\" not loaded successfully."
+msgstr "Ardour: Die voreingestellte UI-Konfigurationsdatei \"%1\" konnte nicht geladen werden."
+
+#: gtk2_ardour/ui_config.cc:88
+msgid "loading user ui configuration file %1"
+msgstr "lade benutzerdefinierte UI-Konfigurationsdatei %1"
+
+#: gtk2_ardour/ui_config.cc:91
+msgid "Ardour: cannot read ui configuration file \"%1\""
+msgstr "Ardour: kann die UI-Konfigurationsdatei \"%1\" nicht lesen"
+
+#: gtk2_ardour/ui_config.cc:96
+msgid "Ardour: user ui configuration file \"%1\" not loaded successfully."
+msgstr "Ardour: Die benutzerdefinierte UI-Konfigurationsdatei \"%1\" konnte nicht geladen werden."
+
+#: gtk2_ardour/ui_config.cc:120
+msgid "UI config file %1 not saved"
+msgstr "UI-Konfigurationsdatei %1 nicht gespeichert."
+
+#: gtk2_ardour/utils.cc:132
+#: gtk2_ardour/utils.cc:175
 msgid "bad XPM header %1"
 msgstr "Fehlerhafter XPM Header %1"
 
-#: gtk2_ardour/utils.cc:313
+#: gtk2_ardour/utils.cc:314
 msgid "missing RGBA style for \"%1\""
 msgstr "Fehlender RGBA Style für \"%1\""
 
-#: gtk2_ardour/utils.cc:495
+#: gtk2_ardour/utils.cc:337
+msgid "no style found for %1, using red"
+msgstr ""
+
+#: gtk2_ardour/utils.cc:376
+msgid "unknown style attribute %1 requested for color; using \"red\""
+msgstr ""
+
+#: gtk2_ardour/utils.cc:581
 msgid "cannot find icon image for %1"
 msgstr "Konnte Icon-Bild für %1 nicht finden"
 
@@ -6308,12 +7232,12 @@ msgstr ""
 #: gtk2_ardour/connection_editor.cc:531
 #, c-format
 msgid "in %d"
-msgstr ""
+msgstr "In %d"
 
 #: gtk2_ardour/connection_editor.cc:533
 #, c-format
 msgid "out %d"
-msgstr ""
+msgstr "Out %d"
 
 #: gtk2_ardour/connection_editor.cc:657
 msgid "Name for new connection:"
index e5ccc827f3ff04617677efbab272c5c1933fe49c..7ccef4ea536b48f262e926a71695653925875a47 100644 (file)
@@ -104,7 +104,6 @@ ProcessorBox::ProcessorBox (Placement pcmnt, Session& sess, boost::shared_ptr<Ro
        processor_drag_in_progress = false;
        no_processor_redisplay = false;
        ignore_delete = false;
-       ab_direction = true;
 
        model = ListStore::create(columns);
 
index 3410dc025af3077b91b6999478cb8e097546e8b2..749c78dc50b7be9e9f39348b48911de00febe072 100644 (file)
@@ -212,15 +212,15 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
        virtual void add_toplevel_controls (Gtk::Container&) = 0;
        virtual void set_zoom_focus (Editing::ZoomFocus) = 0;
        virtual Editing::ZoomFocus get_zoom_focus () const = 0;
-       virtual gdouble get_current_zoom () = 0;
-       virtual PlaylistSelector& playlist_selector () const = 0;
+       virtual gdouble   get_current_zoom () const = 0;
+       virtual PlaylistSelector& playlist_selector() const = 0;
        virtual void route_name_changed (TimeAxisView *) = 0;
        virtual void clear_playlist (boost::shared_ptr<ARDOUR::Playlist>) = 0;
        virtual void new_playlists (TimeAxisView*) = 0;
        virtual void copy_playlists (TimeAxisView*) = 0;
        virtual void clear_playlists (TimeAxisView*) = 0;
        virtual void select_all_tracks () = 0;
-       virtual bool set_selected_track (TimeAxisView&, Selection::Operation op = Selection::Set, bool no_remove = false) = 0;
+       virtual void set_selected_track (TimeAxisView&, Selection::Operation op = Selection::Set, bool no_remove = false) = 0;
        virtual void set_selected_mixer_strip (TimeAxisView&) = 0;
        virtual void hide_track_in_display (TimeAxisView& tv) = 0;
        virtual void show_track_in_display (TimeAxisView& tv) = 0;
@@ -252,7 +252,8 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
        virtual void remove_last_capture () = 0;
        virtual void maximise_editing_space () = 0;
        virtual void restore_editing_space () = 0;
-       virtual nframes64_t get_preferred_edit_position () = 0;
+       virtual nframes64_t get_preferred_edit_position (bool ignore_playhead = false) = 0;
+       virtual void toggle_meter_updating() = 0;
 
 #ifdef WITH_CMT
        virtual void add_imageframe_time_axis(const std::string & track_name, void*)  = 0;
index fb715559a1a7dcf4b2c4f7e50485ede26e2af6e4..fa9ec5969bf42bd976c1c8224b6519a1edb70888 100644 (file)
@@ -123,6 +123,8 @@ RegionView::init (Gdk::Color& basic_color, bool wfd)
        wait_for_data   = wfd;
        sync_mark     = 0;
        sync_line     = 0;
+       sync_mark     = 0;
+       sync_line     = 0;
 
        compute_colors (basic_color);
 
@@ -132,8 +134,6 @@ RegionView::init (Gdk::Color& basic_color, bool wfd)
                name_text->set_data ("regionview", this);
        }
 
-       //reset_width_dependent_items ((double) _region->length() / samples_per_unit);
-
        if (wfd)
                _enable_display = true;
 
@@ -385,8 +385,8 @@ RegionView::fake_set_opaque (bool yn)
        } else {
                fill_opacity = 60;
        }
-
-       TimeAxisViewItem::set_frame_color ();
+       
+       set_frame_color ();
 }
 
 void
@@ -500,7 +500,7 @@ RegionView::region_sync_changed ()
 
                        points.clear ();
                        points.push_back (Gnome::Art::Point (offset, 0));
-                       points.push_back (Gnome::Art::Point (offset, _height - NAME_HIGHLIGHT_SIZE));
+                       points.push_back (Gnome::Art::Point (offset, trackview.height - NAME_HIGHLIGHT_SIZE));
 
                        sync_line->property_points().set_value (points);
                        sync_line->show ();
index cae24510c3ec2db0185dcbf4afae04f5055de8e1..497e99ba61058ea75030a8c05175f76f4dcf44d4 100644 (file)
@@ -352,9 +352,9 @@ void
 RouteParams_UI::cleanup_pre_view (bool stopupdate)
 {
        if (_active_pre_view) {
-               LadspaPluginUI *   plugui = 0;
+               GenericPluginUI *   plugui = 0;
                
-               if (stopupdate && (plugui = dynamic_cast<LadspaPluginUI*>(_active_pre_view)) != 0) {
+               if (stopupdate && (plugui = dynamic_cast<GenericPluginUI*>(_active_pre_view)) != 0) {
                          plugui->stop_updating (0);
                }
 
@@ -369,9 +369,9 @@ void
 RouteParams_UI::cleanup_post_view (bool stopupdate)
 {
        if (_active_post_view) {
-               LadspaPluginUI *   plugui = 0;
+               GenericPluginUI *   plugui = 0;
                
-               if (stopupdate && (plugui = dynamic_cast<LadspaPluginUI*>(_active_post_view)) != 0) {
+               if (stopupdate && (plugui = dynamic_cast<GenericPluginUI*>(_active_post_view)) != 0) {
                          plugui->stop_updating (0);
                }
                _post_plugin_conn.disconnect();
@@ -581,7 +581,7 @@ RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Processor> insert,
                }
        } else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (insert)) != 0) {                         
 
-               LadspaPluginUI *plugin_ui = new LadspaPluginUI (plugin_insert, session->frame_rate(), session->engine().frames_per_cycle(), true);
+               GenericPluginUI *plugin_ui = new GenericPluginUI (plugin_insert, true);
 
                if (place == PreFader) {
                        cleanup_pre_view();
index f654a3056c6f906b815e9a91a193fef955fdbc3c..42b2e646ad478aff2be92c0ddf0cdc2c8e157410 100644 (file)
@@ -52,6 +52,7 @@
 #include <ardour/session_playlist.h>
 #include <ardour/utils.h>
 #include <ardour/parameter.h>
+#include <ardour/profile.h>
 
 #include "ardour_ui.h"
 #include "route_time_axis.h"
@@ -105,6 +106,8 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
        _view = 0;
        timestretch_rect = 0;
        no_redraw = false;
+       destructive_track_mode_item = 0;
+       normal_track_mode_item = 0;
 
        ignore_toggle = false;
 
@@ -149,6 +152,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
                rec_enable_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::rec_enable_release));
                controls_table.attach (*rec_enable_button, 4, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
                ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record"));
+
        }
 
        controls_hbox.pack_start(lm, false, false);
@@ -172,17 +176,22 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
        
        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 (!Profile->get_sae()) {
+
+               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);
+
+       } else {
+
+               controls_table.attach (automation_button, 4, 5, 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 */
-       
        y_position = -1;
 
        _route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
@@ -325,7 +334,7 @@ RouteTimeAxisView::get_automation_child_xml_node (Parameter param)
 gint
 RouteTimeAxisView::edit_click (GdkEventButton *ev)
 {
-       if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+       if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
                _route->set_edit_group (0, this);
                return FALSE;
        } 
@@ -502,13 +511,15 @@ RouteTimeAxisView::build_display_menu ()
        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));
+
+       if (!Profile->get_sae()) {
+               items.push_back (MenuElem (_("Remote Control ID"), *remote_control_menu));
+               items.push_back (MenuElem (_("Automation"), *automation_action_menu));
+               items.push_back (SeparatorElem());
+       }
 
        // Hook for derived classes to add type specific stuff
-       items.push_back (SeparatorElem());
        append_extra_display_menu_items ();
        items.push_back (SeparatorElem());
        
@@ -545,7 +556,26 @@ RouteTimeAxisView::build_display_menu ()
                if (get_diskstream()->alignment_style() == CaptureTime)
                        align_capture_item->set_active();
 
-               items.push_back (MenuElem (_("Alignment"), *alignment_menu));
+               if (!Profile->get_sae()) {
+                       items.push_back (MenuElem (_("Alignment"), *alignment_menu));
+                       get_diskstream()->AlignmentStyleChanged.connect (mem_fun(*this, &RouteTimeAxisView::align_style_changed));
+                       
+                       RadioMenuItem::Group mode_group;
+                       items.push_back (RadioMenuElem (mode_group, _("Normal mode"),
+                                                       bind (mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Normal)));
+                       normal_track_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
+                       items.push_back (RadioMenuElem (mode_group, _("Tape mode"),
+                                                       bind (mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Destructive)));
+                       destructive_track_mode_item = dynamic_cast<RadioMenuItem*>(&items.back());
+                       
+                       switch (track()->mode()) {
+                       case ARDOUR::Destructive:
+                               destructive_track_mode_item->set_active ();
+                               break;
+                       case ARDOUR::Normal:
+                               normal_track_mode_item->set_active ();
+                               break;
+                       }
 
                get_diskstream()->AlignmentStyleChanged.connect (
                                mem_fun(*this, &RouteTimeAxisView::align_style_changed));
@@ -553,9 +583,11 @@ RouteTimeAxisView::build_display_menu ()
                mode_menu = build_mode_menu();
                if (mode_menu)
                        items.push_back (MenuElem (_("Mode"), *mode_menu));
+                       
+               items.push_back (SeparatorElem());
+               }
        }
 
-       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());
@@ -590,8 +622,8 @@ RouteTimeAxisView::set_track_mode (TrackMode mode)
                /*NOTREACHED*/
                return;
        }
-
-       if (item->get_active () && track()->mode() != mode) {
+       
+       if (item && other_item && item->get_active () && track()->mode() != mode) {
                _set_track_mode (track().get(), mode, other_item);
        }
 }
@@ -740,7 +772,7 @@ RouteTimeAxisView::set_height (TrackHeight h)
 {
        int gmlen = (height_to_pixels (h)) - 5;
        bool height_changed = (height == 0) || (h != height_style);
-
+       lm.setup_meters (gmlen);
        TimeAxisView::set_height (h);
 
        ensure_xml_node ();
@@ -822,7 +854,6 @@ RouteTimeAxisView::set_height (TrackHeight h)
                break;
 
        case Small:
-               hide_meter();
                hide_name_entry ();
                show_name_label ();
 
@@ -1084,7 +1115,7 @@ RouteTimeAxisView::update_diskstream_display ()
 void
 RouteTimeAxisView::selection_click (GdkEventButton* ev)
 {
-       if (Keyboard::modifier_state_equals (ev->state, (Keyboard::Shift|Keyboard::Control))) {
+       if (Keyboard::modifier_state_equals (ev->state, (Keyboard::TertiaryModifier|Keyboard::PrimaryModifier))) {
 
                /* special case: select/deselect all tracks */
                if (editor.get_selection().selected (this)) {
@@ -1292,6 +1323,19 @@ RouteTimeAxisView::find_next_region (nframes_t pos, RegionPoint point, int32_t d
        return boost::shared_ptr<Region> ();
 }
 
+nframes64_t 
+RouteTimeAxisView::find_next_region_boundary (nframes64_t pos, int32_t dir)
+{
+       boost::shared_ptr<Diskstream> stream;
+       boost::shared_ptr<Playlist> playlist;
+
+       if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) {
+               return playlist->find_next_region_boundary (pos, dir);
+       }
+
+       return -1;
+}
+
 bool
 RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
 {
@@ -1497,6 +1541,7 @@ RouteTimeAxisView::color_handler ()
                timestretch_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TimeStretchFill.get();
        }
 
+       reset_meter();
 }
 
 void
index de89d54d94d7b4e6f81a5e5ecd91daeab1837e34..294a0e73ff7224be6c86e445103bc572cd6b0949 100644 (file)
@@ -40,6 +40,7 @@
 #include "canvas.h"
 #include "level_meter.h"
 
+
 namespace ARDOUR {
        class Session;
        class Region;
@@ -83,6 +84,7 @@ public:
        void set_layer_display (LayerDisplay d);
                
        boost::shared_ptr<ARDOUR::Region> find_next_region (nframes_t pos, ARDOUR::RegionPoint, int32_t dir);
+       nframes64_t find_next_region_boundary (nframes64_t pos, int32_t dir);
 
        /* Editing operations */
        bool cut_copy_clear (Selection&, Editing::CutCopyOp);
index f9325f5d68799ed34759cd7f5c5513627b6459e2..659d3a04febb70ede0a2c4c64f854d223e1b321e 100644 (file)
@@ -148,10 +148,10 @@ RouteUI::mute_press(GdkEventButton* ev)
                } else {
 
                        if (ev->button == 2) {
-                               // ctrl-button2 click is the midi binding click
+                               // Primary-button2 click is the midi binding click
                                // button2-click is "momentary"
                                
-                               if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
+                               if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
                                        wait_for_release = true;
                                } else {
                                        return false;
@@ -160,9 +160,9 @@ RouteUI::mute_press(GdkEventButton* ev)
 
                        if (ev->button == 1 || ev->button == 2) {
 
-                               if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
+                               if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
 
-                                       /* ctrl-shift-click applies change to all routes */
+                                       /* Primary-Tertiary-click applies change to all routes */
 
                                        _session.begin_reversible_command (_("mute change"));
                                         Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
@@ -171,10 +171,10 @@ RouteUI::mute_press(GdkEventButton* ev)
                                        _session.add_command(cmd);
                                        _session.commit_reversible_command ();
 
-                               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+                               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
 
-                                       /* ctrl-click applies change to the mix group.
-                                          ctrl-button2 is MIDI learn.
+                                       /* Primary-button1 applies change to the mix group.
+                                          NOTE: Primary-button2 is MIDI learn.
                                        */
 
                                        if (ev->button == 1) {
@@ -226,10 +226,10 @@ RouteUI::solo_press(GdkEventButton* ev)
 
                        if (ev->button == 2) {
 
-                               // ctrl-button2 click is the midi binding click
+                               // Primary-button2 click is the midi binding click
                                // button2-click is "momentary"
                                
-                               if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
+                               if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
                                        wait_for_release = true;
                                } else {
                                        return false;
@@ -238,9 +238,9 @@ RouteUI::solo_press(GdkEventButton* ev)
 
                        if (ev->button == 1 || ev->button == 2) {
 
-                               if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
+                               if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
 
-                                       /* ctrl-shift-click applies change to all routes */
+                                       /* Primary-Tertiary-click applies change to all routes */
 
                                        _session.begin_reversible_command (_("solo change"));
                                         Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
@@ -249,9 +249,9 @@ RouteUI::solo_press(GdkEventButton* ev)
                                        _session.add_command (cmd);
                                        _session.commit_reversible_command ();
                                        
-                               } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
+                               } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
 
-                                       // ctrl-alt-click: exclusively solo this track, not a toggle */
+                                       // Primary-Secondary-click: exclusively solo this track, not a toggle */
 
                                        _session.begin_reversible_command (_("solo change"));
                                         Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand (_session, this);
@@ -261,17 +261,17 @@ RouteUI::solo_press(GdkEventButton* ev)
                                        _session.add_command(cmd);
                                        _session.commit_reversible_command ();
 
-                               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+                               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
 
                                        // shift-click: set this route to solo safe
 
                                        _route->set_solo_safe (!_route->solo_safe(), this);
                                        wait_for_release = false;
 
-                               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+                               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
 
-                                       /* ctrl-click: solo mix group.
-                                          ctrl-button2 is MIDI learn.
+                                       /* Primary-button1: solo mix group.
+                                          NOTE: Primary-button2 is MIDI learn.
                                        */
 
                                        if (ev->button == 1) {
@@ -281,7 +281,7 @@ RouteUI::solo_press(GdkEventButton* ev)
                                } else {
 
                                        /* click: solo this route */
-
+                                       
                                        reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
                                }
                        }
@@ -318,11 +318,12 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
 
        if (!ignore_toggle && is_track() && rec_enable_button) {
 
-               if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+               if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
 
                        // do nothing on midi bind event
+                       return false;
 
-               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
+               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
 
                        _session.begin_reversible_command (_("rec-enable change"));
                         Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
@@ -337,7 +338,11 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
                        _session.add_command(cmd);
                        _session.commit_reversible_command ();
 
-               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+               } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
+
+                       /* Primary-button1 applies change to the mix group.
+                          NOTE: Primary-button2 is MIDI learn.
+                       */
 
                        set_mix_group_rec_enable (_route, !_route->record_enabled());
 
index 51fc5da027bafb62d5013dc336d0215e22b5558b..ca316c6450e8a62127de41109351781e96db4909 100644 (file)
@@ -34,7 +34,6 @@ class Selectable : public virtual sigc::trackable
        virtual void set_selected (bool yn) {
                if (yn != _selected) {
                        _selected = yn;
-                       Selected (_selected); /* EMIT_SIGNAL */
                }
        }
 
@@ -42,9 +41,6 @@ class Selectable : public virtual sigc::trackable
                return _selected;
        }
 
-       /** Emitted when the selected status of this Selectable changes */
-       sigc::signal<void, bool> Selected ;
-
   protected:
        bool _selected;
 };
index f1511c6ffa452249691b8dc6a92fc1593857b967..fac18393af076d435a10ff34f444369610470d20 100644 (file)
@@ -295,13 +295,23 @@ Selection::add (TimeAxisView* track)
        }
 }
 
+void
+Selection::add (const RegionSelection& rs)
+{
+       if (!rs.empty()) {
+               regions.insert (regions.end(), rs.begin(), rs.end());
+               RegionsChanged(); /* EMIT SIGNAL */
+       }
+}
+
 void
 Selection::add (RegionView* r)
 {
        if (find (regions.begin(), regions.end(), r) == regions.end()) {
                regions.add (r);
-               select_edit_group_regions ();
-               add (&r->get_trackview());
+               if (Config->get_link_region_and_track_selection()) {
+                       add (&r->get_trackview());
+               }
                RegionsChanged ();
        }
 }
@@ -314,7 +324,7 @@ Selection::add (vector<RegionView*>& v)
        for (vector<RegionView*>::iterator i = v.begin(); i != v.end(); ++i) {
                if (find (regions.begin(), regions.end(), (*i)) == regions.end()) {
                        changed = regions.add ((*i));
-                       if (changed) {
+                       if (Config->get_link_region_and_track_selection() && changed) {
                                add (&(*i)->get_trackview());
                        }
                }
@@ -438,7 +448,7 @@ Selection::remove (RegionView* r)
                RegionsChanged ();
        }
 
-       if (!regions.involves (r->get_trackview())) {
+       if (Config->get_link_region_and_track_selection() && !regions.involves (r->get_trackview())) {
                remove (&r->get_trackview());
        }
 }
@@ -505,20 +515,32 @@ Selection::set (const list<boost::shared_ptr<Playlist> >& pllist)
 }
 
 void
-Selection::set (RegionView* r)
+Selection::set (const RegionSelection& rs)
+{
+       clear_regions();
+       regions = rs;
+       RegionsChanged(); /* EMIT SIGNAL */
+}
+
+void
+Selection::set (RegionView* r, bool also_clear_tracks)
 {
        clear_regions ();
-       clear_tracks ();
+       if (also_clear_tracks) {
+               clear_tracks ();
+       }
        add (r);
 }
 
 void
 Selection::set (vector<RegionView*>& v)
 {
-       clear_tracks ();
        clear_regions ();
-       // make sure to deselect any automation selections
-       clear_points();
+       if (Config->get_link_region_and_track_selection()) {
+               clear_tracks ();
+               // make sure to deselect any automation selections
+               clear_points();
+       }
        add (v);
 }
 
index 2b2db77360ad77b03c947bd8dbef46894e585692..17862e127b0aeb3529b405360c3252bc0aba5b7b 100644 (file)
@@ -102,7 +102,7 @@ class Selection : public sigc::trackable
        
        void set (TimeAxisView*);
        void set (const std::list<TimeAxisView*>&);
-       void set (RegionView*);
+       void set (RegionView*, bool also_clear_tracks = true);
        void set (std::vector<RegionView*>&);
        long set (TimeAxisView*, nframes_t, nframes_t);
        void set (ARDOUR::AutomationList*);
@@ -110,6 +110,7 @@ class Selection : public sigc::trackable
        void set (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
        void set (AutomationSelectable*);
        void set (Marker*);
+       void set (const RegionSelection&);
 
        void toggle (TimeAxisView*);
        void toggle (const std::list<TimeAxisView*>&);
@@ -131,6 +132,7 @@ class Selection : public sigc::trackable
        void add (boost::shared_ptr<ARDOUR::Playlist>);
        void add (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
        void add (Marker*);
+       void add (const RegionSelection&);
 
        void remove (TimeAxisView*);
        void remove (const std::list<TimeAxisView*>&);
index ae8209e9da471f4692f05fb6bd76f6d911379629..9bb0c75795877506072a4216f337934839361774 100644 (file)
@@ -395,6 +395,11 @@ SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::S
          found_search_btn (_("Search"))
 
 {
+       if (ARDOUR::Profile->get_sae()) {
+               chooser.add_shortcut_folder_uri("file:///Library/GarageBand/Apple Loops");
+               chooser.add_shortcut_folder_uri("file:///Library/Application Support/GarageBand/Instrument Library/Sampler/Sampler Files");
+       }
+       
        VBox* vbox;
        HBox* hbox;
 
index f6d6924a761efd17c7da49c2829f81b5842d989a..633e60e252fc8c2a2fc98570cd6b0f9a00ab40f9 100644 (file)
@@ -379,7 +379,6 @@ StreamView::set_selected_regionviews (RegionSelection& regions)
 {
        bool selected;
 
-       // cerr << _trackview.name() << " (selected = " << regions.size() << ")" << endl;
        for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
                
                selected = false;
@@ -389,8 +388,7 @@ StreamView::set_selected_regionviews (RegionSelection& regions)
                                selected = true;
                        }
                }
-               
-               // cerr << "\tregion " << (*i)->region().name() << " selected = " << selected << endl;
+
                (*i)->set_selected (selected);
        }
 }
index 229802b324cef4b413f9f7bfd21d58f282242c61..60dff79e07e5ff1d518cc8d3f0f8435df8f88475 100644 (file)
@@ -311,30 +311,45 @@ carbon_menu_item_update_accelerator (CarbonMenuItem *carbon_item,
          GdkKeymap       *keymap  = gdk_keymap_get_for_display (display);
          GdkKeymapKey    *keys;
          gint             n_keys;
+         gint             use_command;
 
          if (gdk_keymap_get_entries_for_keyval (keymap, key->accel_key,
                                                 &keys, &n_keys))
            {
-             UInt8 modifiers = 0;
+            UInt8 modifiers = 0; /* implies Command key */
 
              SetMenuItemCommandKey (carbon_item->menu, carbon_item->index,
                                     true, keys[0].keycode);
 
              g_free (keys);
 
+             use_command = 0;
+
              if (key->accel_mods)
                {
-                 if (key->accel_mods & GDK_SHIFT_MASK)
+                 if (key->accel_mods & GDK_SHIFT_MASK) {
                    modifiers |= kMenuShiftModifier;
+                 }
 
-                 if (key->accel_mods & GDK_MOD1_MASK)
+                 if (key->accel_mods & (GDK_MOD1_MASK)) {
                    modifiers |= kMenuOptionModifier;
-               }
-
-             if (!(key->accel_mods & GDK_CONTROL_MASK))
-               {
-                 modifiers |= kMenuNoCommandModifier;
-               }
+                 }
+
+                 if (key->accel_mods & GDK_CONTROL_MASK) {
+                   modifiers |= kMenuControlModifier;
+                 }
+                 
+                 if (key->accel_mods & GDK_MOD5_MASK) {
+                         /* Mod5 is what ardour's binding file uses to mean "Command"
+                            Nothing needs to be set in modifiers, but we need to notice
+                            that there *is* an implicit modifier
+                         */
+                         use_command = 1;
+                 }
+               }  
+
+             if (!use_command)
+               modifiers |= kMenuNoCommandModifier;
 
              SetMenuItemModifiers (carbon_item->menu, carbon_item->index,
                                    modifiers);
index f46d1c05dc9e8e6ac9c09c4d9692519a2eba5fd9..2cb06af63da3a9b11eed437979e2ba5580aec6e6 100644 (file)
@@ -96,5 +96,5 @@ void
 TapeAudioRegionView::set_frame_color ()
 {
        fill_opacity = 255;
-       TimeAxisViewItem::set_frame_color ();
+       AudioRegionView::set_frame_color ();
 }
index d69acf7ef1c43fea000ad5b8836bdbfc9f62582b..61adb7c0fe37a79b693656c64dc476032087e05b 100644 (file)
@@ -34,6 +34,7 @@ using namespace PBD;
 
 TempoDialog::TempoDialog (TempoMap& map, nframes_t frame, const string & action)
        : ArdourDialog (_("edit tempo")),
+         note_frame (_("BPM denominator")),
          bpm_adjustment (60.0, 1.0, 999.9, 0.1, 1.0, 1.0),
          bpm_spinner (bpm_adjustment),
          bpm_frame (_("Beats per minute")),
@@ -48,7 +49,7 @@ TempoDialog::TempoDialog (TempoMap& map, nframes_t frame, const string & action)
        Tempo tempo (map.tempo_at (frame));
        map.bbt_time (frame, when);
 
-       init (when, tempo.beats_per_minute(), true);
+       init (when, tempo.beats_per_minute(), tempo.note_type(), true);
 }
 
 TempoDialog::TempoDialog (TempoSection& section, const string & action)
@@ -63,23 +64,62 @@ TempoDialog::TempoDialog (TempoSection& section, const string & action)
          when_table (2, 2),
          when_frame (_("Location"))
 {
-       init (section.start(), section.beats_per_minute(), section.movable());
+       init (section.start(), section.beats_per_minute(), section.note_type(), section.movable());
 }
 
 void
-TempoDialog::init (const BBT_Time& when, double bpm, bool movable)
+TempoDialog::init (const BBT_Time& when, double bpm, double note_type, bool movable)
 {
        bpm_spinner.set_numeric (true);
-       bpm_spinner.set_digits (1);
+       bpm_spinner.set_digits (2);
        bpm_spinner.set_wrap (true);
        bpm_spinner.set_value (bpm);
 
+       strings.push_back (_("whole (1)"));
+       strings.push_back (_("second (2)"));
+       strings.push_back (_("third (3)"));
+       strings.push_back (_("quarter (4)"));
+       strings.push_back (_("eighth (8)"));
+       strings.push_back (_("sixteenth (16)"));
+       strings.push_back (_("thirty-second (32)"));
+       
+       /* the string here needs to be the longest one to display */
+       const guint32 FUDGE = 20; // Combo's are stupid - they steal space from the entry for the button
+       // TRANSLATORS: this is not a mis-spelling of "thirty", we're including a vertical 
+       // descender to make sure the height gets computed properly.
+        Gtkmm2ext::set_size_request_to_display_given_text (note_types, "thirtq-second (32)", 7+FUDGE, 15);
+
+       set_popdown_strings (note_types, strings);
+
+       if (note_type==1.0f)
+               note_types.set_active_text (_("whole (1)"));
+       else if (note_type==2.0f)
+               note_types.set_active_text (_("second (2)"));
+       else if (note_type==3.0f)
+               note_types.set_active_text (_("third (3)"));
+       else if (note_type==4.0f)
+               note_types.set_active_text (_("quarter (4)"));
+       else if (note_type==8.0f)
+               note_types.set_active_text (_("eighth (8)"));
+       else if (note_type==16.0f)
+               note_types.set_active_text (_("sixteenth (16)"));
+       else if (note_type==32.0f)
+               note_types.set_active_text (_("thirty-second (32)"));
+       else
+               note_types.set_active_text (_("quarter (4)"));
+
        hspacer1.set_border_width (5);
        hspacer1.pack_start (bpm_spinner, false, false);
        vspacer1.set_border_width (5);
        vspacer1.pack_start (hspacer1, false, false);
 
+       hspacer2.set_border_width (5);
+       hspacer2.pack_start (note_types, false, false);
+       vspacer2.set_border_width (5);
+       vspacer2.pack_start (hspacer2, false, false);
+
        bpm_frame.add (vspacer1);
+       note_frame.add (vspacer2);
 
        if (movable) {
                snprintf (buf, sizeof (buf), "%" PRIu32, when.bars);
@@ -115,9 +155,12 @@ TempoDialog::init (const BBT_Time& when, double bpm, bool movable)
 
        bpm_frame.set_name ("MetricDialogFrame");
        bpm_spinner.set_name ("MetricEntry");
+       note_frame.set_name ("MetricDialogFrame");
 
+       get_vbox()->set_border_width (12);
        get_vbox()->pack_start (bpm_frame, false, false);
-       
+       get_vbox()->pack_start (note_frame, false, false);
+
        add_button (Stock::CANCEL, RESPONSE_CANCEL);
        add_button (Stock::APPLY, RESPONSE_ACCEPT);
        set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
@@ -131,6 +174,7 @@ TempoDialog::init (const BBT_Time& when, double bpm, bool movable)
        bpm_spinner.signal_activate().connect (bind (mem_fun (*this, &TempoDialog::response), RESPONSE_ACCEPT));
        bpm_spinner.signal_button_press_event().connect (mem_fun (*this, &TempoDialog::bpm_button_press), false);
        bpm_spinner.signal_button_release_event().connect (mem_fun (*this, &TempoDialog::bpm_button_release), false);
+       note_types.signal_changed().connect (mem_fun (*this, &TempoDialog::note_types_change));
 }
 
 bool
@@ -168,6 +212,41 @@ TempoDialog::get_bbt_time (BBT_Time& requested)
        return true;
 }
 
+double
+TempoDialog::get_note_type ()
+{
+       double note_type = 0;
+       vector<string>::iterator i;
+       string text = note_types.get_active_text();
+       
+       for (i = strings.begin(); i != strings.end(); ++i) {
+               if (text == *i) {
+                       if (sscanf (text.c_str(), "%*[^0-9]%lf", &note_type) != 1) {
+                               error << string_compose(_("garbaged note type entry (%1)"), text) << endmsg;
+                               return 0;
+                       } else {
+                               break;
+                       }
+               }
+       } 
+       
+       if (i == strings.end()) {
+               if (sscanf (text.c_str(), "%lf", &note_type) != 1) {
+                       error << string_compose(_("incomprehensible note type entry (%1)"), text) << endmsg;
+                       return 0;
+               }
+       }
+
+       cerr << "returning " << note_type << " based on " << text << endl;
+       return note_type;
+}
+
+void
+TempoDialog::note_types_change ()
+{
+        set_response_sensitive (Gtk::RESPONSE_ACCEPT, true);
+}
+
 
 MeterDialog::MeterDialog (TempoMap& map, nframes_t frame, const string & action)
        : ArdourDialog ("meter dialog"),
@@ -216,6 +295,13 @@ MeterDialog::init (const BBT_Time& when, double bpb, double note_type, bool mova
        strings.push_back (_("sixteenth (16)"));
        strings.push_back (_("thirty-second (32)"));
        
+       /* the string here needs to be the longest one to display */
+       const guint32 FUDGE = 20; // Combo's are stupid - they steal space from the entry for the button
+
+       // TRANSLATORS: this is not a mis-spelling of "thirty", we're including a vertical 
+       // descender to make sure the height gets computed properly.
+        Gtkmm2ext::set_size_request_to_display_given_text (note_types, _("thirtq-second (32)"), 7+FUDGE, 15);
+
        set_popdown_strings (note_types, strings);
 
        if (note_type==1.0f)
@@ -235,10 +321,6 @@ MeterDialog::init (const BBT_Time& when, double bpb, double note_type, bool mova
        else
                note_types.set_active_text (_("quarter (4)"));
                
-       /* the string here needs to be the longest one to display */
-       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 (note_types, "thirty-second (32)", 7+FUDGE, 7);
-
        hspacer1.set_border_width (5);
        hspacer1.pack_start (note_types, false, false);
        vspacer1.set_border_width (5);
@@ -283,6 +365,8 @@ MeterDialog::init (const BBT_Time& when, double bpb, double note_type, bool mova
                
                get_vbox()->pack_start (when_frame, false, false);
        }
+
+       get_vbox()->set_border_width (12);
        get_vbox()->pack_start (bpb_frame, false, false);
        get_vbox()->pack_start (note_frame, false, false);
        
index b9f6a16b24e8aea7f9752d971412383fea18f606..a92f26f8e3664a4be4d18b480bbe75847e8442f0 100644 (file)
@@ -37,6 +37,9 @@
 
 struct TempoDialog : public ArdourDialog 
 {
+    Gtk::ComboBoxText note_types;
+    vector<string> strings;
+    Gtk::Frame   note_frame;
     Gtk::Adjustment   bpm_adjustment;
     Gtk::SpinButton   bpm_spinner;
     Gtk::Frame        bpm_frame;
@@ -44,8 +47,8 @@ struct TempoDialog : public ArdourDialog
     Gtk::Button  ok_button;
     Gtk::Button  cancel_button;
     Gtk::HBox    button_box;
-    Gtk::HBox    hspacer1;
-    Gtk::VBox    vspacer1;
+    Gtk::HBox    hspacer1, hspacer2;
+    Gtk::VBox    vspacer1, vspacer2;
     Gtk::Entry   when_bar_entry;
     Gtk::Entry   when_beat_entry;
     Gtk::Label   when_bar_label;
@@ -58,13 +61,15 @@ struct TempoDialog : public ArdourDialog
     TempoDialog (ARDOUR::TempoSection&, const string & action);
 
     double get_bpm ();
+    double get_note_type ();
     bool   get_bbt_time (ARDOUR::BBT_Time&);
     
   private:
-    void init (const ARDOUR::BBT_Time& start, double, bool);
+    void init (const ARDOUR::BBT_Time& start, double, double, bool);
     void bpm_changed ();
     bool bpm_button_press (GdkEventButton* );
     bool bpm_button_release (GdkEventButton* );
+    void note_types_change ();
 };
 
 struct MeterDialog : public ArdourDialog 
index 4815aff0a0f6c823facc79a30193d2d4c237452a..5788daf19d67083f209c40a1387b2dd748514c8d 100644 (file)
@@ -247,14 +247,14 @@ TimeAxisView::controls_ebox_scroll (GdkEventScroll* ev)
 {
        switch (ev->direction) {
        case GDK_SCROLL_UP:
-               if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+               if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
                        step_height (true);
                        return true;
                }
                break;
                
        case GDK_SCROLL_DOWN:
-               if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+               if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
                        step_height (false);
                        return true;
                }
@@ -364,11 +364,12 @@ TimeAxisView::set_height_pixels (uint32_t h)
 {
        height = h;
        controls_frame.set_size_request (-1, height + ((order == 0) ? 1 : 0));
-
+       //cerr << "TimeAxisView::set_height_pixels() called h = " << h << endl;//DEBUG
        if (canvas_item_visible (selection_group)) {
                /* resize the selection rect */
                show_selection (editor.get_selection().time);
        }
+       
 }
 
 bool
@@ -518,10 +519,7 @@ TimeAxisView::popup_display_menu (guint32 when)
                build_display_menu ();
        }
 
-       if (!get_selected()) {
-               editor.set_selected_track (*this, Selection::Set);
-       }
-
+       editor.set_selected_track (*this, Selection::Add);
        display_menu->popup (1, when);  
 }
 
index 4be3d4eabb7e0c87168627d6cf31dce18369cab5..18d6638738cab141d121db24249593da17462e28 100644 (file)
@@ -201,7 +201,7 @@ class TimeAxisViewItem : public Selectable
      */
     void set_name_text(const Glib::ustring& new_name) ;
     
-  virtual void set_y_position_and_height(double y, double h);
+    virtual void set_y_position_and_height(double y, double h) ;
     
     /**
      * 
@@ -357,7 +357,7 @@ class TimeAxisViewItem : public Selectable
     /**
      * Sets the frame color depending on whether this item is selected
      */
-    void set_frame_color() ;
+    virtual void set_frame_color() ;
     
     /**
      * Sets the colors of the start and end trim handle depending on object state
index 34f176f73a6952055c8f9ecee45e4a83e5f09d79..13db1f88036983ce2c48ef22ba08e747147450c3 100644 (file)
@@ -235,8 +235,6 @@ UIConfiguration::pack_canvasvars ()
 #define CANVAS_VARIABLE(var,name) canvas_colors.push_back(&var); 
 #include "canvas_vars.h"
 #undef  CANVAS_VARIABLE
-       cerr << "Configuration::pack_canvasvars () called, canvas_colors.size() = " << canvas_colors.size() << endl;
-       
 }
 
 
index 941132396acfd4aa31e3a2d5ba819b0ba941b930..a5238784461ad5dae2a5de485ecf5557f39c61c9 100644 (file)
@@ -406,7 +406,7 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
        GtkWidget* focus = gtk_window_get_focus (win);
        bool special_handling_of_unmodified_accelerators = false;
 
-#undef  DEBUG_ACCELERATOR_HANDLING
+#undef DEBUG_ACCELERATOR_HANDLING
 #ifdef  DEBUG_ACCELERATOR_HANDLING
        bool debug = (getenv ("ARDOUR_DEBUG_ACCELERATOR_HANDLING") != 0);
 #endif
@@ -490,15 +490,14 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
                        return true;
                }
        }
-               
-       if (!special_handling_of_unmodified_accelerators ||
-           ev->state & (Gdk::MOD1_MASK|
-                        Gdk::MOD3_MASK|
-                        Gdk::MOD4_MASK|
-                        Gdk::MOD5_MASK|
-                        Gdk::CONTROL_MASK)) {
 
-               /* no special handling or modifiers in effect: accelerate first */
+       /* consider all relevant modifiers but not LOCK or SHIFT */
+
+       guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
+
+       if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
+
+               /* no special handling or there are modifiers in effect: accelerate first */
 
 #ifdef DEBUG_ACCELERATOR_HANDLING
                if (debug) {
@@ -511,12 +510,17 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
                }
 #endif
                if (!gtk_window_activate_key (win, ev)) {
+#ifdef DEBUG_ACCELERATOR_HANDLING
+                       if (debug) {
+                               cerr << "\tnot accelerated, now propagate\n";
+                       }
+#endif
                        return gtk_window_propagate_key_event (win, ev);
                } else {
 #ifdef DEBUG_ACCELERATOR_HANDLING
-               if (debug) {
-                       cerr << "\tnot handled\n";
-               }
+                       if (debug) {
+                               cerr << "\taccelerated - done.\n";
+                       }
 #endif
                        return true;
                } 
@@ -588,11 +592,24 @@ get_icon (const char* cname)
 
        sys::path data_file_path;
 
-       if(!find_file_in_search_path (spath, name, data_file_path)) {
+       if (!find_file_in_search_path (spath, name, data_file_path)) {
                fatal << string_compose (_("cannot find icon image for %1"), name) << endmsg;
        }
 
-       return Gdk::Pixbuf::create_from_file (data_file_path.to_string());
+       Glib::RefPtr<Gdk::Pixbuf> img;
+       try {
+               img = Gdk::Pixbuf::create_from_file (data_file_path.to_string());
+       }
+       catch (const Gdk::PixbufError &e)
+    {
+        cerr << "Caught PixbufError: " << e.what() << endl;
+    }
+    catch (...)
+    {
+        g_message("Caught ... ");
+    }
+
+       return img;
 }
 
 string
index e1378dbb2a41ff3aac13ddf22a5aaab495a8b44a..5072c42a8e92af3f2f34dd8b0463ab6ad866a10a 100644 (file)
@@ -57,6 +57,12 @@ VSTPluginUI::get_preferred_height ()
        return vst->fst()->height;
 }
 
+int
+VSTPluginUI::get_preferred_width ()
+{
+       return vst->fst()->width;
+}
+
 int
 VSTPluginUI::package (Gtk::Window& win)
 {
index b5908341df125caf0272bcb26676d7789e0c2ce9..5c5d5c9ab2929ae60188e89ff4044a9a744bb839 100644 (file)
@@ -4,3 +4,8 @@ void
 ARDOUR_UI::platform_specific ()
 {
 }
+
+void
+ARDOUR_UI::platform_setup ()
+{
+}
index 6661ea16a2e3d36053d5770f0da0c1ff33690b4b..6a05bb22957d5d692d36af4da1b3306481142374 100644 (file)
@@ -129,7 +129,6 @@ sndfile_helpers.cc
 sndfilesource.cc
 source.cc
 source_factory.cc
-stretch.cc
 tape_file_matcher.cc
 template_utils.cc
 tempo.cc
@@ -145,6 +144,7 @@ vst_files = [ 'vst_plugin.cc', 'session_vst.cc' ]
 audiounit_files = [ 'audio_unit.cc' ]
 coreaudio_files = [ 'coreaudiosource.cc' ]
 extra_sources = [ ]
+timefx_sources = [ ]
 
 if ardour['VST']:
        extra_sources += vst_files
@@ -296,22 +296,28 @@ ardour.Merge ([
             libraries['samplerate'],
             libraries['sigc2'],
             libraries['pbd'],
-            libraries['soundtouch'],
             libraries['midi++2'],
             libraries['glib2'],
             libraries['glibmm2']
             ])
 
+#if ardour['RUBBERBAND']:
+#      ardour.Merge ([ libraries['rubberband'],  libraries['vamp'], libraries['fftw3f'] ])
+#      timefx_sources += [ 'rb_effect.cc' ]
+#else:
+ardour.Merge ([ libraries['soundtouch'] ])
+timefx_sources += [ 'st_stretch.cc', 'st_pitch.cc' ]
+       
 if ardour['LIBLO']:
-    ardour.Merge ([ libraries['lo'] ])
+       ardour.Merge ([ libraries['lo'] ])
 
 if ardour['COREAUDIO'] or ardour['AUDIOUNITS']:
-    ardour.Merge ([ libraries['appleutility'] ])
+       ardour.Merge ([ libraries['appleutility'] ])
 
 def SharedAsmObjectEmitter(target, source, env):
-    for tgt in target:
-        tgt.attributes.shared = 1
-    return (target, source)
+       for tgt in target:
+               tgt.attributes.shared = 1
+       return (target, source)
 
 
 env['BUILDERS']['SharedAsmObject'] = Builder (action = '$CXX -c -fPIC $SOURCE -o $TARGET',
@@ -341,12 +347,12 @@ if env['FPU_OPTIMIZATION']:
                arch_specific_objects = env.SharedAsmObject('sse_functions_64bit.os', 'sse_functions_64bit.s')
                always_sse_objects += [ sse_env.SharedObject (source = 'sse_functions_xmm.cc') ]
                        
-libardour = ardour.SharedLibrary('ardour', ardour_files + always_sse_objects + extra_sources + arch_specific_objects)
+libardour = ardour.SharedLibrary('ardour', ardour_files + always_sse_objects + timefx_sources + extra_sources + arch_specific_objects)
 
 Default(libardour)
 
 if env['NLS']:
-       i18n (ardour, ardour_files + vst_files + coreaudio_files + audiounit_files, env)
+       i18n (ardour, ardour_files + vst_files + coreaudio_files + timefx_sources + audiounit_files, env)
 
 
 env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ardour2'), libardour))
@@ -354,6 +360,8 @@ env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ar
 env.Alias('version', ardour.VersionBuild(['version.cc', 'ardour/version.h'], []))
 
 env.Alias('tarball', env.Distribute (env['DISTTREE'],
-                                    [ 'SConscript', 'i18n.h', 'gettext.h', 'sse_functions_xmm.cc', 'sse_functions.s', 'sse_functions_64bit.s' ] +
+                                    [ 'SConscript', 'i18n.h', 'gettext.h' ] + 
+                                    [ 'sse_functions_xmm.cc', 'sse_functions.s', 'sse_functions_64bit.s' ] +
+                                    [ 'rb_effect.cc', 'st_stretch.cc', 'st_pitch.cc' ] +
                                     ardour_files + osc_files + vst_files + coreaudio_files + audiounit_files +
                                     glob.glob('po/*.po') + glob.glob('ardour/*.h')))
index 6e7b494441b260319774111e67185de29989ac3a..fcec83394f14ee7d56bc3cd3659c375eebe352f9 100644 (file)
@@ -48,6 +48,8 @@ namespace ARDOUR {
        int cleanup ();
 
        std::string get_ardour_revision ();
+       
+       const layer_t max_layer = UCHAR_MAX;
 
        microseconds_t get_microseconds ();
 
index 09bf5946fa40a853af0421866712d99b5998cca9..1f6c2f63bf15411c59d1cf47580850e0fdd85b9f 100644 (file)
@@ -43,6 +43,7 @@ public:
        
        /** Read @a len frames FROM THE START OF @a src into self at @a offset */
        void read_from(const Buffer& src, nframes_t len, nframes_t offset) {
+               assert(&src != this);
                assert(_capacity > 0);
                assert(src.type() == DataType::AUDIO);
                assert(offset + len <= _capacity);
index 7b31b1937f974a8f01b47d3a52c01ef841d1d07b..b0e4d34c2804afe948ba4c09faf08b201b1ed066 100644 (file)
@@ -22,6 +22,7 @@
 #define __ardour_audio_unit_h__
 
 #include <stdint.h>
+#include <boost/shared_ptr.hpp>
 
 #include <list>
 #include <set>
@@ -30,6 +31,8 @@
 
 #include <ardour/plugin.h>
 
+#include <AudioUnit/AudioUnit.h>
+
 #include <boost/shared_ptr.hpp>
 
 class CAComponent;
@@ -45,13 +48,13 @@ class Session;
 class AUPlugin : public ARDOUR::Plugin
 {
   public:
-       AUPlugin (AudioEngine& engine, Session& session, CAComponent* comp);
+       AUPlugin (AudioEngine& engine, Session& session, boost::shared_ptr<CAComponent> comp);
        virtual ~AUPlugin ();
        
-       uint32_t unique_id () const;
+        std::string unique_id () const;
        const char * label () const;
        const char * name () const { return _info->name.c_str(); }
-       const char * maker () const;
+       const char * maker () const { return _info->creator.c_str(); }
        uint32_t parameter_count () const;
        float default_value (uint32_t port);
        nframes_t signal_latency () const;
@@ -87,34 +90,65 @@ class AUPlugin : public ARDOUR::Plugin
     
        bool has_editor () const;
        
-       CAAudioUnit* get_au () { return unit; }
-       CAComponent* get_comp () { return comp; }
-       
+       bool fixed_io() const { return false; }
+       int32_t can_support_input_configuration (int32_t in);
+       int32_t compute_output_streams (int32_t nplugins);
+       uint32_t output_streams() const;
+       uint32_t input_streams() const;
+
+       boost::shared_ptr<CAAudioUnit> get_au () { return unit; }
+       boost::shared_ptr<CAComponent> get_comp () { return comp; }
+    
+        OSStatus render_callback(AudioUnitRenderActionFlags *ioActionFlags,
+                                const AudioTimeStamp    *inTimeStamp,
+                                UInt32       inBusNumber,
+                                UInt32       inNumberFrames,
+                                AudioBufferList*       ioData);
   private:
-       CAComponent* comp;
-    CAAudioUnit* unit;
-
-       AudioBufferList* in_list;
-       AudioBufferList* out_list;
+        boost::shared_ptr<CAComponent> comp;
+        boost::shared_ptr<CAAudioUnit> unit;
+       
+       AudioStreamBasicDescription streamFormat;
+        bool initialized;
+        int format_set;
+       AudioBufferList* buffers;
+       
+       UInt32 global_elements;
+       UInt32 output_elements;
+       UInt32 input_elements;
+       
+       int set_output_format ();
+       int set_input_format ();
+       int set_stream_format (int scope, uint32_t cnt);
+        int _set_block_size (nframes_t nframes);
 
        std::vector<std::pair<uint32_t, uint32_t> > parameter_map;
+       uint32_t current_maxbuf;
+        nframes_t current_offset;
+        nframes_t cb_offset;
+        vector<Sample*>* current_buffers;
+        nframes_t frames_processed;
 };
-
+       
 typedef boost::shared_ptr<AUPlugin> AUPluginPtr;
 
 class AUPluginInfo : public PluginInfo {
   public:      
-       AUPluginInfo () { };
+        AUPluginInfo (boost::shared_ptr<CAComponentDescription>);
        ~AUPluginInfo ();
 
-       CAComponentDescription* desc;
+       PluginPtr load (Session& session);
 
        static PluginInfoList discover ();
-       PluginPtr load (Session& session);
+       static void get_names (CAComponentDescription&, std::string& name, Glib::ustring& maker);
+        static std::string stringify_descriptor (const CAComponentDescription&);
 
   private:
-       static std::string get_name (CAComponentDescription&);
-       void setup_nchannels (CAComponentDescription&);
+       boost::shared_ptr<CAComponentDescription> descriptor;
+
+        static void discover_music (PluginInfoList&);
+        static void discover_fx (PluginInfoList&);
+        static void discover_by_description (PluginInfoList&, CAComponentDescription&);
 };
 
 typedef boost::shared_ptr<AUPluginInfo> AUPluginInfoPtr;
index dc7ae8e000818285f2d756e4839a1c6e4b508d1b..88f1111a6c4158b2c64e64c0324f5b0decd56ebd 100644 (file)
@@ -106,7 +106,13 @@ class AudioEngine : public sigc::trackable
 
        class PortRegistrationFailure : public std::exception {
          public:
-               virtual const char *what() const throw() { return "failed port registration"; }
+               PortRegistrationFailure (const char* why = "") {
+                       reason = why;
+               }
+               virtual const char *what() const throw() { return reason; }
+
+         private:
+               const char* reason;
        };
 
        class NoBackendAvailable : public std::exception {
@@ -235,6 +241,8 @@ class AudioEngine : public sigc::trackable
 
        std::string get_nth_physical (DataType type, uint32_t n, int flags);
 
+       void port_registration_failure (const std::string& portname);
+
        static int  _xrun_callback (void *arg);
        static int  _graph_order_callback (void *arg);
        static int  _process_callback (nframes_t nframes, void *arg);
index ba2bbaee223bf83b21553b720262bb63ce8f4a24..b84d197c3f90b0def9e0e77d976285c7d91ac27d 100644 (file)
@@ -76,8 +76,10 @@ class AudioRegion : public Region
                                      uint32_t chan_n=0, double samples_per_unit= 1.0) const;
        
        virtual nframes_t read_at (Sample *buf, Sample *mixdown_buf,
-                                  float *gain_buf, nframes_t position, nframes_t cnt, 
-                                  uint32_t       chan_n      = 0) const;
+                       float *gain_buf, nframes_t position, nframes_t cnt, 
+                       uint32_t  chan_n      = 0,
+                       nframes_t read_frames = 0,
+                       nframes_t skip_frames = 0) const;
        
        virtual nframes_t master_read_at (Sample *buf, Sample *mixdown_buf, 
                                          float *gain_buf,
@@ -146,8 +148,10 @@ class AudioRegion : public Region
        void recompute_gain_at_start ();
 
        nframes_t _read_at (const SourceList&, Sample *buf, Sample *mixdown_buffer, 
-                           float *gain_buffer, nframes_t position, nframes_t cnt, 
-                           uint32_t chan_n = 0) const;
+                                float *gain_buffer, nframes_t position, nframes_t cnt, 
+                                uint32_t chan_n = 0,
+                                nframes_t read_frames = 0,
+                                nframes_t skip_frames = 0) const;
 
        void recompute_at_start ();
        void recompute_at_end ();
@@ -174,13 +178,6 @@ class AudioRegion : public Region
        AudioRegion (boost::shared_ptr<const AudioRegion>);
 
        int set_live_state (const XMLNode&, Change&, bool send);
-       
-       virtual bool verify_start (nframes_t);
-       virtual bool verify_start_and_length (nframes_t, nframes_t);
-       virtual bool verify_start_mutable (nframes_t&_start);
-       virtual bool verify_length (nframes_t);
-       /*virtual void recompute_at_start () = 0;
-       virtual void recompute_at_end () = 0;*/
 };
 
 } /* namespace ARDOUR */
index f02b28d9f594ff1f7a7e8460b5b5f874cdb4b60f..93708a5b07b5dc2561ad4c38e7cfce477b4a5770 100644 (file)
@@ -43,9 +43,7 @@ using std::vector;
 
 namespace ARDOUR {
 
-const nframes_t frames_per_peak = 256;
-
- class AudioSource : public Source, public boost::enable_shared_from_this<ARDOUR::AudioSource>
+class AudioSource : public Source, public boost::enable_shared_from_this<ARDOUR::AudioSource>
 {
   public:
        AudioSource (Session&, Glib::ustring name);
@@ -72,7 +70,8 @@ const nframes_t frames_per_peak = 256;
        uint32_t read_data_count() const { return _read_data_count; }
        uint32_t write_data_count() const { return _write_data_count; }
 
-       virtual int read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, double samples_per_unit) const;
+       int read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, double samples_per_visual_peak) const;
+
        int  build_peaks ();
        bool peaks_ready (sigc::slot<void>, sigc::connection&) const;
 
@@ -129,6 +128,12 @@ const nframes_t frames_per_peak = 256;
        
        void update_length (nframes_t pos, nframes_t cnt);
 
+       virtual int read_peaks_with_fpp (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, 
+                                        double samples_per_visual_peak, nframes_t fpp) const;
+
+       int compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframes_t cnt, bool force, 
+                                    bool intermediate_peaks_ready_signal, nframes_t frames_per_peak);
+
   private:
        int peakfile;
        nframes_t peak_leftover_cnt;
index edae45a56a49e095ea445c823546681f8e6d0222..aa27a3ef24e982dec1a9c84f17069c1b2a195d56 100644 (file)
@@ -72,6 +72,8 @@ CONFIG_VARIABLE (uint32_t, destructive_xfade_msecs,  "destructive-xfade-msecs",
 
 CONFIG_VARIABLE (EditMode, edit_mode, "edit-mode", Slide)
 CONFIG_VARIABLE (LayerModel, layer_model, "layer-model", MoveAddHigher)
+CONFIG_VARIABLE (bool, link_region_and_track_selection, "link-region-and-track-selection", false)
+CONFIG_VARIABLE (std::string, keyboard_layout_name, "keyboard-layout-name", "ansi")
 
 /* monitoring, mute, solo etc */
 
@@ -148,6 +150,8 @@ CONFIG_VARIABLE (uint32_t, periodic_safety_backup_interval, "periodic-safety-bac
 CONFIG_VARIABLE (float, automation_interval, "automation-interval", 50)
 CONFIG_VARIABLE (bool, sync_all_route_ordering, "sync-all-route-ordering", true)
 CONFIG_VARIABLE (bool, only_copy_imported_files, "only-copy-imported-files", true)
+CONFIG_VARIABLE (std::string, keyboard_layout, "keyboard-layout", "ansi")
+CONFIG_VARIABLE (std::string, default_bindings, "default-bindings", "ardour")
 
 /* denormal management */
 
index 78a137bde30a2482e0a0f1ca2be74334f45d5e1e..9ba3689e823f1fb545d8b46ebd5aa2c205eb9d79 100644 (file)
@@ -81,8 +81,10 @@ class Crossfade : public ARDOUR::AudioRegion
        boost::shared_ptr<ARDOUR::AudioRegion> out() const { return _out; }
        
        nframes_t read_at (Sample *buf, Sample *mixdown_buffer, 
-                          float *gain_buffer, nframes_t position, nframes_t cnt, 
-                          uint32_t chan_n) const;
+                               float *gain_buffer, nframes_t position, nframes_t cnt, 
+                               uint32_t chan_n,
+                               nframes_t read_frames = 0,
+                               nframes_t skip_frames = 0) const;
        
        bool refresh ();
 
index e466e532155fb5c506da0658d2414a24e5f1743e..7c0b0b2abed2695e699f303db0ff97e9ff43e900 100644 (file)
@@ -53,7 +53,7 @@ class LadspaPlugin : public ARDOUR::Plugin
 
        /* Plugin interface */
        
-       uint32_t unique_id() const                       { return descriptor->UniqueID; }
+       std::string unique_id() const;
        const char * label() const                       { return descriptor->Label; }
        const char * name() const                        { return descriptor->Name; }
        const char * maker() const                       { return descriptor->Maker; }
index 5ffb716598d61be6cd222d2c8551ffcbba5f64cd..53d9489823184ae8f645d341808f7b7ec0be9de0 100644 (file)
@@ -146,6 +146,8 @@ class Locations : public PBD::StatefulDestructible
        Locations ();
        ~Locations ();
        
+       const LocationList& list() { return locations; }
+
        void add (Location *, bool make_current = false);
        void remove (Location *);
        void clear ();
diff --git a/libs/ardour/ardour/pitch.h b/libs/ardour/ardour/pitch.h
new file mode 100644 (file)
index 0000000..38d8380
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+    Copyright (C) 2007 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_pitch_h__
+#define __ardour_pitch_h__
+
+#include <ardour/filter.h>
+
+namespace ARDOUR {
+       class AudioRegion;
+}
+
+#ifdef USE_RUBBERBAND
+
+#include <ardour/rb_effect.h>
+
+namespace ARDOUR {
+
+class Pitch : public RBEffect {
+  public:
+       Pitch (ARDOUR::Session&, TimeFXRequest&);
+       ~Pitch () {}
+};
+
+} /* namespace */
+
+# else
+
+namespace ARDOUR {
+
+class Pitch : public Filter {
+  public:
+       Pitch (ARDOUR::Session&, TimeFXRequest&);
+       ~Pitch () {}
+
+       int run (boost::shared_ptr<ARDOUR::Region>);
+
+  private:
+       TimeFXRequest& tsr;
+};
+
+} /* namespace */
+
+#endif
+
+#endif /* __ardour_pitch_h__ */
index f2e07aa067e8cbd8d93d4af9a45275c617f1e081..3f328de00518654d63b1f455b47b15007d18b580 100644 (file)
@@ -95,6 +95,7 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla
        void partition (nframes_t start, nframes_t end, bool just_top_level);
        void duplicate (boost::shared_ptr<Region>, nframes_t position, float times);
        void nudge_after (nframes_t start, nframes_t distance, bool forwards);
+       void shuffle (boost::shared_ptr<Region>, int dir);
 
        boost::shared_ptr<Playlist> cut  (list<AudioRange>&, bool result_is_hidden = true);
        boost::shared_ptr<Playlist> copy (list<AudioRange>&, bool result_is_hidden = true);
@@ -102,9 +103,12 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla
 
        RegionList*                regions_at (nframes_t frame);
        RegionList*                regions_touched (nframes_t start, nframes_t end);
+       RegionList*                regions_to_read (nframes_t start, nframes_t end);
        boost::shared_ptr<Region>  find_region (const PBD::ID&) const;
        boost::shared_ptr<Region>  top_region_at (nframes_t frame);
        boost::shared_ptr<Region>  find_next_region (nframes_t frame, RegionPoint point, int dir);
+       nframes64_t                find_next_region_boundary (nframes64_t frame, int dir);
+       bool                       region_is_shuffle_constrained (boost::shared_ptr<Region>);
 
        template<class T> void foreach_region (T *t, void (T::*func)(boost::shared_ptr<Region>, void *), void *arg);
        template<class T> void foreach_region (T *t, void (T::*func)(boost::shared_ptr<Region>));
@@ -124,6 +128,8 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla
        void freeze ();
        void thaw ();
 
+       void raise_region (boost::shared_ptr<Region>);
+       void lower_region (boost::shared_ptr<Region>);
        void raise_region_to_top (boost::shared_ptr<Region>);
        void lower_region_to_bottom (boost::shared_ptr<Region>);
 
@@ -182,6 +188,7 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla
        bool             first_set_state;
        bool            _hidden;
        bool            _splicing;
+       bool            _shuffling;
        bool            _nudging;
        uint32_t        _refcnt;
        EditMode        _edit_mode;
@@ -227,12 +234,12 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla
 
        void sort_regions ();
 
-       void possibly_splice ();
-       void possibly_splice_unlocked();
-       void core_splice ();
-       void splice_locked ();
-       void splice_unlocked ();
+       void possibly_splice (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude = boost::shared_ptr<Region>());
+       void possibly_splice_unlocked(nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude = boost::shared_ptr<Region>());
 
+       void core_splice (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude);
+       void splice_locked (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude);
+       void splice_unlocked (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude);
 
        virtual void finalize_split_region (boost::shared_ptr<Region> original, boost::shared_ptr<Region> left, boost::shared_ptr<Region> right) {}
        
@@ -258,6 +265,7 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla
        boost::shared_ptr<Playlist> cut (nframes_t start, nframes_t cnt, bool result_is_hidden);
        boost::shared_ptr<Playlist> copy (nframes_t start, nframes_t cnt, bool result_is_hidden);
 
+       int move_region_to_layer (layer_t, boost::shared_ptr<Region> r, int dir);
        void relayer ();
        
        void unset_freeze_parent (Playlist*);
index 830ed7c02531fd85d132abcd16ef6156f09485e7..d721476db7b51f3b3473168f6373303b8d9a60f1 100644 (file)
@@ -77,7 +77,7 @@ class PluginInfo {
        ChanCount n_outputs;
        ARDOUR::PluginType type;
        
-       long unique_id;
+       std::string unique_id;
 
        virtual PluginPtr load (Session& session) = 0;
 
@@ -114,7 +114,7 @@ class Plugin : public PBD::StatefulDestructible, public Latent
            bool max_unbound;
        };
 
-       virtual uint32_t unique_id() const = 0;
+       virtual std::string unique_id() const = 0;
        virtual const char * label() const = 0;
        virtual const char * name() const = 0;
        virtual const char * maker() const = 0;
@@ -170,7 +170,7 @@ class Plugin : public PBD::StatefulDestructible, public Latent
        bool save_preset(string name, string domain /* vst, ladspa etc. */);
 };
 
-PluginPtr find_plugin(ARDOUR::Session&, string name, long unique_id, ARDOUR::PluginType);
+PluginPtr find_plugin(ARDOUR::Session&, string unique_id, ARDOUR::PluginType);
 
 } // namespace ARDOUR
  
index bce723d85725029d5c07a6004d71eaeaa12c31d7..64b871104bb3b6c8e77576d0f579fdbd8ee0a8d5 100644 (file)
@@ -40,6 +40,7 @@ class PluginManager {
 
        ARDOUR::PluginInfoList &vst_plugin_info () { return _vst_plugin_info; }
        ARDOUR::PluginInfoList &ladspa_plugin_info () { return _ladspa_plugin_info; }
+       ARDOUR::PluginInfoList &au_plugin_info () { return _au_plugin_info; }
 
        void refresh ();
 
@@ -51,6 +52,8 @@ class PluginManager {
   private:
        ARDOUR::PluginInfoList _vst_plugin_info;
        ARDOUR::PluginInfoList _ladspa_plugin_info;
+       ARDOUR::PluginInfoList _au_plugin_info;
+       
        std::map<uint32_t, std::string> rdf_type;
 
        std::string ladspa_path;
@@ -64,6 +67,9 @@ class PluginManager {
        void add_vst_presets ();
        void add_presets (std::string domain);
 
+       int au_discover ();
+       void au_refresh ();
+
        int vst_discover_from_path (std::string path);
        int vst_discover (std::string path);
 
@@ -71,6 +77,7 @@ class PluginManager {
        int ladspa_discover (std::string path);
 
        std::string get_ladspa_category (uint32_t id);
+       std::vector<uint32_t> ladspa_plugin_whitelist;
 
        static PluginManager* _manager; // singleton
 };
diff --git a/libs/ardour/ardour/rb_effect.h b/libs/ardour/ardour/rb_effect.h
new file mode 100644 (file)
index 0000000..bde0422
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+    Copyright (C) 2007 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_rbeffect_h__
+#define __ardour_rbeffect_h__
+
+#include <ardour/audiofilter.h>
+
+namespace ARDOUR {
+
+class AudioRegion;
+
+class RBEffect : public Filter {
+  public:
+       RBEffect (ARDOUR::Session&, TimeFXRequest&);
+       ~RBEffect ();
+
+       int run (boost::shared_ptr<ARDOUR::Region>);
+
+  private:
+       TimeFXRequest& tsr;
+};
+
+} /* namespace */
+
+#endif /* __ardour_rbeffect_h__ */
index c246da9cce00f680f0b525f69b38b3e2cebb895e..76b41a04cbb8f4fb9a29f2c61322a4657b368214 100644 (file)
@@ -96,11 +96,17 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
        nframes_t length()    const { return _length; }
        layer_t   layer ()    const { return _layer; }
 
+       /* these two are valid ONLY during a StateChanged signal handler */
+
+       nframes_t last_position() const { return _last_position; }
+       nframes_t last_length() const { return _last_length; }
+
        nframes64_t ancestral_start () const { return _ancestral_start; }
        nframes64_t ancestral_length () const { return _ancestral_length; }
        float stretch() const { return _stretch; }
+       float shift() const { return _shift; }
 
-       void set_ancestral_data (nframes64_t start, nframes64_t length, float stretch);
+       void set_ancestral_data (nframes64_t start, nframes64_t length, float stretch, float shift);
 
        nframes_t sync_offset(int& dir) const;
        nframes_t sync_position() const;
@@ -129,7 +135,7 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
        void thaw (const string& why);
 
        bool covers (nframes_t frame) const {
-               return first_frame() <= frame && frame < last_frame();
+               return first_frame() <= frame && frame <= last_frame();
        }
 
        OverlapType coverage (nframes_t start, nframes_t end) const {
@@ -149,7 +155,7 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
        void set_position (nframes_t, void *src);
        void set_position_on_top (nframes_t, void *src);
        void special_set_position (nframes_t);
-       void nudge_position (long, void *src);
+       void nudge_position (nframes64_t, void *src);
 
        bool at_natural_position () const;
        void move_to_natural_position (void *src);
@@ -160,6 +166,8 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
        void trim_to (nframes_t position, nframes_t length, void *src);
        
        void set_layer (layer_t l); /* ONLY Playlist can call this */
+       void raise ();
+       void lower ();
        void raise_to_top ();
        void lower_to_bottom ();
 
@@ -232,10 +240,11 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
        void maybe_uncopy ();
        void first_edit ();
        
-       virtual bool verify_start (nframes_t);
-       virtual bool verify_start_and_length (nframes_t, nframes_t);
-       virtual bool verify_start_mutable (nframes_t&_start);
-       virtual bool verify_length (nframes_t);
+       bool verify_start (nframes_t);
+       bool verify_start_and_length (nframes_t, nframes_t&);
+       bool verify_start_mutable (nframes_t&_start);
+       bool verify_length (nframes_t);
+       
        virtual void recompute_at_start () = 0;
        virtual void recompute_at_end () = 0;
 
@@ -243,7 +252,9 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
        Flag                    _flags;
        nframes_t               _start;
        nframes_t               _length;
+       nframes_t               _last_length;
        nframes_t               _position;
+       nframes_t               _last_position;
        nframes_t               _sync_position;
        layer_t                 _layer;
        mutable RegionEditState _first_edit;
@@ -251,6 +262,7 @@ class Region : public Automatable, public boost::enable_shared_from_this<Region>
        nframes64_t             _ancestral_start;
        nframes64_t             _ancestral_length;
        float                   _stretch;
+       float                   _shift;
        mutable uint32_t        _read_data_count;  ///< modified in read()
        Change                  _pending_changed;
        uint64_t                _last_layer_op;  ///< timestamp
index fc17af06eedf4c4f476c0829a4a394a7f457acfb..d2e40501f1096a4652b1c66006b09d8d8aa6af82 100644 (file)
@@ -109,7 +109,7 @@ class Route : public IO
 
        void set_gain (gain_t val, void *src);
        void inc_gain (gain_t delta, void *src);
-
+       
        bool active() const { return _active; }
        void set_active (bool yn);
 
index d0add4e2aa13514274673208ff428bff08818823..90a9563ad1be021a0a97a9512b38e08f9eda55f0 100644 (file)
@@ -138,6 +138,7 @@ class Session : public PBD::StatefulDestructible
                    SetDiskstreamSpeed,
                    Locate,
                    LocateRoll,
+                   LocateRollLocate,
                    SetLoop,
                    PunchIn,
                    PunchOut,
@@ -224,9 +225,9 @@ class Session : public PBD::StatefulDestructible
        /* creating from an XML file */
 
        Session (AudioEngine&,
-                string fullpath,
-                string snapshot_name,
-                string* mix_template = 0);
+                const string& fullpath,
+                const string& snapshot_name,
+                string mix_template = "");
 
        /* creating a new Session */
 
@@ -354,7 +355,7 @@ class Session : public PBD::StatefulDestructible
 
        sigc::signal<void,RouteList&> RouteAdded;
 
-       void request_roll ();
+       void request_roll_at_and_return (nframes_t start, nframes_t return_to);
        void request_bounded_roll (nframes_t start, nframes_t end);
        void request_stop (bool abort = false);
        void request_locate (nframes_t frame, bool with_roll = false);
@@ -499,6 +500,7 @@ class Session : public PBD::StatefulDestructible
 
        nframes_t transport_frame () const {return _transport_frame; }
        nframes_t audible_frame () const;
+       nframes64_t requested_return_frame() const { return _requested_return_frame; }
 
        enum PullupFormat {
                pullup_Plus4Plus1,
@@ -542,6 +544,9 @@ class Session : public PBD::StatefulDestructible
        float       transport_speed() const { return _transport_speed; }
        bool        transport_stopped() const { return _transport_speed == 0.0f; }
        bool        transport_rolling() const { return _transport_speed != 0.0f; }
+       
+       void set_silent (bool yn);
+       bool silent () { return _silent; }
 
        int jack_slave_sync (nframes_t);
 
@@ -701,6 +706,13 @@ class Session : public PBD::StatefulDestructible
        uint32_t n_port_inserts() const { return _port_inserts.size(); }
        uint32_t n_plugin_inserts() const { return _plugin_inserts.size(); }
        uint32_t n_sends() const { return _sends.size(); }
+       
+       static void set_disable_all_loaded_plugins (bool yn) { 
+               _disable_all_loaded_plugins = yn;
+       }
+       static bool get_disable_all_loaded_plugins() { 
+               return _disable_all_loaded_plugins;
+       }
 
        uint32_t next_send_id();
        uint32_t next_insert_id();
@@ -901,6 +913,18 @@ class Session : public PBD::StatefulDestructible
                                  long value,
                                  void* ptr,
                                  float opt);
+       
+       typedef float (*compute_peak_t)          (Sample *, nframes_t, float);
+       typedef void  (*find_peaks_t)            (Sample *, nframes_t, float *, float*);
+       typedef void  (*apply_gain_to_buffer_t)  (Sample *, nframes_t, float);
+       typedef void  (*mix_buffers_with_gain_t) (Sample *, Sample *, nframes_t, float);
+       typedef void  (*mix_buffers_no_gain_t)   (Sample *, Sample *, nframes_t);
+
+       static compute_peak_t           compute_peak;
+       static find_peaks_t             find_peaks;
+       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;
 
@@ -927,12 +951,9 @@ class Session : public PBD::StatefulDestructible
        void update_latency_compensation (bool, bool);
        
   private:
+       int  create (bool& new_session, const string& mix_template, nframes_t initial_length);
        void destroy ();
-
-       void initialize_start_and_end_locations(nframes_t start, nframes_t end);
-       bool create_session_file();
-       bool create_session_file_from_template (const string& template_path);
-
+       
        nframes_t compute_initial_length ();
 
        enum SubState {
@@ -949,35 +970,36 @@ class Session : public PBD::StatefulDestructible
        */
 
        typedef void (Session::*process_function_type)(nframes_t);
-
-       AudioEngine            &_engine;
-       mutable gint            processing_prohibited;
-       /// the function called when the main JACK process callback happens
+       
+       AudioEngine&            _engine;
+       mutable gint             processing_prohibited;
        process_function_type    process_function;
        process_function_type    last_process_function;
        bool                     waiting_for_sync_offset;
-       nframes_t          _base_frame_rate;
-       nframes_t          _current_frame_rate;  //this includes video pullup offset
+       nframes_t               _base_frame_rate;
+       nframes_t               _current_frame_rate;  //this includes video pullup offset
        int                      transport_sub_state;
-       mutable gint           _record_status;
-       nframes_t          _transport_frame;
+       mutable gint            _record_status;
+       volatile nframes_t      _transport_frame;
        Location*                end_location;
        Location*                start_location;
-       Slave                  *_slave;
+       Slave*                  _slave;
+       bool                    _silent;
        volatile float          _transport_speed;
        volatile float          _desired_transport_speed;
        float                   _last_transport_speed;
        bool                     auto_play_legal;
-       nframes_t          _last_slave_transport_frame;
-       nframes_t           maximum_output_latency;
-       nframes_t           last_stop_frame;
+       nframes_t               _last_slave_transport_frame;
+       nframes_t                maximum_output_latency;
+       nframes_t                last_stop_frame;
+       volatile nframes64_t    _requested_return_frame;
        BufferSet*              _scratch_buffers;
        BufferSet*              _silent_buffers;
        BufferSet*              _mix_buffers;
-       nframes_t           current_block_size;
-       nframes_t          _worst_output_latency;
-       nframes_t          _worst_input_latency;
-       nframes_t          _worst_track_latency;
+       nframes_t                current_block_size;
+       nframes_t               _worst_output_latency;
+       nframes_t               _worst_input_latency;
+       nframes_t               _worst_track_latency;
        bool                    _have_captured;
        float                   _meter_hold;
        float                   _meter_falloff;
@@ -1675,6 +1697,8 @@ class Session : public PBD::StatefulDestructible
        
        void set_history_depth (uint32_t depth);
        void sync_order_keys ();
+       
+       static bool _disable_all_loaded_plugins;
 };
 
 } // namespace ARDOUR
index 92ef076a9ba62d6005bb710de53b82b7f67000eb..e0103185c2d6e8612e5e6eaf2165d5e7816c4b80 100644 (file)
@@ -34,11 +34,6 @@ class SilentFileSource : public AudioFileSource {
 
        void set_length (nframes_t len);
        
-       int read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, double samples_per_unit) const {
-               memset (peaks, 0, sizeof (PeakData) * npeaks);
-               return 0;
-       }
-
        bool destructive() const { return false; }
 
   protected:
@@ -58,6 +53,11 @@ class SilentFileSource : public AudioFileSource {
 
        void set_header_timeline_position () {}
 
+       int read_peaks_with_fpp (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, double samples_per_unit, nframes_t fpp) const {
+               memset (peaks, 0, sizeof (PeakData) * npeaks);
+               return 0;
+       }
+
 };
 
 } // namespace ARDOUR
index 73b66ca20e530eef9585c09565bfac2c7774c414..509f8fa9d2fce8c44988243e3395133a37492a79 100644 (file)
@@ -47,6 +47,7 @@ class Slave {
        virtual bool starting() const { return false; }
        virtual nframes_t resolution() const = 0;
        virtual bool requires_seekahead () const = 0;
+       virtual bool is_always_synced() const { return false; }
 };
 
 
@@ -139,6 +140,7 @@ class JACK_Slave : public Slave
        nframes_t resolution() const { return 1; }
        bool requires_seekahead () const { return false; }
        void reset_client (jack_client_t* jack);
+       bool is_always_synced() const { return true; }
 
   private:
        jack_client_t* jack;
index 26a93ad1249493137b9cec97cb9d8df10804ce8f..cf6b15f3a4f523c862e7ba8c913d830d7e00e620 100644 (file)
@@ -28,7 +28,7 @@ using std::string;
 // Use this define when initializing arrarys for use in sndfile_*_format()
 #define SNDFILE_STR_LENGTH 32
 
-#define SNDFILE_HEADER_FORMATS 7
+#define SNDFILE_HEADER_FORMATS 5
 extern const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1];
 extern const char * const sndfile_file_endings_strings[SNDFILE_HEADER_FORMATS+1];
 
index 6f323dd8786ea8001e2c6acc54bb243f83d34107..869111bb0784a404498dce37704576b95c8892f6 100644 (file)
@@ -63,6 +63,8 @@ class Source : public SessionObject
        XMLNode& get_state ();
        int set_state (const XMLNode&);
        
+       virtual bool destructive() const { return false; }
+       
        void use () { _in_use++; }
        void disuse () { if (_in_use) { _in_use--; } }
        
index 4d00c9b17bdcddbe100066a0db5a0d5428ef90c7..020d03270df804b8ffa9d218674cf3100ad50052 100644 (file)
 #define __ardour_stretch_h__
 
 #include <ardour/filter.h>
-#include <soundtouch/SoundTouch.h>
 
 namespace ARDOUR {
+       class AudioRegion;
+}
+
+#ifdef USE_RUBBERBAND
 
-class AudioRegion;
+#include <ardour/rb_effect.h>
+
+namespace ARDOUR {
 
-struct TimeStretchRequest : public InterThreadInfo {
-    float                fraction;   
-    bool                 quick_seek; 
-    bool                 antialias;  
+class Stretch : public RBEffect {
+  public:
+       Stretch (ARDOUR::Session&, TimeFXRequest&);
+       ~Stretch() {}
 };
 
+} /* namespace */
+
+#else
+
+#include <soundtouch/SoundTouch.h>
+
+namespace ARDOUR {
+
 class Stretch : public Filter {
   public:
-       Stretch (ARDOUR::Session&, TimeStretchRequest&);
+       Stretch (ARDOUR::Session&, TimeFXRequest&);
        ~Stretch ();
 
        int run (boost::shared_ptr<ARDOUR::Region>);
 
   private:
-       TimeStretchRequest& tsr;
-       soundtouch::SoundTouch st;
+       TimeFXRequest& tsr;
 
+       soundtouch::SoundTouch st;
 };
 
 } /* namespace */
 
+#endif
+
 #endif /* __ardour_stretch_h__ */
index 2d8462a7515ef9dab609b8fbe76cf56d5a0b2ac0..72f24c10544698a9559f0b474170dbe8f9a0dcd2 100644 (file)
@@ -40,27 +40,29 @@ using std::list;
 using std::vector;
 
 namespace ARDOUR {
-
+class Meter;
 class Tempo {
   public:
-       Tempo (double bpm)
-               : _beats_per_minute (bpm) {}
+       Tempo (double bpm, double type=4.0) // defaulting to quarter note
+               : _beats_per_minute (bpm), _note_type(type) {} 
        Tempo (const Tempo& other) {
                _beats_per_minute = other._beats_per_minute;
+               _note_type = other._note_type;
        }
        void operator= (const Tempo& other) {
                if (&other != this) {
                        _beats_per_minute = other._beats_per_minute;
+                       _note_type = other._note_type;
                }
        }
 
-       double beats_per_minute () const { return _beats_per_minute; }
-       double frames_per_beat (nframes_t sr) const {
-               return  ((60.0 * sr) / _beats_per_minute);
-       }
+       double beats_per_minute () const { return _beats_per_minute;}
+       double note_type () const { return _note_type;}
+       double frames_per_beat (nframes_t sr, const Meter& meter) const;
 
   protected:
        double _beats_per_minute;
+       double _note_type;
 };
 
 class Meter {
@@ -149,8 +151,8 @@ class MeterSection : public MetricSection, public Meter {
 
 class TempoSection : public MetricSection, public Tempo {
   public:
-       TempoSection (const BBT_Time& start, double qpm)
-               : MetricSection (start), Tempo (qpm) {}
+       TempoSection (const BBT_Time& start, double qpm, double note_type)
+               : MetricSection (start), Tempo (qpm, note_type) {}
        TempoSection (const XMLNode&);
 
        static const string xml_state_node_name;
index 0d32d35c7d8ab5afb8e329336b8f3cd89f038f4e..d7961babbd7c8f860d65bdf630dafb826d33aecd 100644 (file)
@@ -379,6 +379,13 @@ namespace ARDOUR {
                SrcFastest
        };
 
+       struct TimeFXRequest : public InterThreadInfo {
+           float time_fraction;
+           float pitch_fraction;
+           bool  quick_seek; 
+           bool  antialias;  
+       };
+
 } // namespace ARDOUR
 
 std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
index 1622df0c1aeef3922c4482adc508a448fa5c7565..3a05360f157923a7917ac982b6a0ebbdfa3dc1a6 100644 (file)
@@ -56,7 +56,7 @@ class VSTPlugin : public ARDOUR::Plugin
 
        /* Plugin interface */
        
-       uint32_t unique_id() const;
+       std::string unique_id() const;
        const char * label() const;
        const char * name() const;
        const char * maker() const;
index 4871035e80cb11cf0d56a7489c80c8dbb6106ccb..8444304832384e2a7df76d2f0532c66d6c78063f 100644 (file)
@@ -32,7 +32,7 @@ AudioBuffer::AudioBuffer(size_t capacity)
        , _owns_data (false)
        , _data (0)
 {
-       if (_capacity) {
+       if (_capacity > 0) {
                _owns_data = true; // prevent resize() from gagging
                resize (_capacity);
                silence (_capacity);
index bc42cb0b5b5849c6c07c023ed6e8ac0a6fbf6541..bc4a352c45f1134e9ad1f30406f6c9db1a3a4b99 100644 (file)
@@ -850,10 +850,18 @@ AudioDiskstream::commit (nframes_t nframes)
        }
        
        if (_slaved) {
-               need_butler = c->front()->playback_buf->write_space() >= c->front()->playback_buf->bufsize() / 2;
+               /*if (_io && _io->active()) {*/
+                       need_butler = c->front()->playback_buf->write_space() >= c->front()->playback_buf->bufsize() / 2;
+               /*} else {
+                       need_butler = false;
+               }*/
        } else {
-               need_butler = c->front()->playback_buf->write_space() >= disk_io_chunk_frames
-                       || c->front()->capture_buf->read_space() >= disk_io_chunk_frames;
+               /*if (_io && _io->active()) {*/
+                       need_butler = c->front()->playback_buf->write_space() >= disk_io_chunk_frames
+                               || c->front()->capture_buf->read_space() >= disk_io_chunk_frames;
+               /*} else {
+                       need_butler = c->front()->capture_buf->read_space() >= disk_io_chunk_frames;
+               }*/
        }
 
        if (commit_should_unlock) {
@@ -1940,6 +1948,7 @@ AudioDiskstream::set_state (const XMLNode& node)
        if (nchans > _n_channels.n_audio()) {
 
                add_channel (nchans - _n_channels.n_audio());
+               IO::PortCountChanged(_n_channels);
 
        } else if (nchans < _n_channels.n_audio()) {
 
index 0631c9121b1fcf5e2b2acf257d07dddac6eaf7a0..1506d204f15f6400d49e6db7f5811780ce051455 100644 (file)
@@ -123,7 +123,10 @@ ARDOUR::nframes_t
 AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t start,
                     nframes_t cnt, unsigned chan_n)
 {
+       nframes_t ret = cnt;
        nframes_t end;
+       nframes_t read_frames;
+       nframes_t skip_frames;
 
        /* optimizing this memset() away involves a lot of conditionals
           that may well cause more of a hit due to cache misses 
@@ -147,14 +150,24 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nf
        Glib::Mutex::Lock rm (region_lock);
 
        end =  start + cnt - 1;
+       read_frames = 0;
+       skip_frames = 0;
+       _read_data_count = 0;
 
        _read_data_count = 0;
 
+       RegionList* rlist = regions_to_read (start, start+cnt);
+
+       if (rlist->empty()) {
+               delete rlist;
+               return cnt;
+       }
+
        map<uint32_t,vector<boost::shared_ptr<Region> > > relevant_regions;
        map<uint32_t,vector<boost::shared_ptr<Crossfade> > > relevant_xfades;
        vector<uint32_t> relevant_layers;
 
-       for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+       for (RegionList::iterator i = rlist->begin(); i != rlist->end(); ++i) {
                if ((*i)->coverage (start, end) != OverlapNone) {
                        relevant_regions[(*i)->layer()].push_back (*i);
                        relevant_layers.push_back ((*i)->layer());
@@ -186,7 +199,7 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nf
                for (vector<boost::shared_ptr<Region> >::iterator i = r.begin(); i != r.end(); ++i) {
                        boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(*i);
                        assert(ar);
-                       ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n);
+                       ar->read_at (buf, mixdown_buffer, gain_buffer, start, cnt, chan_n, read_frames, skip_frames);
                        _read_data_count += ar->read_data_count();
                }
                
@@ -199,7 +212,8 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nf
                }
        }
 
-       return cnt;
+       delete rlist;
+       return ret;
 }
 
 
index 66d31c63fecef177d507e5f43dbef264014f16f7..714be28f3409c4c0ce7fe4006fd7621bdb9598ba 100644 (file)
 using namespace ARDOUR;
 using namespace std;
 
-AudioPort::AudioPort (const std::string& name, Flags flgs, bool external, nframes_t capacity)
-       : Port (name, flgs)
-       , BaseAudioPort (name, flgs)
-       , PortFacade (name, flgs)
+AudioPort::AudioPort (const std::string& name, Flags flags, bool external, nframes_t capacity)
+       : Port (name, flags)
+       , BaseAudioPort (name, flags)
+       , PortFacade (name, flags)
 {
        if (!external || receives_input()) {
 
@@ -43,6 +43,7 @@ AudioPort::AudioPort (const std::string& name, Flags flgs, bool external, nframe
        if (!external) {
 
                _ext_port = 0;
+               set_name (name);
 
        } else {
                
@@ -52,7 +53,7 @@ AudioPort::AudioPort (const std::string& name, Flags flgs, bool external, nframe
                   will in turn be using the JACK port buffer for data.
                */
 
-               _ext_port = new JackAudioPort (name, flgs, 0);
+               _ext_port = new JackAudioPort (name, flags, 0);
 
                if (sends_output()) {
                        _buffer = &dynamic_cast<JackAudioPort*>(_ext_port)->get_audio_buffer();
index dfcffb8cfed2288750ab9e86c59d58a47f673efa..f86e78416955b5f8ed71c5739c85a59631af7ad2 100644 (file)
@@ -1,6 +1,5 @@
 /*
     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
 
 */
 
+#include <sstream>
+
 #include <pbd/transmitter.h>
 #include <pbd/xml++.h>
+#include <pbd/whitespace.h>
+
+#include <glibmm/thread.h>
 
 #include <ardour/audioengine.h>
+#include <ardour/io.h>
 #include <ardour/audio_unit.h>
 #include <ardour/session.h>
 #include <ardour/utils.h>
@@ -37,66 +42,93 @@ using namespace std;
 using namespace PBD;
 using namespace ARDOUR;
 
-AUPlugin::AUPlugin (AudioEngine& engine, Session& session, CAComponent* _comp)
+static OSStatus 
+_render_callback(void *userData,
+                AudioUnitRenderActionFlags *ioActionFlags,
+                const AudioTimeStamp    *inTimeStamp,
+                UInt32       inBusNumber,
+                UInt32       inNumberFrames,
+                AudioBufferList*       ioData)
+{
+       return ((AUPlugin*)userData)->render_callback (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
+}
+
+AUPlugin::AUPlugin (AudioEngine& engine, Session& session, boost::shared_ptr<CAComponent> _comp)
        :
        Plugin (engine, session),
        comp (_comp),
-       unit (new CAAudioUnit)
+       unit (new CAAudioUnit),
+       initialized (false),
+       buffers (0),
+       current_maxbuf (0),
+       current_offset (0),
+       current_buffers (0),
+       frames_processed (0)
 {                      
-       OSErr err = CAAudioUnit::Open (*comp, *unit);
+       OSErr err = CAAudioUnit::Open (*(comp.get()), *unit);
+
        if (err != noErr) {
                error << _("AudioUnit: Could not convert CAComponent to CAAudioUnit") << endmsg;
-               delete unit;
-               delete comp;
                throw failed_constructor ();
        }
        
-       unit->Initialize ();
+       AURenderCallbackStruct renderCallbackInfo;
+
+       renderCallbackInfo.inputProc = _render_callback;
+       renderCallbackInfo.inputProcRefCon = this;
+
+       if ((err = unit->SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 
+                                        0, (void*) &renderCallbackInfo, sizeof(renderCallbackInfo))) != 0) {
+               cerr << "cannot install render callback (err = " << err << ')' << endl;
+               throw failed_constructor();
+       }
+
+       unit->GetElementCount (kAudioUnitScope_Input, input_elements);
+       unit->GetElementCount (kAudioUnitScope_Output, output_elements);
+
+       // set up the basic stream format. these fields do not change
+                           
+       streamFormat.mSampleRate = session.frame_rate();
+       streamFormat.mFormatID = kAudioFormatLinearPCM;
+       streamFormat.mFormatFlags = kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked|kAudioFormatFlagIsNonInterleaved;
+       streamFormat.mBitsPerChannel = 32;
+       streamFormat.mFramesPerPacket = 1;
+
+       // subject to later modification as we discover channel counts
+
+       streamFormat.mBytesPerPacket = 4;
+       streamFormat.mBytesPerFrame = 4;
+       streamFormat.mChannelsPerFrame = 1;
+
+       format_set = 0;
+
+       if (_set_block_size (_session.get_block_size())) {
+               error << _("AUPlugin: cannot set processing block size") << endmsg;
+               throw failed_constructor();
+       }
 }
 
 AUPlugin::~AUPlugin ()
 {
        if (unit) {
                unit->Uninitialize ();
-               delete unit;
-       }
-       
-       if (comp) {
-               delete comp;
-       }
-       
-       if (in_list) {
-               delete in_list;
        }
-       
-       if (out_list) {
-               delete out_list;
-       }
-}
 
-AUPluginInfo::~AUPluginInfo ()
-{
-       if (desc) {
-               delete desc;
+       if (buffers) {
+               free (buffers);
        }
 }
 
-uint32_t
+string
 AUPlugin::unique_id () const
 {
-       return 0;
+       return AUPluginInfo::stringify_descriptor (comp->Desc());
 }
 
 const char *
 AUPlugin::label () const
 {
-       return "AUPlugin label";
-}
-
-const char *
-AUPlugin::maker () const
-{
-       return "AUplugin maker";
+       return _info->name.c_str();
 }
 
 uint32_t
@@ -125,7 +157,7 @@ AUPlugin::signal_latency () const
 void
 AUPlugin::set_parameter (uint32_t which, float val)
 {
-       unit->SetParameter (parameter_map[which].first, parameter_map[which].second, 0, val);
+       // unit->SetParameter (parameter_map[which].first, parameter_map[which].second, 0, val);
 }
 
 float
@@ -133,7 +165,7 @@ AUPlugin::get_parameter (uint32_t which) const
 {
        float outValue = 0.0;
        
-       unit->GetParameter(parameter_map[which].first, parameter_map[which].second, 0, outValue);
+       // unit->GetParameter(parameter_map[which].first, parameter_map[which].second, 0, outValue);
        
        return outValue;
 }
@@ -153,19 +185,174 @@ AUPlugin::nth_parameter (uint32_t which, bool& ok) const
 void
 AUPlugin::activate ()
 {
-       unit->GlobalReset ();
+       if (!initialized) {
+               OSErr err;
+               if ((err = unit->Initialize()) != noErr) {
+                       error << string_compose (_("AUPlugin: cannot initialize plugin (err = %1)"), err) << endmsg;
+               } else {
+                       frames_processed = 0;
+                       initialized = true;
+               }
+       }
 }
 
 void
 AUPlugin::deactivate ()
 {
-       // not needed.  GlobalReset () takes care of it.
+       unit->GlobalReset ();
 }
 
 void
 AUPlugin::set_block_size (nframes_t nframes)
 {
+       _set_block_size (nframes);
+}
+
+int
+AUPlugin::_set_block_size (nframes_t nframes)
+{
+       bool was_initialized = initialized;
+       UInt32 numFrames = nframes;
+       OSErr err;
+
+       if (initialized) {
+               unit->Uninitialize ();
+       }
+
+       if ((err = unit->SetProperty (kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 
+                                     0, &numFrames, sizeof (numFrames))) != noErr) {
+               cerr << "cannot set max frames (err = " << err << ')' << endl;
+               return -1;
+       }
+
+       if (was_initialized) {
+               activate ();
+       }
+
+       return 0;
+}
+
+int32_t 
+AUPlugin::can_support_input_configuration (int32_t in)
+{      
+       streamFormat.mChannelsPerFrame = in;
+       /* apple says that for non-interleaved data, these
+          values always refer to a single channel.
+       */
+       streamFormat.mBytesPerPacket = 4;
+       streamFormat.mBytesPerFrame = 4;
+
+       if (set_input_format () == 0) {
+               return 1;
+       } else {
+               return -1;
+       }
+}
+
+int
+AUPlugin::set_input_format ()
+{
+       return set_stream_format (kAudioUnitScope_Input, input_elements);
+}
+
+int
+AUPlugin::set_output_format ()
+{
+       return set_stream_format (kAudioUnitScope_Output, output_elements);
+}
+
+int
+AUPlugin::set_stream_format (int scope, uint32_t cnt)
+{
+       OSErr result;
+
+       for (uint32_t i = 0; i < cnt; ++i) {
+               if ((result = unit->SetFormat (scope, i, streamFormat)) != 0) {
+                       error << string_compose (_("AUPlugin: could not set stream format for %1/%2 (err = %3)"),
+                                                (scope == kAudioUnitScope_Input ? "input" : "output"), i, result) << endmsg;
+                       return -1;
+               }
+       }
+
+       if (scope == kAudioUnitScope_Input) {
+               format_set |= 0x1;
+       } else {
+               format_set |= 0x2;
+       }
+
+       return 0;
+}
+
+int32_t 
+AUPlugin::compute_output_streams (int32_t nplugins)
+{
+       /* we will never replicate AU plugins - either they can do the I/O we need
+          or not. thus, we can ignore nplugins entirely.
+       */
        
+       if (set_output_format() == 0) {
+
+               if (buffers) {
+                       free (buffers);
+                       buffers = 0;
+               }
+
+               buffers = (AudioBufferList *) malloc (offsetof(AudioBufferList, mBuffers) + 
+                                                     streamFormat.mChannelsPerFrame * sizeof(AudioBuffer));
+
+               Glib::Mutex::Lock em (_session.engine().process_lock());
+               IO::MoreOutputs (streamFormat.mChannelsPerFrame);
+
+               return streamFormat.mChannelsPerFrame;
+       } else {
+               return -1;
+       }
+}
+
+uint32_t
+AUPlugin::output_streams() const
+{
+       if (!(format_set & 0x2)) {
+               warning << _("AUPlugin: output_streams() called without any format set!") << endmsg;
+               return 1;
+       }
+       return streamFormat.mChannelsPerFrame;
+}
+
+
+uint32_t
+AUPlugin::input_streams() const
+{
+       if (!(format_set & 0x1)) {
+               warning << _("AUPlugin: input_streams() called without any format set!") << endmsg;
+               return 1;
+       }
+       return streamFormat.mChannelsPerFrame;
+}
+
+OSStatus 
+AUPlugin::render_callback(AudioUnitRenderActionFlags *ioActionFlags,
+                         const AudioTimeStamp    *inTimeStamp,
+                         UInt32       inBusNumber,
+                         UInt32       inNumberFrames,
+                         AudioBufferList*       ioData)
+{
+       /* not much to do - the data is already in the buffers given to us in connect_and_run() */
+
+       if (current_maxbuf == 0) {
+               error << _("AUPlugin: render callback called illegally!") << endmsg;
+               return kAudioUnitErr_CannotDoInCurrentContext;
+       }
+
+       for (uint32_t i = 0; i < current_maxbuf; ++i) {
+               ioData->mBuffers[i].mNumberChannels = 1;
+               ioData->mBuffers[i].mDataByteSize = sizeof (Sample) * inNumberFrames;
+               ioData->mBuffers[i].mData = (*current_buffers)[i] + cb_offset + current_offset;
+       }
+
+       cb_offset += inNumberFrames;
+
+       return noErr;
 }
 
 int
@@ -173,17 +360,37 @@ AUPlugin::connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in,
 {
        AudioUnitRenderActionFlags flags = 0;
        AudioTimeStamp ts;
-       
-       AudioBufferList abl;
-       abl.mNumberBuffers = 1;
-       abl.mBuffers[0].mNumberChannels = 1;
-       abl.mBuffers[0].mDataByteSize = nframes * sizeof(Sample);
-       abl.mBuffers[0].mData = &bufs[0];
-       
-       
-       unit->Render (&flags, &ts, 0, 0, &abl);
-       
-       return 0;
+
+       current_buffers = &bufs;
+       current_maxbuf = maxbuf;
+       current_offset = offset;
+       cb_offset = 0;
+
+       buffers->mNumberBuffers = maxbuf;
+
+       for (uint32_t i = 0; i < maxbuf; ++i) {
+               buffers->mBuffers[i].mNumberChannels = 1;
+               buffers->mBuffers[i].mDataByteSize = nframes * sizeof (Sample);
+               buffers->mBuffers[i].mData = 0;
+       }
+
+       ts.mSampleTime = frames_processed;
+       ts.mFlags = kAudioTimeStampSampleTimeValid;
+
+       if (unit->Render (&flags, &ts, 0, nframes, buffers) == noErr) {
+
+               current_maxbuf = 0;
+               frames_processed += nframes;
+               
+               for (uint32_t i = 0; i < maxbuf; ++i) {
+                       if (bufs[i] + offset != buffers->mBuffers[i].mData) {
+                               memcpy (bufs[i]+offset, buffers->mBuffers[i].mData, nframes * sizeof (Sample));
+                       }
+               }
+               return 0;
+       }
+
+       return -1;
 }
 
 set<uint32_t>
@@ -245,8 +452,8 @@ AUPlugin::parameter_is_output (uint32_t) const
 XMLNode&
 AUPlugin::get_state()
 {
-       XMLNoderoot = new XMLNode (state_node_name());
-       
+       XMLNode *root = new XMLNode (state_node_name());
+       LocaleGuard lg (X_("POSIX"));
        return *root;
 }
 
@@ -279,7 +486,19 @@ AUPlugin::get_presets ()
 bool
 AUPlugin::has_editor () const
 {
-       return false;
+       // even if the plugin doesn't have its own editor, the AU API can be used
+       // to create one that looks native.
+       return true;
+}
+
+AUPluginInfo::AUPluginInfo (boost::shared_ptr<CAComponentDescription> d)
+       : descriptor (d)
+{
+
+}
+
+AUPluginInfo::~AUPluginInfo ()
+{
 }
 
 PluginPtr
@@ -288,7 +507,7 @@ AUPluginInfo::load (Session& session)
        try {
                PluginPtr plugin;
 
-               CAComponent* comp = new CAComponent(*desc);
+               boost::shared_ptr<CAComponent> comp (new CAComponent(*descriptor));
                
                if (!comp->IsValid()) {
                        error << ("AudioUnit: not a valid Component") << endmsg;
@@ -296,7 +515,7 @@ AUPluginInfo::load (Session& session)
                        plugin.reset (new AUPlugin (session.engine(), session, comp));
                }
                
-               plugin->set_info(PluginInfoPtr(new AUPluginInfo(*this)));
+               plugin->set_info (PluginInfoPtr (new AUPluginInfo (*this)));
                return plugin;
        }
 
@@ -310,6 +529,28 @@ AUPluginInfo::discover ()
 {
        PluginInfoList plugs;
 
+       discover_fx (plugs);
+       discover_music (plugs);
+
+       return plugs;
+}
+
+void
+AUPluginInfo::discover_music (PluginInfoList& plugs)
+{
+       CAComponentDescription desc;
+       desc.componentFlags = 0;
+       desc.componentFlagsMask = 0;
+       desc.componentSubType = 0;
+       desc.componentManufacturer = 0;
+       desc.componentType = kAudioUnitType_MusicEffect;
+
+       discover_by_description (plugs, desc);
+}
+
+void
+AUPluginInfo::discover_fx (PluginInfoList& plugs)
+{
        CAComponentDescription desc;
        desc.componentFlags = 0;
        desc.componentFlagsMask = 0;
@@ -317,35 +558,146 @@ AUPluginInfo::discover ()
        desc.componentManufacturer = 0;
        desc.componentType = kAudioUnitType_Effect;
 
+       discover_by_description (plugs, desc);
+}
+
+void
+AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescription& desc)
+{
        Component comp = 0;
 
        comp = FindNextComponent (NULL, &desc);
+
        while (comp != NULL) {
                CAComponentDescription temp;
                GetComponentInfo (comp, &temp, NULL, NULL, NULL);
+
+               AUPluginInfoPtr info (new AUPluginInfo 
+                                     (boost::shared_ptr<CAComponentDescription> (new CAComponentDescription(temp))));
+
+               /* no panners, format converters or i/o AU's for our purposes
+                */
+
+               switch (info->descriptor->Type()) {
+               case kAudioUnitType_Panner:
+               case kAudioUnitType_OfflineEffect:
+               case kAudioUnitType_FormatConverter:
+                       continue;
+               default:
+                       break;
+               }
+
+               switch (info->descriptor->SubType()) {
+               case kAudioUnitSubType_DefaultOutput:
+               case kAudioUnitSubType_SystemOutput:
+               case kAudioUnitSubType_GenericOutput:
+               case kAudioUnitSubType_AUConverter:
+                       continue;
+                       break;
+
+               case kAudioUnitSubType_DLSSynth:
+                       info->category = "DLSSynth";
+                       break;
+
+               case kAudioUnitType_MusicEffect:
+                       info->category = "MusicEffect";
+                       break;
+
+               case kAudioUnitSubType_Varispeed:
+                       info->category = "Varispeed";
+                       break;
+
+               case kAudioUnitSubType_Delay:
+                       info->category = "Delay";
+                       break;
+
+               case kAudioUnitSubType_LowPassFilter:
+                       info->category = "LowPassFilter";
+                       break;
+
+               case kAudioUnitSubType_HighPassFilter:
+                       info->category = "HighPassFilter";
+                       break;
+
+               case kAudioUnitSubType_BandPassFilter:
+                       info->category = "BandPassFilter";
+                       break;
+
+               case kAudioUnitSubType_HighShelfFilter:
+                       info->category = "HighShelfFilter";
+                       break;
+
+               case kAudioUnitSubType_LowShelfFilter:
+                       info->category = "LowShelfFilter";
+                       break;
+
+               case kAudioUnitSubType_ParametricEQ:
+                       info->category = "ParametricEQ";
+                       break;
+
+               case kAudioUnitSubType_GraphicEQ:
+                       info->category = "GraphicEQ";
+                       break;
+
+               case kAudioUnitSubType_PeakLimiter:
+                       info->category = "PeakLimiter";
+                       break;
+
+               case kAudioUnitSubType_DynamicsProcessor:
+                       info->category = "DynamicsProcessor";
+                       break;
+
+               case kAudioUnitSubType_MultiBandCompressor:
+                       info->category = "MultiBandCompressor";
+                       break;
+
+               case kAudioUnitSubType_MatrixReverb:
+                       info->category = "MatrixReverb";
+                       break;
+
+               case kAudioUnitType_Mixer:
+                       info->category = "Mixer";
+                       break;
+
+               case kAudioUnitSubType_StereoMixer:
+                       info->category = "StereoMixer";
+                       break;
+
+               case kAudioUnitSubType_3DMixer:
+                       info->category = "3DMixer";
+                       break;
+
+               case kAudioUnitSubType_MatrixMixer:
+                       info->category = "MatrixMixer";
+                       break;
+
+               default:
+                       info->category = "";
+               }
+
+               AUPluginInfo::get_names (temp, info->name, info->creator);
+
+               info->type = ARDOUR::AudioUnit;
+               info->unique_id = stringify_descriptor (*info->descriptor);
+
+               /* mark the plugin as having flexible i/o */
                
-               AUPluginInfoPtr plug(new AUPluginInfo);
-               plug->name = AUPluginInfo::get_name (temp);
-               plug->type = ARDOUR::AudioUnit;
-               plug->n_inputs = 0;
-               plug->n_outputs = 0;
-               // plug->setup_nchannels (temp);
-               plug->category = "AudioUnit";
-               plug->desc = new CAComponentDescription(temp);
-
-               plugs.push_back(plug);
+               info->n_inputs = -1;
+               info->n_outputs = -1;
+
+
+               plugs.push_back (info);
                
                comp = FindNextComponent (comp, &desc);
        }
-
-       return plugs;
 }
 
-string
-AUPluginInfo::get_name (CAComponentDescription& comp_desc)
+void
+AUPluginInfo::get_names (CAComponentDescription& comp_desc, std::string& name, Glib::ustring& maker)
 {
        CFStringRef itemName = NULL;
-       // Marc Poirier -style item name
+
+       // Marc Poirier-style item name
        CAComponent auComponent (comp_desc);
        if (auComponent.IsValid()) {
                CAComponentDescription dummydesc;
@@ -379,23 +731,36 @@ AUPluginInfo::get_name (CAComponentDescription& comp_desc)
                        CFRelease(compManufacturerString);
        }
        
-       return CFStringRefToStdString(itemName);
-}
-
-void
-AUPluginInfo::setup_nchannels (CAComponentDescription& comp_desc)
-{
-       CAAudioUnit unit;
-       
-       CAAudioUnit::Open (comp_desc, unit);
-       
-       if (unit.SupportsNumChannels()) {
-               n_inputs = n_outputs = 0;
+       string str = CFStringRefToStdString(itemName);
+       string::size_type colon = str.find (':');
+
+       if (colon) {
+               name = str.substr (colon+1);
+               maker = str.substr (0, colon);
+               // strip_whitespace_edges (maker);
+               // strip_whitespace_edges (name);
        } else {
-               AUChannelInfo cinfo;
-               size_t info_size = sizeof(cinfo);
-               OSStatus err = AudioUnitGetProperty (unit.AU(), kAudioUnitProperty_SupportedNumChannels, kAudioUnitScope_Global,
-                                             0, &cinfo, &info_size);
+               name = str;
+               maker = "unknown";
        }
 }
 
+// from CAComponentDescription.cpp (in libs/appleutility in ardour source)
+extern char *StringForOSType (OSType t, char *writeLocation);
+
+std::string
+AUPluginInfo::stringify_descriptor (const CAComponentDescription& desc)
+{
+       char str[24];
+       stringstream s;
+
+       s << StringForOSType (desc.Type(), str);
+       s << " - ";
+               
+       s << StringForOSType (desc.SubType(), str);
+       s << " - ";
+               
+       s << StringForOSType (desc.Manu(), str);
+
+       return s.str();
+}
index 91ff8b8d35efb67ec16a682c24ed6ef18d99b783..08d18c7cab9dd38b631d8edcee2265897d32bce1 100644 (file)
@@ -22,6 +22,7 @@
 #include <vector>
 #include <exception>
 #include <stdexcept>
+#include <sstream>
 
 #include <glibmm/timer.h>
 #include <pbd/pthread_utils.h>
@@ -368,6 +369,20 @@ AudioEngine::process_callback (nframes_t nframes)
                last_monitor_check = next_processed_frames;
        }
 
+       if (session->silent()) {
+
+               boost::shared_ptr<Ports> p = ports.reader();
+
+               for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
+                       
+                       Port *port = (*i);
+                       
+                       if (port->sends_output()) {
+                               port->get_buffer().silence(nframes);
+                       }
+               }
+       }
+
        _processed_frames = next_processed_frames;
        return 0;
 }
@@ -510,6 +525,26 @@ AudioEngine::remove_session ()
        remove_all_ports ();
 }
 
+void
+AudioEngine::port_registration_failure (const std::string& portname)
+{
+       string full_portname = jack_client_name;
+       full_portname += ':';
+       full_portname += portname;
+       
+       
+       jack_port_t* p = jack_port_by_name (_jack, full_portname.c_str());
+       string reason;
+       
+       if (p) {
+               reason = _("a port with this name already exists: check for duplicated track/bus names");
+       } else {
+               reason = _("unknown error");
+       }
+       
+       throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str());
+}      
+
 Port *
 AudioEngine::register_port (DataType dtype, const string& portname, bool input, bool publish)
 {
@@ -533,7 +568,7 @@ AudioEngine::register_port (DataType dtype, const string& portname, bool input,
        }
 
        catch (...) {
-               throw PortRegistrationFailure();
+               throw PortRegistrationFailure("unable to create port (unknown type?)");
        }
 }
 
@@ -563,7 +598,7 @@ AudioEngine::register_output_port (DataType type, const string& portname, bool p
        return register_port (type, portname, false, publish);
 }
 
-int          
+int
 AudioEngine::unregister_port (Port& port)
 {
        /* caller must hold process lock */
@@ -590,6 +625,8 @@ AudioEngine::unregister_port (Port& port)
                
                /* writer goes out of scope, forces update */
        }
+               
+       remove_connections_for (port);
 
        return 0;
 }
@@ -1054,6 +1091,23 @@ AudioEngine::remove_all_ports ()
        }
 }
 
+void
+AudioEngine::remove_connections_for (Port& port)
+{
+       for (PortConnections::iterator i = port_connections.begin(); i != port_connections.end(); ) {
+               PortConnections::iterator tmp;
+               
+               tmp = i;
+               ++tmp;
+               
+               if ((*i).first == port.name()) {
+                       port_connections.erase (i);
+               }
+
+               i = tmp;
+       }
+}
+
 
 #ifdef HAVE_JACK_CLIENT_OPEN
 
index 1284dd343bbe0fb127d5432ceb8115fc50d11989..81ad45e08a5fcb473f26ccb1bfeee40a8bf4a5da 100644 (file)
@@ -135,18 +135,15 @@ AudioFileSource::removable () const
 int
 AudioFileSource::init (ustring pathstr, bool must_exist)
 {
-       bool is_new = false;
-
        _length = 0;
        timeline_position = 0;
        _peaks_built = false;
-       file_is_new = false;
 
-       if (!find (pathstr, must_exist, is_new, _channel)) {
+       if (!find (pathstr, must_exist, file_is_new, _channel)) {
                throw non_existent_source ();
        }
 
-       if (is_new && must_exist) {
+       if (file_is_new && must_exist) {
                return -1;
        }
 
index 8034f3ddacf5963b4517fca7c4407583b62424d2..301351fe719d2246ba4ce23eb5076d668b47725b 100644 (file)
@@ -237,54 +237,6 @@ AudioRegion::listen_to_my_curves ()
        _fade_out->StateChanged.connect (mem_fun (*this, &AudioRegion::fade_out_changed));
 }
 
-bool
-AudioRegion::verify_length (nframes_t len)
-{
-       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(source());
-
-       if (afs && afs->destructive()) {
-               return true;
-       } else {
-               return Region::verify_length(len);
-       }
-}
-
-bool
-AudioRegion::verify_start_and_length (nframes_t new_start, nframes_t new_length)
-{
-       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(source());
-
-       if (afs && afs->destructive()) {
-               return true;
-       } else {
-               return Region::verify_start_and_length(new_start, new_length);
-       }
-}
-
-bool
-AudioRegion::verify_start (nframes_t pos)
-{
-       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(source());
-
-       if (afs && afs->destructive()) {
-               return true;
-       } else {
-               return Region::verify_start(pos);
-       }
-}
-
-bool
-AudioRegion::verify_start_mutable (nframes_t& new_start)
-{
-       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(source());
-
-       if (afs && afs->destructive()) {
-               return true;
-       } else {
-               return Region::verify_start_mutable(new_start);
-       }
-}
-
 void
 AudioRegion::set_envelope_active (bool yn)
 {
@@ -321,25 +273,26 @@ AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nfra
        }
 }
 
-ARDOUR::nframes_t
-AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t position, nframes_t cnt, uint32_t chan_n) const
+nframes_t
+AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t position, 
+                     nframes_t cnt, 
+                     uint32_t chan_n, nframes_t read_frames, nframes_t skip_frames) const
 {
-       return _read_at (_sources, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n);
+       return _read_at (_sources, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, read_frames, skip_frames);
 }
 
-ARDOUR::nframes_t
+nframes_t
 AudioRegion::master_read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t position, 
                             nframes_t cnt, uint32_t chan_n) const
 {
-       return _read_at (_master_sources, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n);
+       return _read_at (_master_sources, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, 0, 0);
 }
 
-ARDOUR::nframes_t
+nframes_t
 AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
-                      nframes_t position, nframes_t cnt, uint32_t chan_n) const
+                      nframes_t position, nframes_t cnt, 
+                      uint32_t chan_n, nframes_t read_frames, nframes_t skip_frames) const
 {
-       // cerr << _name << "._read_at(" << position << ") - " << _position << endl;
-
        nframes_t internal_offset;
        nframes_t buf_offset;
        nframes_t to_read;
@@ -377,13 +330,12 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
        _read_data_count = 0;
 
        if (chan_n < n_channels()) {
-               
+
                boost::shared_ptr<AudioSource> src = audio_source(chan_n);
                if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) {
-
                        return 0; /* "read nothing" */
                }
-
+               
                _read_data_count += src->read_data_count();
 
        } else {
index a2ce7209f6f634e0802b71f69b4dd2d0e6cd8071..ce8aa95964fa5a1916f25c3032aa39b13b8cc437 100644 (file)
@@ -49,6 +49,8 @@ using Glib::ustring;
 bool AudioSource::_build_missing_peakfiles = false;
 bool AudioSource::_build_peakfiles = false;
 
+#define _FPP 256
+
 AudioSource::AudioSource (Session& s, ustring name)
        : Source (s, name, DataType::AUDIO)
 {
@@ -135,7 +137,7 @@ AudioSource::peaks_ready (sigc::slot<void> the_slot, sigc::connection& conn) con
        /* check to see if the peak data is ready. if not
           connect the slot while still holding the lock.
        */
-       
+
        if (!(ret = _peaks_built)) {
                conn = PeaksReady.connect (the_slot);
        }
@@ -192,44 +194,36 @@ AudioSource::initialize_peakfile (bool newfile, ustring audio_path)
                peakpath = find_broken_peakfile (peakpath, audio_path);
        }
 
-       if (newfile) {
-
-               if (!_build_peakfiles) {
-                       return 0;
+       if (stat (peakpath.c_str(), &statbuf)) {
+               if (errno != ENOENT) {
+                       /* it exists in the peaks dir, but there is some kind of error */
+                       
+                       error << string_compose(_("AudioSource: cannot stat peakfile \"%1\""), peakpath) << endmsg;
+                       return -1;
                }
 
+               /* peakfile does not exist */
+               
                _peaks_built = false;
-
+               
        } else {
-
-               if (stat (peakpath.c_str(), &statbuf)) {
-                       if (errno != ENOENT) {
-                               /* it exists in the peaks dir, but there is some kind of error */
-                               
-                               error << string_compose(_("AudioSource: cannot stat peakfile \"%1\""), peakpath) << endmsg;
-                               return -1;
-                       }
-                       
+               
+               /* we found it in the peaks dir, so check it out */
+               
+               if (statbuf.st_size == 0) {
+                       // empty
                        _peaks_built = false;
-
                } else {
+                       // Check if the audio file has changed since the peakfile was built.
+                       struct stat stat_file;
+                       int err = stat (audio_path.c_str(), &stat_file);
                        
-                       /* we found it in the peaks dir, so check it out */
-
-                       if (statbuf.st_size == 0) {
+                       if (!err && stat_file.st_mtime > statbuf.st_mtime){
                                _peaks_built = false;
+                               _peak_byte_max = 0;
                        } else {
-                               // Check if the audio file has changed since the peakfile was built.
-                               struct stat stat_file;
-                               int err = stat (audio_path.c_str(), &stat_file);
-                               
-                               if (!err && stat_file.st_mtime > statbuf.st_mtime){
-                                       _peaks_built = false;
-                                       _peak_byte_max = 0;
-                               } else {
-                                       _peaks_built = true;
-                                       _peak_byte_max = statbuf.st_size;
-                               }
+                               _peaks_built = true;
+                               _peak_byte_max = statbuf.st_size;
                        }
                }
        }
@@ -255,8 +249,15 @@ AudioSource::write (Sample *dst, nframes_t cnt)
        return write_unlocked (dst, cnt);
 }
 
-int 
+int
 AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, double samples_per_visual_peak) const
+{
+       return read_peaks_with_fpp (peaks, npeaks, start, cnt, samples_per_visual_peak, _FPP);
+}
+
+int 
+AudioSource::read_peaks_with_fpp (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, 
+                                 double samples_per_visual_peak, nframes_t samples_per_file_peak) const
 {
        Glib::Mutex::Lock lm (_lock);
        double scale;
@@ -271,7 +272,7 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
        Sample* raw_staging = 0;
        int _peakfile = -1;
 
-       expected_peaks = (cnt / (double) frames_per_peak);
+       expected_peaks = (cnt / (double) samples_per_file_peak);
        scale = npeaks/expected_peaks;
 
 #undef DEBUG_READ_PEAKS
@@ -326,7 +327,7 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
 
        if (scale == 1.0) {
 
-               off_t first_peak_byte = (start / frames_per_peak) * sizeof (PeakData);
+               off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
 
                /* open, read, close */
 
@@ -390,10 +391,10 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
                /* compute the rounded up frame position  */
        
                nframes_t current_frame = start;
-               nframes_t current_stored_peak = (nframes_t) ceil (current_frame / (double) frames_per_peak);
+               nframes_t current_stored_peak = (nframes_t) ceil (current_frame / (double) samples_per_file_peak);
                uint32_t       next_visual_peak  = (uint32_t) ceil (current_frame / samples_per_visual_peak);
                double         next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
-               uint32_t       stored_peak_before_next_visual_peak = (nframes_t) next_visual_peak_frame / frames_per_peak;
+               uint32_t       stored_peak_before_next_visual_peak = (nframes_t) next_visual_peak_frame / samples_per_file_peak;
                uint32_t       nvisual_peaks = 0;
                uint32_t       stored_peaks_read = 0;
                uint32_t       i = 0;
@@ -414,7 +415,7 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
                        if (i == stored_peaks_read) {
 
                                uint32_t       start_byte = current_stored_peak * sizeof(PeakData);
-                               tnp = min ((_length/frames_per_peak - current_stored_peak), (nframes_t) expected_peaks);
+                               tnp = min ((_length/samples_per_file_peak - current_stored_peak), (nframes_t) expected_peaks);
                                to_read = min (chunksize, tnp);
                                
 #ifdef DEBUG_READ_PEAKS
@@ -437,7 +438,7 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
                                             << ')'
                                             << " at start_byte = " << start_byte 
                                             << " _length = " << _length << " versus len = " << fend
-                                            << " expected maxpeaks = " << (_length - current_frame)/frames_per_peak
+                                            << " expected maxpeaks = " << (_length - current_frame)/samples_per_file_peak
                                             << " npeaks was " << npeaks
                                             << endl;
                                        goto out;
@@ -466,7 +467,7 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
 
                        //next_visual_peak_frame = min ((next_visual_peak * samples_per_visual_peak), (next_visual_peak_frame+samples_per_visual_peak) );
                        next_visual_peak_frame =  min ((double) start+cnt, (next_visual_peak_frame+samples_per_visual_peak) );
-                       stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / frames_per_peak; 
+                       stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak; 
                }
 
                if (zero_fill) {
@@ -611,7 +612,7 @@ AudioSource::build_peaks_from_scratch ()
                                goto out;
                        }
 
-                       if (compute_and_write_peaks (buf, current_frame, frames_read, true, false)) {
+                       if (compute_and_write_peaks (buf, current_frame, frames_read, true, false, _FPP)) {
                                break;
                        }
                        
@@ -662,7 +663,7 @@ void
 AudioSource::done_with_peakfile_writes (bool done)
 {
        if (peak_leftover_cnt) {
-               compute_and_write_peaks (0, 0, 0, true, false);
+               compute_and_write_peaks (0, 0, 0, true, false, _FPP);
        }
        
        if (done) {
@@ -677,6 +678,13 @@ AudioSource::done_with_peakfile_writes (bool done)
 
 int
 AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframes_t cnt, bool force, bool intermediate_peaks_ready)
+{
+       return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
+}
+
+int
+AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframes_t cnt, bool force, 
+                                     bool intermediate_peaks_ready, nframes_t fpp)
 {
        Sample* buf2 = 0;
        nframes_t to_do;
@@ -707,9 +715,7 @@ AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframe
                        x.min = peak_leftovers[0];
                        x.max = peak_leftovers[0];
 
-                       ARDOUR::find_peaks (peak_leftovers + 1, peak_leftover_cnt - 1, &x.min, &x.max);
-
-                       off_t byte = (peak_leftover_frame / frames_per_peak) * sizeof (PeakData);
+                       off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
 
                        if (::pwrite (peakfile, &x, sizeof (PeakData), byte) != sizeof (PeakData)) {
                                error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
@@ -761,7 +767,7 @@ AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframe
                to_do = cnt;
        }
 
-       peakbuf = new PeakData[(to_do/frames_per_peak)+1];
+       peakbuf = new PeakData[(to_do/fpp)+1];
        peaks_computed = 0;
        current_frame = first_frame;
        frames_done = 0;
@@ -769,11 +775,11 @@ AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframe
        while (to_do) {
 
                /* if some frames were passed in (i.e. we're not flushing leftovers)
-                  and there are less than frames_per_peak to do, save them till
+                  and there are less than fpp to do, save them till
                   next time
                */
 
-               if (force && (to_do < frames_per_peak)) {
+               if (force && (to_do < fpp)) {
                        /* keep the left overs around for next time */
 
                        if (peak_leftover_size < to_do) {
@@ -790,7 +796,7 @@ AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframe
                        break;
                }
                        
-               nframes_t this_time = min (frames_per_peak, to_do);
+               nframes_t this_time = min (fpp, to_do);
 
                peakbuf[peaks_computed].max = buf[0];
                peakbuf[peaks_computed].min = buf[0];
@@ -804,7 +810,7 @@ AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframe
                current_frame += this_time;
        }
                
-       first_peak_byte = (first_frame / frames_per_peak) * sizeof (PeakData);
+       first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
 
        if (can_truncate_peaks()) {
 
@@ -887,7 +893,7 @@ AudioSource::available_peaks (double zoom_factor) const
 {
        off_t end;
 
-       if (zoom_factor < frames_per_peak) {
+       if (zoom_factor < _FPP) {
                return length(); // peak data will come from the audio file
        } 
        
@@ -899,7 +905,7 @@ AudioSource::available_peaks (double zoom_factor) const
 
        end = _peak_byte_max;
 
-       return (end/sizeof(PeakData)) * frames_per_peak;
+       return (end/sizeof(PeakData)) * _FPP;
 }
 
 void
index 6085501470a581fc2a13fd54cd99040a766a73e7..d6f63c2f9da410183e4e180672016ef4d9cec87d 100644 (file)
@@ -151,8 +151,19 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
        reset_panner();
 
        length = the_region->length();
-       _diskstream->seek (0);
-       current_frame = 0;
+
+       int dir;
+       nframes_t offset = the_region->sync_offset (dir);
+
+       /* can't audition from a negative sync point */
+
+       if (dir < 0) {
+               offset = 0;
+       }
+
+       _diskstream->seek (offset);
+       current_frame = offset;
+
        g_atomic_int_set (&_active, 1);
 }
 
index 508e6515c9f9375df5bcdcb79d621134c41d9709..f7711b32241372475aaff368c07e4acd2136f562 100644 (file)
@@ -260,7 +260,8 @@ Crossfade::read_raw_internal (Sample* buf, nframes_t start, nframes_t cnt) const
 
 nframes_t 
 Crossfade::read_at (Sample *buf, Sample *mixdown_buffer, 
-                   float *gain_buffer, nframes_t start, nframes_t cnt, uint32_t chan_n) const
+                   float *gain_buffer, nframes_t start, nframes_t cnt, uint32_t chan_n,
+                   nframes_t read_frames, nframes_t skip_frames) const
 {
        nframes_t offset;
        nframes_t to_write;
@@ -301,9 +302,9 @@ Crossfade::read_at (Sample *buf, Sample *mixdown_buffer,
        } else if (!(_in->opaque())) {
                memset (crossfade_buffer_in, 0, sizeof (Sample) * to_write);
        }
-       
-       _out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, start, to_write, chan_n);
-       _in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, start, to_write, chan_n);
+
+       _out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
+       _in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, start, to_write, chan_n, read_frames, skip_frames);
 
        float* fiv = new float[to_write];
        float* fov = new float[to_write];
index f2d2e92169d9d4d03ee67258c3ab48f519dcf8e5..9f2ce4fab9e6275e1b78aa38e47e614d29c4b9fc 100644 (file)
@@ -164,7 +164,6 @@ setup_enum_writer ()
        REGISTER_ENUM (SyncPoint);      
        REGISTER (_RegionPoint);
 
-
        REGISTER_ENUM (PreFader);
        REGISTER_ENUM (PostFader);
        REGISTER (_Placement);
@@ -243,6 +242,7 @@ setup_enum_writer ()
        REGISTER_CLASS_ENUM (Session::Event, SetDiskstreamSpeed);
        REGISTER_CLASS_ENUM (Session::Event, Locate);
        REGISTER_CLASS_ENUM (Session::Event, LocateRoll);
+       REGISTER_CLASS_ENUM (Session::Event, LocateRollLocate);
        REGISTER_CLASS_ENUM (Session::Event, SetLoop);
        REGISTER_CLASS_ENUM (Session::Event, PunchIn);
        REGISTER_CLASS_ENUM (Session::Event, PunchOut);
index a8fb4050f92a8b291c0135d19eebbf36b3ef1fb3..91e5b9850c0bf176069136574e2e1a0e4925e78c 100644 (file)
 #include <boost/scoped_array.hpp>
 #include <boost/shared_array.hpp>
 
+#include <pbd/basename.h>
 #include <pbd/convert.h>
 
 #include <ardour/ardour.h>
 #include <ardour/session.h>
-#include <ardour/session_directory.h>
 #include <ardour/audio_diskstream.h>
 #include <ardour/sndfilesource.h>
 #include <ardour/sndfile_helpers.h>
 using namespace ARDOUR;
 using namespace PBD;
 
-std::auto_ptr<ImportableSource>
-open_importable_source (const string& path, nframes_t samplerate,
-               ARDOUR::SrcQuality quality)
+static std::auto_ptr<ImportableSource>
+open_importable_source (const string& path, nframes_t samplerate, ARDOUR::SrcQuality quality)
 {
        std::auto_ptr<ImportableSource> source(new ImportableSource(path));
 
        if (source->samplerate() == samplerate) {
                return source;
        }
-
-       return std::auto_ptr<ImportableSource>(
-                       new ResampledImportableSource(path, samplerate, quality)
-                       );
+       
+       return std::auto_ptr<ImportableSource>(new ResampledImportableSource(path, samplerate, quality));
 }
 
-std::string
+static std::string
 get_non_existent_filename (const std::string& basename, uint channel, uint channels)
 {
        char buf[PATH_MAX+1];
@@ -86,8 +83,8 @@ get_non_existent_filename (const std::string& basename, uint channel, uint chann
                } else {
                        snprintf (buf, sizeof(buf), "%s.wav", base.c_str());
                }
-
-               if (sys::exists (buf)) {
+               
+               if (Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
 
                        /* if the file already exists, we must come up with
                         *  a new name for it.  for now we just keep appending
@@ -106,27 +103,27 @@ get_non_existent_filename (const std::string& basename, uint channel, uint chann
        return buf;
 }
 
-vector<string>
-get_paths_for_new_sources (const string& import_file_path, const string& session_dir, 
-               uint channels)
+static vector<string>
+get_paths_for_new_sources (const string& import_file_path, const string& session_dir, uint channels)
 {
        vector<string> new_paths;
-       const string basename = sys::basename (import_file_path);
-       SessionDirectory sdir(session_dir);
+       const string basename = basename_nosuffix (import_file_path);
 
        for (uint n = 0; n < channels; ++n) {
 
-               std::string filename = get_non_existent_filename (basename, n, channels); 
+               std::string filepath;
 
-               sys::path filepath = sdir.sound_path() / filename;
+               filepath = session_dir;
+               filepath += '/';
+               filepath += get_non_existent_filename (basename, n, channels); 
 
-               new_paths.push_back (filepath.to_string());
+               new_paths.push_back (filepath);
        }
 
        return new_paths;
 }
 
-bool
+static bool
 create_mono_sources_for_writing (const vector<string>& new_paths, Session& sess,
                uint samplerate, vector<boost::shared_ptr<AudioFileSource> >& newfiles)
 {
@@ -138,12 +135,12 @@ create_mono_sources_for_writing (const vector<string>& new_paths, Session& sess,
                try
                {
                        source = SourceFactory::createWritable (
-                                       DataType::AUDIO,
-                                       sess,
-                                       i->c_str(),
-                                       false, // destructive
-                                       samplerate
-                                       );
+                               DataType::AUDIO,
+                               sess,
+                               i->c_str(),
+                               false, // destructive
+                               samplerate
+                               );
                }
                catch (const failed_constructor& err)
                {
@@ -156,29 +153,29 @@ create_mono_sources_for_writing (const vector<string>& new_paths, Session& sess,
        return true;
 }
 
-Glib::ustring
+static Glib::ustring
 compose_status_message (const string& path,
-               uint file_samplerate,
-               uint session_samplerate,
-               uint current_file,
-               uint total_files)
+                       uint file_samplerate,
+                       uint session_samplerate,
+                       uint current_file,
+                       uint total_files)
 {
        if (file_samplerate != session_samplerate) {
                return string_compose (_("converting %1\n(resample from %2KHz to %3KHz)\n(%4 of %5)"),
-                               sys::path(path).leaf(),
-                               file_samplerate/1000.0f,
-                               session_samplerate/1000.0f,
-                               current_file, total_files);
+                                      Glib::path_get_basename (path),
+                                      file_samplerate/1000.0f,
+                                      session_samplerate/1000.0f,
+                                      current_file, total_files);
        }
 
        return  string_compose (_("converting %1\n(%2 of %3)"), 
-                       sys::path(path).leaf(),
-                       current_file, total_files);
+                               Glib::path_get_basename (path),
+                               current_file, total_files);
 }
 
-void
+static void
 write_audio_data_to_new_files (ImportableSource* source, Session::import_status& status,
-               vector<boost::shared_ptr<AudioFileSource> >& newfiles)
+                              vector<boost::shared_ptr<AudioFileSource> >& newfiles)
 {
        const nframes_t nframes = ResampledImportableSource::blocksize;
        uint channels = source->channels();
@@ -225,10 +222,10 @@ write_audio_data_to_new_files (ImportableSource* source, Session::import_status&
        }
 }
 
-void
+static void
 remove_file_source (boost::shared_ptr<AudioFileSource> file_source)
 {
-       sys::remove (std::string(file_source->path()));
+       ::unlink (file_source->path().c_str());
 }
 
 void
@@ -260,7 +257,7 @@ Session::import_audiofiles (import_status& status)
                vector<string> new_paths = get_paths_for_new_sources (*p,
                                get_best_session_directory_for_new_source (),
                                source->channels());
-
+               
                AudioSources newfiles;
 
                status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles);
@@ -309,3 +306,4 @@ Session::import_audiofiles (import_status& status)
 
        status.done = true;
 }
+
index 89c342e9cf6064c1e13f61153b5bb28611009f69..7a2ae2aad9f537c28b62836b01c45bb0b904dd5b 100644 (file)
@@ -307,12 +307,12 @@ void
 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
 {
        assert(outs.available() >= n_inputs());
-
-       outs.set_count(n_inputs());
        
-       if (outs.count() == ChanCount::ZERO)
+       if (n_inputs() == ChanCount::ZERO)
                return;
 
+       outs.set_count(n_inputs());
+       
        for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
                
                BufferSet::iterator o = outs.begin(*t);
@@ -2567,3 +2567,4 @@ IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
                sigc::mem_fun (*io, &IO::bundle_ports_have_changed)
                );
 }
+
index 3a0b34ab195a5e95d2f15fec781e3d2c016da49a..b2ddb6d48e3d1d4b5c03623f8176af00226c6a68 100644 (file)
@@ -29,10 +29,14 @@ JackAudioPort::JackAudioPort (const std::string& name, Flags flgs, AudioBuffer*
 {
        if (buf) {
 
+               cout << "jack audio port buffer" << endl;
+
                _buffer = buf;
                _own_buffer = false;
 
        } else {
+               
+               cout << "jack audio port no buffer" << endl;
 
                /* data space will be provided by JACK */
 
index 7dbb8655f69745b2ce84aeeb702f5bd9c81ad0c0..c9471c9d0c49542227f1d9a5c75fbfc55166141c 100644 (file)
@@ -71,8 +71,8 @@ JackMidiPort::cycle_start (nframes_t nframes, nframes_t offset_ignored_but_proba
 
        assert(_buffer->size() == event_count);
 
-       if (_buffer->size() > 0)
-               cerr << "MIDIPort got " << event_count << " events." << endl;
+       /*if (_buffer->size() > 0)
+               cerr << "JackMIDIPort got " << event_count << " events (buf " << _buffer << ")" << endl;*/
 }
 
 void
index 0614e3334d1d171a5aa6ce7d07841d36a0b78337..696ada3b81faf8488f0efdc9e66b8253c9b30221 100644 (file)
@@ -185,6 +185,14 @@ LadspaPlugin::restore_state (PluginState& state)
        }
 }
 
+string
+LadspaPlugin::unique_id() const
+{
+       char buf[32];
+       snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
+       return string (buf);
+}
+
 float
 LadspaPlugin::default_value (uint32_t port)
 {
index d108374ba07d57e3f48e773ddc209a2a8a363b8e..f85fd3ec33a8d33fa3c72dc83bb244c817f791e5 100644 (file)
@@ -41,7 +41,7 @@ PeakMeter::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_f
 
        // Meter what we have (midi)
        for ( ; n < meterable && n < bufs.count().n_midi(); ++n) {
-               
+       
                float val = 0;
                
                // GUI needs a better MIDI meter, not much information can be
index a629fe458f4855e31354d81578fd2bacf85e1162..1ca6a5db7212b308d4add9e3af93170a403f843e 100644 (file)
@@ -104,21 +104,23 @@ void
 MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
 {
        assert(src.type() == DataType::MIDI);
-       const MidiBuffer& msrc = (MidiBuffer&)src;
+       assert(&src != this);
 
-       assert(_capacity >= src.size());
+       const MidiBuffer& msrc = (MidiBuffer&)src;
+       
+       assert(_capacity >= msrc.size());
 
        clear();
        assert(_size == 0);
-
+       
        // FIXME: slow
-       for (size_t i=0; i < src.size(); ++i) {
+       for (size_t i=0; i < msrc.size(); ++i) {
                const MidiEvent& ev = msrc[i];
                if (ev.time() >= offset && ev.time() < offset+nframes) {
-                       //cerr << "MidiBuffer::read_from got event, " << ev.time() << endl;
+                       //cout << "MidiBuffer::read_from got event, " << ev.time() << endl;
                        push_back(ev);
                } else {
-                       //cerr << "MidiBuffer event out of range, " << ev.time() << endl;
+                       cerr << "MidiBuffer event out of range, " << ev.time() << endl;
                }
        }
 
index 7590c42e0bbafcbaae63ed6a7f63326265d00447..3e8dea4f62a6df04f4a104af92bd3046fa116066 100644 (file)
 using namespace ARDOUR;
 using namespace std;
 
-MidiPort::MidiPort (const std::string& name, Flags flags, bool external, nframes_t bufsize)
+MidiPort::MidiPort (const std::string& name, Flags flags, bool external, nframes_t capacity)
        : Port (name, flags)
        , BaseMidiPort (name, flags)
        , PortFacade (name, flags)
 {
-       set_name (name);
-
-       _buffer = new MidiBuffer (bufsize);
+       _buffer = new MidiBuffer (capacity);
 
-       cout << "MIDI port "  << name << " external: " << external << endl;
-
-       if (!external) {
-               _ext_port = 0;
-       } else {
+       if (external) {
+               /* external ports use the same buffer for the jack port (_ext_port)
+                * and internal ports (this) */
                _ext_port = new JackMidiPort (name, flags, _buffer);
+       } else {
+               /* internal ports just have a single buffer, no jack port */
+               _ext_port = 0;
        }
 
+       set_name (name);
        reset ();
 }
 
@@ -70,7 +70,6 @@ MidiPort::cycle_start (nframes_t nframes, nframes_t offset)
        /* caller must hold process lock */
        
        if (_ext_port) {
-               // cout << "external\n";
                _ext_port->cycle_start (nframes, offset);
        }
        
@@ -78,11 +77,9 @@ MidiPort::cycle_start (nframes_t nframes, nframes_t offset)
                        
                if (_ext_port) {
                
-                       // cout << "external in\n";
-
-                       _buffer->read_from (dynamic_cast<BaseMidiPort*>(_ext_port)->get_midi_buffer(), nframes, offset);
-
-                       // cout << "read " << _buffer->size() << " events." << endl;
+                       BaseMidiPort* mprt = dynamic_cast<BaseMidiPort*>(_ext_port);
+                       assert(mprt);
+                       assert(&mprt->get_midi_buffer() == _buffer);
 
                        if (!_connections.empty()) {
                                (*_mixdown) (_connections, _buffer, nframes, offset, false);
@@ -90,8 +87,6 @@ MidiPort::cycle_start (nframes_t nframes, nframes_t offset)
 
                } else {
                
-                       // cout << "internal in\n";
-
                        if (_connections.empty()) {
                                _buffer->silence (nframes, offset);
                        } else {
@@ -101,10 +96,6 @@ MidiPort::cycle_start (nframes_t nframes, nframes_t offset)
 
        } else {
                        
-               // cout << "out\n";
-               
                _buffer->silence (nframes, offset);
        }
-
-       // cout << endl;
 }
index 8d20d8539d75417cb5bc6313f6629f76b6a9738b..04649a56fe5fb0409d2bc519a6ac647571fbd9ad 100644 (file)
@@ -30,6 +30,7 @@
 #include <pbd/failed_constructor.h>
 #include <pbd/stl_delete.h>
 #include <pbd/xml++.h>
+#include <pbd/stacktrace.h>
 
 #include <ardour/playlist.h>
 #include <ardour/session.h>
@@ -233,6 +234,7 @@ Playlist::init (bool hide)
        _refcnt = 0;
        _hidden = hide;
        _splicing = false;
+       _shuffling = false;
        _nudging = false;
        in_set_state = 0;
        _edit_mode = Config->get_edit_mode();
@@ -351,7 +353,7 @@ Playlist::notify_region_removed (boost::shared_ptr<Region> r)
                /* this might not be true, but we have to act
                   as though it could be.
                */
-               pending_length = false;
+               pending_length = false;
                LengthChanged (); /* EMIT SIGNAL */
                pending_modified = false;
                Modified (); /* EMIT SIGNAL */
@@ -439,7 +441,6 @@ Playlist::flush_notifications ()
 
        if (n || pending_modified) {
                if (!in_set_state) {
-                       possibly_splice ();
                        relayer ();
                }
                pending_modified = false;
@@ -479,12 +480,7 @@ Playlist::add_region (boost::shared_ptr<Region> region, nframes_t position, floa
                --itimes;
        }
        
-       /* later regions will all be spliced anyway */
        
-       if (!holding_state ()) {
-               possibly_splice_unlocked ();
-       }
-
        /* note that itimes can be zero if we being asked to just
           insert a single fraction of the region.
        */
@@ -495,14 +491,18 @@ Playlist::add_region (boost::shared_ptr<Region> region, nframes_t position, floa
                pos += region->length();
        }
        
+       nframes_t length = 0;
+
        if (floor (times) != times) {
-               nframes_t length = (nframes_t) floor (region->length() * (times - floor (times)));
+               length = (nframes_t) floor (region->length() * (times - floor (times)));
                string name;
                _session.region_name (name, region->name(), false);
                boost::shared_ptr<Region> sub = RegionFactory::create (region, 0, length, name, region->layer(), region->flags());
                add_region_internal (sub, pos);
        }
 
+
+       possibly_splice_unlocked (position, (pos + length) - position, boost::shared_ptr<Region>());
        release_notifications ();
 }
 
@@ -540,6 +540,8 @@ Playlist::add_region_internal (boost::shared_ptr<Region> region, nframes_t posit
        regions.insert (upper_bound (regions.begin(), regions.end(), region, cmp), region);
        all_regions.insert (region);
 
+       possibly_splice_unlocked (position, region->length(), region);
+
        if (!holding_state () && !in_set_state) {
                /* layers get assigned from XML state */
                relayer ();
@@ -565,12 +567,15 @@ Playlist::replace_region (boost::shared_ptr<Region> old, boost::shared_ptr<Regio
 {
        RegionLock rlock (this);
 
+       bool old_sp = _splicing;
+       _splicing = true;
+
        remove_region_internal (old);
        add_region_internal (newr, pos);
 
-       if (!holding_state ()) {
-               possibly_splice_unlocked ();
-       }
+       _splicing = old_sp;
+
+       possibly_splice_unlocked (pos, (nframes64_t) old->length() - (nframes64_t) newr->length());
 }
 
 void
@@ -578,14 +583,10 @@ Playlist::remove_region (boost::shared_ptr<Region> region)
 {
        RegionLock rlock (this);
        remove_region_internal (region);
-
-       if (!holding_state ()) {
-               possibly_splice_unlocked ();
-       }
 }
 
 int
-Playlist::remove_region_internal (boost::shared_ptr<Region>region)
+Playlist::remove_region_internal (boost::shared_ptr<Region> region)
 {
        RegionList::iterator i;
        nframes_t old_length = 0;
@@ -602,8 +603,13 @@ Playlist::remove_region_internal (boost::shared_ptr<Region>region)
        for (i = regions.begin(); i != regions.end(); ++i) {
                if (*i == region) {
 
+                       nframes_t pos = (*i)->position();
+                       nframes64_t distance = (*i)->length();
+
                        regions.erase (i);
 
+                       possibly_splice_unlocked (pos, -distance);
+
                        if (!holding_state ()) {
                                relayer ();
                                remove_dependents (region);
@@ -617,6 +623,9 @@ Playlist::remove_region_internal (boost::shared_ptr<Region>region)
                        return 0;
                }
        }
+
+
+
        return -1;
 }
 
@@ -664,6 +673,7 @@ Playlist::partition (nframes_t start, nframes_t end, bool just_top_level)
 void
 Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, RegionList& thawlist)
 {
+       RegionLock rlock (this);
        boost::shared_ptr<Region> region;
        boost::shared_ptr<Region> current;
        string new_name;
@@ -671,19 +681,14 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
        OverlapType overlap;
        nframes_t pos1, pos2, pos3, pos4;
        RegionList new_regions;
-       RegionList copy;
 
        in_partition = true;
 
-       delay_notifications();
-
        /* need to work from a copy, because otherwise the regions we add during the process
           get operated on as well.
        */
-       {
-               RegionLock rlock (this);
-               copy = regions;
-       }
+
+       RegionList copy = regions;
 
        for (RegionList::iterator i = copy.begin(); i != copy.end(); i = tmp) {
                
@@ -691,10 +696,9 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                ++tmp;
 
                current = *i;
-
+               
                if (current->first_frame() == start && current->last_frame() == end) {
                        if (cutting) {
-                               RegionLock rlock (this);
                                remove_region_internal (current);
                        }
                        continue;
@@ -703,14 +707,14 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                if ((overlap = current->coverage (start, end)) == OverlapNone) {
                        continue;
                }
-
+               
                pos1 = current->position();
                pos2 = start;
                pos3 = end;
                pos4 = current->last_frame();
 
                if (overlap == OverlapInternal) {
-
+                       
                        /* split: we need 3 new regions, the front, middle and end.
                           cut:   we need 2 regions, the front and end.
                        */
@@ -730,10 +734,9 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                                
                                /* "middle" ++++++ */
                                
-                               _session.region_name (new_name, current->name(), false); //takes the session-wide region lock
+                               _session.region_name (new_name, current->name(), false);
                                region = RegionFactory::create (current, pos2 - pos1, pos3 - pos2, new_name,
                                                       regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::LeftOfSplit|Region::RightOfSplit));
-                               RegionLock rlock (this);
                                add_region_internal (region, start);
                                new_regions.push_back (region);
                        }
@@ -743,11 +746,10 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                        _session.region_name (new_name, current->name(), false);
                        region = RegionFactory::create (current, pos3 - pos1, pos4 - pos3, new_name, 
                                               regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit));
-                       {
-                               RegionLock rlock (this);
-                               add_region_internal (region, end);
-                               new_regions.push_back (region);
-                       }
+
+                       add_region_internal (region, end);
+                       new_regions.push_back (region);
+
                        /* "front" ***** */
                                
                        current->freeze ();
@@ -772,9 +774,8 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                                /* end +++++ */
                                
                                _session.region_name (new_name, current->name(), false);
-                               region = RegionFactory::create (current, pos2 - pos1, pos4 - pos2, new_name, regions.size(),
+                               region = RegionFactory::create (current, pos2 - pos1, pos4 - pos2, new_name, (layer_t) regions.size(),
                                                       Region::Flag(current->flags()|Region::Automatic|Region::LeftOfSplit));
-                               RegionLock rlock (this);
                                add_region_internal (region, start);
                                new_regions.push_back (region);
                        }
@@ -809,7 +810,6 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                                 _session.region_name (new_name, current->name(), false);
                                 region = RegionFactory::create (current, 0, pos3 - pos1, new_name,
                                                        regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit));
-                                RegionLock rlock (this);
                                 add_region_internal (region, pos1);
                                 new_regions.push_back (region);
                        } 
@@ -839,7 +839,6 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                        */
 
                        if (cutting) {
-                               RegionLock rlock (this);
                                remove_region_internal (current);
                        }
                        new_regions.push_back (current);
@@ -851,8 +850,6 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
        for (RegionList::iterator i = new_regions.begin(); i != new_regions.end(); ++i) {
                check_dependents (*i, false);
        }
-
-       release_notifications ();
 }
 
 boost::shared_ptr<Playlist>
@@ -919,7 +916,6 @@ Playlist::cut (nframes_t start, nframes_t cnt, bool result_is_hidden)
        }
 
        partition_internal (start, start+cnt-1, true, thawlist);
-       possibly_splice ();
 
        for (RegionList::iterator i = thawlist.begin(); i != thawlist.end(); ++i) {
                (*i)->thaw ("playlist cut");
@@ -973,7 +969,6 @@ Playlist::paste (boost::shared_ptr<Playlist> other, nframes_t position, float ti
                        pos += shift;
                }
 
-               possibly_splice_unlocked ();
 
                /* XXX shall we handle fractional cases at some point? */
 
@@ -1033,10 +1028,14 @@ Playlist::split_region (boost::shared_ptr<Region> region, nframes_t playlist_pos
        string before_name;
        string after_name;
 
+       /* split doesn't change anything about length, so don't try to splice */
+       
+       bool old_sp = _splicing;
+       _splicing = true;
+
        before = playlist_position - region->position();
        after = region->length() - before;
        
-       
        _session.region_name (before_name, region->name(), false);
        left = RegionFactory::create (region, 0, before, before_name, region->layer(), Region::Flag (region->flags()|Region::LeftOfSplit));
 
@@ -1045,7 +1044,7 @@ Playlist::split_region (boost::shared_ptr<Region> region, nframes_t playlist_pos
 
        add_region_internal (left, region->position());
        add_region_internal (right, region->position() + before);
-       
+
        uint64_t orig_layer_op = region->last_layer_op();
        for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
                if ((*i)->last_layer_op() > orig_layer_op) {
@@ -1060,71 +1059,84 @@ Playlist::split_region (boost::shared_ptr<Region> region, nframes_t playlist_pos
 
        finalize_split_region (region, left, right);
        
-       if (remove_region_internal (region)) {
-               return;
-       }
+       remove_region_internal (region);
+
+       _splicing = old_sp;
 }
 
 void
-Playlist::possibly_splice ()
+Playlist::possibly_splice (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude)
 {
+       if (_splicing || in_set_state) {
+               /* don't respond to splicing moves or state setting */
+               return;
+       }
+
        if (_edit_mode == Splice) {
-               splice_locked ();
+               splice_locked (at, distance, exclude);
        }
 }
 
 void
-Playlist::possibly_splice_unlocked ()
+Playlist::possibly_splice_unlocked (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude)
 {
+       if (_splicing || in_set_state) {
+               /* don't respond to splicing moves or state setting */
+               return;
+       }
+
        if (_edit_mode == Splice) {
-               splice_unlocked ();
+               splice_unlocked (at, distance, exclude);
        }
 }
 
 void
-Playlist::splice_locked ()
+Playlist::splice_locked (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude)
 {
        {
                RegionLock rl (this);
-               core_splice ();
+               core_splice (at, distance, exclude);
        }
-
-       notify_length_changed ();
 }
 
 void
-Playlist::splice_unlocked ()
+Playlist::splice_unlocked (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude)
 {
-       core_splice ();
-       notify_length_changed ();
+       core_splice (at, distance, exclude);
 }
 
 void
-Playlist::core_splice ()
+Playlist::core_splice (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude)
 {
        _splicing = true;
-       
+
        for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
-               
-               RegionList::iterator next;
-               
-               next = i;
-               ++next;
-               
-               if (next == regions.end()) {
-                       break;
+
+               if (exclude && (*i) == exclude) {
+                       continue;
+               }
+
+               if ((*i)->position() >= at) {
+                       nframes64_t new_pos = (*i)->position() + distance;
+                       if (new_pos < 0) {
+                               new_pos = 0;
+                       } else if (new_pos >= max_frames - (*i)->length()) {
+                               new_pos = max_frames - (*i)->length();
+                       } 
+                               
+                       (*i)->set_position (new_pos, this);
                }
-               
-               (*next)->set_position ((*i)->last_frame() + 1, this);
        }
-       
+
        _splicing = false;
+
+       notify_length_changed ();
 }
 
 void
 Playlist::region_bounds_changed (Change what_changed, boost::shared_ptr<Region> region)
 {
-       if (in_set_state || _splicing || _nudging) {
+       if (in_set_state || _splicing || _nudging || _shuffling) {
                return;
        }
 
@@ -1147,10 +1159,24 @@ Playlist::region_bounds_changed (Change what_changed, boost::shared_ptr<Region>
 
                regions.erase (i);
                regions.insert (upper_bound (regions.begin(), regions.end(), region, cmp), region);
-
        }
 
        if (what_changed & Change (ARDOUR::PositionChanged|ARDOUR::LengthChanged)) {
+               
+               nframes64_t delta = 0;
+               
+               if (what_changed & ARDOUR::PositionChanged) {
+                       delta = (nframes64_t) region->position() - (nframes64_t) region->last_position();
+               } 
+               
+               if (what_changed & ARDOUR::LengthChanged) {
+                       delta += (nframes64_t) region->length() - (nframes64_t) region->last_length();
+               } 
+
+               if (delta) {
+                       possibly_splice (region->last_position() + region->last_length(), delta, region);
+               }
+
                if (holding_state ()) {
                        pending_bounds.push_back (region);
                } else {
@@ -1159,7 +1185,6 @@ Playlist::region_bounds_changed (Change what_changed, boost::shared_ptr<Region>
                                timestamp_layer_op (region);
                        }
                        
-                       possibly_splice ();
                        notify_length_changed ();
                        relayer ();
                        check_dependents (region, false);
@@ -1269,9 +1294,114 @@ Playlist::top_region_at (nframes_t frame)
        return region;
 }      
 
+Playlist::RegionList*
+Playlist::regions_to_read (nframes_t start, nframes_t end)
+{
+       /* Caller must hold lock */
+
+       RegionList covering;
+       set<nframes_t> to_check;
+       set<boost::shared_ptr<Region> > unique;
+       RegionList here;
+
+       to_check.insert (start);
+       to_check.insert (end);
+
+       for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+
+               /* find all/any regions that span start+end */
+
+               switch ((*i)->coverage (start, end)) {
+               case OverlapNone:
+                       break;
+
+               case OverlapInternal:
+                       covering.push_back (*i);
+                       break;
+
+               case OverlapStart:
+                       to_check.insert ((*i)->position());
+                       covering.push_back (*i);
+                       break;
+
+               case OverlapEnd:
+                       to_check.insert ((*i)->last_frame());
+                       covering.push_back (*i);
+                       break;
+
+               case OverlapExternal:
+                       covering.push_back (*i);
+                       to_check.insert ((*i)->position());
+                       to_check.insert ((*i)->last_frame());
+                       break;
+               }
+
+               /* don't go too far */
+
+               if ((*i)->position() > end) {
+                       break;
+               }
+       }
+
+       RegionList* rlist = new RegionList;
+
+       /* find all the regions that cover each position .... */
+
+       if (covering.size() == 1) {
+
+               rlist->push_back (covering.front());
+               
+       } else {
+       
+               for (set<nframes_t>::iterator t = to_check.begin(); t != to_check.end(); ++t) {
+                       
+                       here.clear ();
+                       
+                       for (RegionList::iterator x = covering.begin(); x != covering.end(); ++x) {
+                       
+                               if ((*x)->covers (*t)) {
+                                       here.push_back (*x);
+                               }
+                       }
+                       
+                       RegionSortByLayer cmp;
+                       here.sort (cmp);
+                       
+                       /* ... and get the top/transparent regions at "here" */
+                       
+                       for (RegionList::reverse_iterator c = here.rbegin(); c != here.rend(); ++c) {
+                               
+                               unique.insert (*c);
+                               
+                               if ((*c)->opaque()) {
+                                       
+                                       /* the other regions at this position are hidden by this one */
+                                       
+                                       break;
+                               }
+                       }
+               }
+               
+               for (set<boost::shared_ptr<Region> >::iterator s = unique.begin(); s != unique.end(); ++s) {
+                       rlist->push_back (*s);
+               }
+
+               if (rlist->size() > 1) {
+                       /* now sort by time order */
+                       
+                       RegionSortByPosition cmp;
+                       rlist->sort (cmp);
+               }
+       }
+
+       return rlist;
+}
+
 Playlist::RegionList *
 Playlist::find_regions_at (nframes_t frame)
 {
+       /* Caller must hold lock */
+
        RegionList *rlist = new RegionList;
 
        for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
@@ -1352,6 +1482,92 @@ Playlist::find_next_region (nframes_t frame, RegionPoint point, int dir)
        return ret;
 }
 
+nframes64_t
+Playlist::find_next_region_boundary (nframes64_t frame, int dir)
+{
+       RegionLock rlock (this);
+
+       nframes64_t closest = max_frames;
+       nframes64_t ret = -1;
+
+       if (dir > 0) {
+
+               for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+                       
+                       boost::shared_ptr<Region> r = (*i);
+                       nframes64_t distance;
+                       nframes64_t end = r->position() + r->length();
+                       bool reset;
+
+                       reset = false;
+
+                       if (r->first_frame() > frame) {
+
+                               distance = r->first_frame() - frame;
+                               
+                               if (distance < closest) {
+                                       ret = r->first_frame();
+                                       closest = distance;
+                                       reset = true;
+                               }
+                       }
+
+                       if (end > frame) {
+                               
+                               distance = end - frame;
+                               
+                               if (distance < closest) {
+                                       ret = end;
+                                       closest = distance;
+                                       reset = true;
+                               }
+                       }
+
+                       if (reset) {
+                               break;
+                       }
+               }
+
+       } else {
+
+               for (RegionList::reverse_iterator i = regions.rbegin(); i != regions.rend(); ++i) {
+                       
+                       boost::shared_ptr<Region> r = (*i);
+                       nframes64_t distance;
+                       bool reset;
+
+                       reset = false;
+
+                       if (r->last_frame() < frame) {
+
+                               distance = frame - r->last_frame();
+                               
+                               if (distance < closest) {
+                                       ret = r->last_frame();
+                                       closest = distance;
+                                       reset = true;
+                               }
+                       }
+
+                       if (r->first_frame() < frame) {
+                               distance = frame - r->last_frame();
+                               
+                               if (distance < closest) {
+                                       ret = r->first_frame();
+                                       closest = distance;
+                                       reset = true;
+                               }
+                       }
+
+                       if (reset) {
+                               break;
+                       }
+               }
+       }
+
+       return ret;
+}
+
 /***********************************************************************/
 
 
@@ -1685,6 +1901,33 @@ Playlist::relayer ()
 
 /* XXX these layer functions are all deprecated */
 
+void
+Playlist::raise_region (boost::shared_ptr<Region> region)
+{
+       uint32_t rsz = regions.size();
+       layer_t target = region->layer() + 1U;
+
+       if (target >= rsz) {
+               /* its already at the effective top */
+               return;
+       }
+
+       move_region_to_layer (target, region, 1);
+}
+
+void
+Playlist::lower_region (boost::shared_ptr<Region> region)
+{
+       if (region->layer() == 0) {
+               /* its already at the bottom */
+               return;
+       }
+
+       layer_t target = region->layer() - 1U;
+
+       move_region_to_layer (target, region, -1);
+}
+
 void
 Playlist::raise_region_to_top (boost::shared_ptr<Region> region)
 {
@@ -1707,6 +1950,79 @@ Playlist::lower_region_to_bottom (boost::shared_ptr<Region> region)
        }
 }
 
+int
+Playlist::move_region_to_layer (layer_t target_layer, boost::shared_ptr<Region> region, int dir)
+{
+       RegionList::iterator i;
+       typedef pair<boost::shared_ptr<Region>,layer_t> LayerInfo;
+       list<LayerInfo> layerinfo;
+       layer_t dest;
+
+       {
+               RegionLock rlock (const_cast<Playlist *> (this));
+               
+               for (i = regions.begin(); i != regions.end(); ++i) {
+                       
+                       if (region == *i) {
+                               continue;
+                       }
+
+                       if (dir > 0) {
+
+                               /* region is moving up, move all regions on intermediate layers
+                                  down 1
+                               */
+                               
+                               if ((*i)->layer() > region->layer() && (*i)->layer() <= target_layer) {
+                                       dest = (*i)->layer() - 1;
+                               } else {
+                                       /* not affected */
+                                       continue;
+                               }
+                       } else {
+
+                               /* region is moving down, move all regions on intermediate layers
+                                  up 1
+                               */
+
+                               if ((*i)->layer() < region->layer() && (*i)->layer() >= target_layer) {
+                                       dest = (*i)->layer() + 1;
+                               } else {
+                                       /* not affected */
+                                       continue;
+                               }
+                       }
+
+                       LayerInfo newpair;
+                       
+                       newpair.first = *i;
+                       newpair.second = dest;
+                       
+                       layerinfo.push_back (newpair);
+               } 
+       }
+
+       /* now reset the layers without holding the region lock */
+
+       for (list<LayerInfo>::iterator x = layerinfo.begin(); x != layerinfo.end(); ++x) {
+               x->first->set_layer (x->second);
+       }
+
+       region->set_layer (target_layer);
+
+#if 0
+       /* now check all dependents */
+
+       for (list<LayerInfo>::iterator x = layerinfo.begin(); x != layerinfo.end(); ++x) {
+               check_dependents (x->first, false);
+       }
+       
+       check_dependents (region, false);
+#endif
+       
+       return 0;
+}
+
 void
 Playlist::nudge_after (nframes_t start, nframes_t distance, bool forwards)
 {
@@ -1817,3 +2133,129 @@ Playlist::timestamp_layer_op (boost::shared_ptr<Region> region)
        region->set_last_layer_op (++layer_op_counter);
 }
 
+
+void
+Playlist::shuffle (boost::shared_ptr<Region> region, int dir)
+{
+       bool moved = false;
+       nframes_t new_pos;
+
+       if (region->locked()) {
+               return;
+       }
+
+       _shuffling = true;
+
+       {
+               RegionLock rlock (const_cast<Playlist*> (this));
+               
+               
+               if (dir > 0) {
+                       
+                       RegionList::iterator next;
+
+                       for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {       
+                               if ((*i) == region) {
+                                       next = i;
+                                       ++next;
+
+                                       if (next != regions.end()) {
+
+                                               if ((*next)->locked()) {
+                                                       break;
+                                               }
+
+                                               if ((*next)->position() != region->last_frame() + 1) {
+                                                       /* they didn't used to touch, so after shuffle,
+                                                          just have them swap positions.
+                                                       */
+                                                       new_pos = (*next)->position();
+                                               } else {
+                                                       /* they used to touch, so after shuffle,
+                                                          make sure they still do. put the earlier
+                                                          region where the later one will end after
+                                                          it is moved.
+                                                       */
+                                                       new_pos = region->position() + (*next)->length();
+                                               }
+
+                                               (*next)->set_position (region->position(), this);
+                                               region->set_position (new_pos, this);
+
+                                               /* avoid a full sort */
+
+                                               regions.erase (i); // removes the region from the list */
+                                               next++;
+                                               regions.insert (next, region); // adds it back after next
+
+                                               moved = true;
+                                       }
+                                       break;
+                               }
+                       }
+               } else {
+                       
+                       RegionList::iterator prev = regions.end();
+                       
+                       for (RegionList::iterator i = regions.begin(); i != regions.end(); prev = i, ++i) {     
+                               if ((*i) == region) {
+
+                                       if (prev != regions.end()) {
+
+                                               if ((*prev)->locked()) {
+                                                       break;
+                                               }
+
+                                               if (region->position() != (*prev)->last_frame() + 1) {
+                                                       /* they didn't used to touch, so after shuffle,
+                                                          just have them swap positions.
+                                                       */
+                                                       new_pos = region->position();
+                                               } else {
+                                                       /* they used to touch, so after shuffle,
+                                                          make sure they still do. put the earlier
+                                                          one where the later one will end after
+                                                       */
+                                                       new_pos = (*prev)->position() + region->length();
+                                               }
+
+                                               region->set_position ((*prev)->position(), this);
+                                               (*prev)->set_position (new_pos, this);
+                                               
+                                               /* avoid a full sort */
+
+                                               regions.erase (i); // remove region
+                                               regions.insert (prev, region); // insert region before prev
+
+                                               moved = true;
+                                       }
+
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       _shuffling = false;
+
+       if (moved) {
+
+               relayer ();
+               check_dependents (region, false);
+               
+               notify_modified();
+       }
+
+}
+
+bool
+Playlist::region_is_shuffle_constrained (boost::shared_ptr<Region>) 
+{
+       RegionLock rlock (const_cast<Playlist*> (this));
+       
+       if (regions.size() > 1) {
+               return true;
+       }
+
+       return false;
+}
index bc5688c3189698f4ebc59029df4feb3e538efb69..7f3f21b1fea16ad564846125558cb4dab22b936b 100644 (file)
 #include <ardour/ladspa_plugin.h>
 #include <ardour/plugin_manager.h>
 
+#ifdef HAVE_AUDIOUNITS
+#include <ardour/audio_unit.h>
+#endif
+
 #include <pbd/stl_delete.h>
 
 #include "i18n.h"
@@ -66,7 +70,21 @@ vector<string>
 Plugin::get_presets()
 {
        vector<string> labels;
-       lrdf_uris* set_uris = lrdf_get_setting_uris(unique_id());
+       uint32_t id;
+       std::string unique (unique_id());
+
+       /* XXX problem: AU plugins don't have numeric ID's. 
+          Solution: they have a different method of providing presets.
+          XXX sub-problem: implement it.
+       */
+
+       if (!isdigit (unique[0])) {
+               return labels;
+       }
+
+       id = atol (unique.c_str());
+
+       lrdf_uris* set_uris = lrdf_get_setting_uris(id);
 
        if (set_uris) {
                for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) {
@@ -108,6 +126,20 @@ Plugin::save_preset (string name, string domain)
 {
        lrdf_portvalue portvalues[parameter_count()];
        lrdf_defaults defaults;
+       uint32_t id;
+       std::string unique (unique_id());
+
+       /* XXX problem: AU plugins don't have numeric ID's. 
+          Solution: they have a different method of providing/saving presets.
+          XXX sub-problem: implement it.
+       */
+
+       if (!isdigit (unique[0])) {
+               return false;
+       }
+
+       id = atol (unique.c_str());
+
        defaults.count = parameter_count();
        defaults.items = portvalues;
 
@@ -126,7 +158,7 @@ Plugin::save_preset (string name, string domain)
        
        string source(string_compose("file:%1/.%2/rdf/ardour-presets.n3", envvar, domain));
 
-       free(lrdf_add_preset(source.c_str(), name.c_str(), unique_id(), &defaults));
+       free(lrdf_add_preset(source.c_str(), name.c_str(), id,  &defaults));
 
        string path = string_compose("%1/.%2", envvar, domain);
        if (g_mkdir_with_parents (path.c_str(), 0775)) {
@@ -149,7 +181,7 @@ Plugin::save_preset (string name, string domain)
 }
 
 PluginPtr
-ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginType type)
+ARDOUR::find_plugin(Session& session, string identifier, PluginType type)
 {
        PluginManager *mgr = PluginManager::the_manager();
        PluginInfoList plugs;
@@ -162,14 +194,12 @@ ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginType ty
 #ifdef VST_SUPPORT
        case ARDOUR::VST:
                plugs = mgr->vst_plugin_info();
-               unique_id = 0; // VST plugins don't have a unique id.
                break;
 #endif
 
 #ifdef HAVE_AUDIOUNITS
        case ARDOUR::AudioUnit:
-               plugs = AUPluginInfo::discover ();
-               unique_id = 0; // Neither do AU.
+               plugs = mgr->au_plugin_info();
                break;
 #endif
 
@@ -178,10 +208,10 @@ ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginType ty
        }
 
        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);
+               if (identifier == (*i)->unique_id){
+                       return (*i)->load (session);
                }
        }
        
index 3faebd7179a8831863c39ae2365a3f7b10832c6e..4153f26e85606b4f81d94e5474db76e0c35724d7 100644 (file)
@@ -606,17 +606,10 @@ PluginInsert::get_state(void)
 XMLNode&
 PluginInsert::state (bool full)
 {
-       char buf[256];
        XMLNode& node = Processor::state (full);
 
        node.add_property ("type", _plugins[0]->state_node_name());
-       snprintf(buf, sizeof(buf), "%s", _plugins[0]->name());
-       node.add_property("id", string(buf));
-       if (_plugins[0]->state_node_name() == "ladspa") {
-               char buf[32];
-               snprintf (buf, sizeof (buf), "%ld", _plugins[0]->get_info()->unique_id); 
-               node.add_property("unique-id", string(buf));
-       }
+       node.add_property("unique-id", _plugins[0]->unique_id());
        node.add_property("count", string_compose("%1", _plugins.size()));
        node.add_child_nocopy (_plugins[0]->get_state());
 
@@ -648,7 +641,6 @@ PluginInsert::set_state(const XMLNode& node)
        XMLNodeIterator niter;
        XMLPropertyList plist;
        const XMLProperty *prop;
-       long unique = 0;
        ARDOUR::PluginType type;
 
        if ((prop = node.property ("type")) == 0) {
@@ -666,24 +658,16 @@ PluginInsert::set_state(const XMLNode& node)
                      << endmsg;
                return -1;
        }
-
+       
        prop = node.property ("unique-id");
-       if (prop != 0) {
-               unique = atol(prop->value().c_str());
-       }
-
-       if ((prop = node.property ("id")) == 0) {
-               error << _("XML node describing insert is missing the `id' field") << endmsg;
-               return -1;
+       if (prop == 0) {
+               error << _("Plugin has no unique ID field") << endmsg;
+               return -1;
        }
 
        boost::shared_ptr<Plugin> plugin;
        
-       if (unique != 0) {
-               plugin = find_plugin (_session, "", unique, type);      
-       } else {
-               plugin = find_plugin (_session, prop->value(), 0, type);        
-       }
+       plugin = find_plugin (_session, prop->value(), type);   
 
        if (plugin == 0) {
                error << string_compose(_("Found a reference to a plugin (\"%1\") that is unknown.\n"
index dac8a9eead4060f752df94daa4c69e4587a38ee0..d866a0d49fd7adfef656c0c1f6372b156b4ed076 100644 (file)
 #include <ardour/vst_plugin.h>
 #endif
 
+#ifdef HAVE_AUDIOUNITS
+#include <ardour/audio_unit.h>
+#endif
+
 #include <pbd/error.h>
 #include <pbd/stl_delete.h>
 
@@ -84,10 +88,23 @@ PluginManager::PluginManager ()
                vst_path = s;
        }
 
-       refresh ();
        if (_manager == 0) {
                _manager = this;
        }
+
+       /* the plugin manager is constructed too early to use Profile */
+
+       if (getenv ("ARDOUR_SAE")) {
+               ladspa_plugin_whitelist.push_back (1203); // single band parametric
+               ladspa_plugin_whitelist.push_back (1772); // caps compressor
+               ladspa_plugin_whitelist.push_back (1913); // fast lookahead limiter
+               ladspa_plugin_whitelist.push_back (1075); // simple RMS expander
+               ladspa_plugin_whitelist.push_back (1061); // feedback delay line (max 5s)
+               ladspa_plugin_whitelist.push_back (1216); // gverb
+               ladspa_plugin_whitelist.push_back (2150); // tap pitch shifter
+       } 
+
+       refresh ();
 }
 
 void
@@ -99,6 +116,9 @@ PluginManager::refresh ()
                vst_refresh ();
        }
 #endif // VST_SUPPORT
+#ifdef HAVE_AUDIOUNITS
+       au_refresh ();
+#endif
 }
 
 void
@@ -113,6 +133,7 @@ PluginManager::ladspa_refresh ()
        ladspa_discover_from_path (ladspa_path);
 }
 
+
 int
 PluginManager::add_ladspa_directory (string path)
 {
@@ -248,6 +269,12 @@ PluginManager::ladspa_discover (string path)
                        break;
                }
 
+               if (!ladspa_plugin_whitelist.empty()) {
+                       if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
+                               continue;
+                       }
+               } 
+
                PluginInfoPtr info(new LadspaPluginInfo);
                info->name = descriptor->Name;
                info->category = get_ladspa_category(descriptor->UniqueID);
@@ -257,7 +284,10 @@ PluginManager::ladspa_discover (string path)
                info->n_inputs = ChanCount();
                info->n_outputs = ChanCount();
                info->type = ARDOUR::LADSPA;
-               info->unique_id = descriptor->UniqueID;
+               
+               char buf[32];
+               snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
+               info->unique_id = buf;
                
                for (uint32_t n=0; n < descriptor->PortCount; ++n) {
                        if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
@@ -294,7 +324,7 @@ PluginManager::get_ladspa_category (uint32_t plugin_id)
        lrdf_statement* matches1 = lrdf_matches (&pattern);
 
        if (!matches1) {
-               return _("Unknown");
+               return _("");
        }
 
        pattern.subject = matches1->object;
@@ -306,7 +336,7 @@ PluginManager::get_ladspa_category (uint32_t plugin_id)
        lrdf_free_statements(matches1);
 
        if (!matches2) {
-               return _("Unknown");
+               return _("");
        }
 
        string label = matches2->object;
@@ -315,6 +345,22 @@ PluginManager::get_ladspa_category (uint32_t plugin_id)
        return label;
 }
 
+#ifdef HAVE_AUDIOUNITS
+void
+PluginManager::au_refresh ()
+{
+       au_discover();
+}
+
+int
+PluginManager::au_discover ()
+{
+       _au_plugin_info = AUPluginInfo::discover();
+       return 0;
+}
+
+#endif
+
 #ifdef VST_SUPPORT
 
 void
@@ -373,6 +419,7 @@ int
 PluginManager::vst_discover (string path)
 {
        FSTInfo* finfo;
+       char buf[32];
 
        if ((finfo = fst_get_info (const_cast<char *> (path.c_str()))) == 0) {
                warning << "Cannot get VST information from " << path << endmsg;
@@ -395,6 +442,9 @@ PluginManager::vst_discover (string path)
                info->name = finfo->name;
        }
 
+       
+       snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
+       info->unique_id = buf;
        info->category = "VST";
        info->path = path;
        // need to set info->creator but FST doesn't provide it
diff --git a/libs/ardour/rb_effect.cc b/libs/ardour/rb_effect.cc
new file mode 100644 (file)
index 0000000..0de5a5b
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+    Copyright (C) 2004-2007 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 <cmath>
+
+#include <pbd/error.h>
+#include <rubberband/RubberBandStretcher.h>
+
+#include <ardour/types.h>
+#include <ardour/stretch.h>
+#include <ardour/pitch.h>
+#include <ardour/audiofilesource.h>
+#include <ardour/session.h>
+#include <ardour/audioregion.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+using namespace RubberBand;
+
+Pitch::Pitch (Session& s, TimeFXRequest& req)
+       : RBEffect (s, req)
+{
+}
+
+Stretch::Stretch (Session& s, TimeFXRequest& req)
+       : RBEffect (s, req)
+{
+}
+
+RBEffect::RBEffect (Session& s, TimeFXRequest& req)
+       : Filter (s)
+       , tsr (req)
+
+{
+       tsr.progress = 0.0f;
+}
+
+RBEffect::~RBEffect ()
+{
+}
+
+int
+RBEffect::run (boost::shared_ptr<AudioRegion> region)
+{
+       SourceList nsrcs;
+       nframes_t done;
+       int ret = -1;
+       const nframes_t bufsize = 256;
+       gain_t* gain_buffer = 0;
+       Sample** buffers = 0;
+       char suffix[32];
+       string new_name;
+       string::size_type at;
+       nframes_t pos = 0;
+       int avail = 0;
+
+       RubberBandStretcher stretcher (session.frame_rate(), region->n_channels(),
+                                      RubberBandStretcher::DefaultOptions,
+                                      tsr.time_fraction, tsr.pitch_fraction);
+       
+       stretcher.setExpectedInputDuration(region->length());
+       stretcher.setDebugLevel(1);
+
+       tsr.progress = 0.0f;
+       tsr.done = false;
+
+       uint32_t channels = region->n_channels();
+       nframes_t duration = region->length();
+
+       /* the name doesn't need to be super-precise, but allow for 2 fractional
+          digits just to disambiguate close but not identical FX
+       */
+
+       if (tsr.time_fraction == 1.0) {
+               snprintf (suffix, sizeof (suffix), "@%d", (int) floor (tsr.pitch_fraction * 100.0f));
+       } else if (tsr.pitch_fraction == 1.0) {
+               snprintf (suffix, sizeof (suffix), "@%d", (int) floor (tsr.time_fraction * 100.0f));
+       } else {
+               snprintf (suffix, sizeof (suffix), "@%d-%d", 
+                         (int) floor (tsr.time_fraction * 100.0f),
+                         (int) floor (tsr.pitch_fraction * 100.0f));
+       }
+
+       /* create new sources */
+
+       if (make_new_sources (region, nsrcs, suffix)) {
+               goto out;
+       }
+
+       gain_buffer = new gain_t[bufsize];
+       buffers = new float *[channels];
+
+       for (uint32_t i = 0; i < channels; ++i) {
+               buffers[i] = new float[bufsize];
+       }
+
+       /* we read from the master (original) sources for the region,
+          not the ones currently in use, in case it's already been
+          subject to timefx.  */
+
+       /* study first, process afterwards. */
+
+       pos = 0;
+       avail = 0;
+       done = 0;
+
+       try { 
+               while (pos < duration && !tsr.cancel) {
+                       
+                       nframes_t this_read = 0;
+                       
+                       for (uint32_t i = 0; i < channels; ++i) {
+                               
+                               this_read = 0;
+                               nframes_t this_time;
+                               
+                               this_time = min(bufsize, duration - pos);
+                               
+                               this_read = region->master_read_at
+                                       (buffers[i],
+                                        buffers[i],
+                                        gain_buffer,
+                                        pos + region->position(),
+                                        this_time,
+                                        i);
+                               
+                               if (this_read != this_time) {
+                                       error << string_compose
+                                               (_("tempoize: error reading data from %1"),
+                                                nsrcs[i]->name()) << endmsg;
+                                       goto out;
+                               }
+                       }
+                       
+                       pos += this_read;
+                       done += this_read;
+
+                       tsr.progress = ((float) done / duration) * 0.75;
+
+                       stretcher.study(buffers, this_read, pos == duration);
+               }
+               
+               done = 0;
+               pos = 0;
+
+               while (pos < duration && !tsr.cancel) {
+                       
+                       nframes_t this_read = 0;
+                       
+                       for (uint32_t i = 0; i < channels; ++i) {
+                               
+                               this_read = 0;
+                               nframes_t this_time;
+                               
+                               this_time = min(bufsize, duration - pos);
+                               
+                               this_read = region->master_read_at
+                                       (buffers[i],
+                                        buffers[i],
+                                        gain_buffer,
+                                        pos + region->position(),
+                                        this_time,
+                                        i);
+                               
+                               if (this_read != this_time) {
+                                       error << string_compose
+                                               (_("tempoize: error reading data from %1"),
+                                                nsrcs[i]->name()) << endmsg;
+                                       goto out;
+                               }
+                       }
+
+                       pos += this_read;
+                       done += this_read;
+
+                       tsr.progress = 0.75 + ((float) done / duration) * 0.25;
+
+                       stretcher.process(buffers, this_read, pos == duration);
+
+                       int avail = 0;
+
+                       while ((avail = stretcher.available()) > 0) {
+
+                               this_read = min(bufsize, uint32_t(avail));
+
+                               stretcher.retrieve(buffers, this_read);
+                       
+                               for (uint32_t i = 0; i < nsrcs.size(); ++i) {
+
+                                       if (nsrcs[i]->write(buffers[i], this_read) !=
+                                           this_read) {
+                                               error << string_compose (_("error writing tempo-adjusted data to %1"), nsrcs[i]->name()) << endmsg;
+                                               goto out;
+                                       }
+                               }
+                       }
+               }
+
+               while ((avail = stretcher.available()) >= 0) {
+
+                       uint32_t this_read = min(bufsize, uint32_t(avail));
+
+                       stretcher.retrieve(buffers, this_read);
+
+                       for (uint32_t i = 0; i < nsrcs.size(); ++i) {
+
+                               if (nsrcs[i]->write(buffers[i], this_read) !=
+                                   this_read) {
+                                       error << string_compose (_("error writing tempo-adjusted data to %1"), nsrcs[i]->name()) << endmsg;
+                                       goto out;
+                               }
+                       }
+               }
+
+       } catch (runtime_error& err) {
+               error << _("timefx code failure. please notify ardour-developers.") << endmsg;
+               error << err.what() << endmsg;
+               goto out;
+       }
+
+       new_name = region->name();
+       at = new_name.find ('@');
+
+       // remove any existing stretch indicator
+
+       if (at != string::npos && at > 2) {
+               new_name = new_name.substr (0, at - 1);
+       }
+
+       new_name += suffix;
+
+       ret = finish (region, nsrcs, new_name);
+
+       /* now reset ancestral data for each new region */
+
+       for (vector<boost::shared_ptr<AudioRegion> >::iterator x = results.begin(); x != results.end(); ++x) {
+               nframes64_t astart = (*x)->ancestral_start();
+               nframes64_t alength = (*x)->ancestral_length();
+               nframes_t start;
+               nframes_t length;
+
+               // note: tsr.time_fraction is a percentage of original length. 100 = no change, 
+               // 50 is half as long, 200 is twice as long, etc.
+               
+               
+               float stretch = (*x)->stretch() * (tsr.time_fraction/100.0);
+               float shift = (*x)->shift() * tsr.pitch_fraction;
+
+               start = (nframes_t) floor (astart + ((astart - (*x)->start()) / stretch));
+               length = (nframes_t) floor (alength / stretch);
+
+               (*x)->set_ancestral_data (start, length, stretch, shift);
+       }
+
+  out:
+
+       if (gain_buffer) {
+               delete [] gain_buffer;
+       }
+
+       if (buffers) {
+               for (uint32_t i = 0; i < channels; ++i) {
+                       delete buffers[i];
+               }
+               delete [] buffers;
+       }
+
+       if (ret || tsr.cancel) {
+               for (SourceList::iterator si = nsrcs.begin(); si != nsrcs.end(); ++si) {
+                       (*si)->mark_for_remove ();
+               }
+       }
+       
+       tsr.done = true;
+
+       return ret;
+}
+
+
+
+
+    
index ecc7b5e30550b5fa0a035bd6d947798b8f677294..0505985aea922a38d6c132133d1cb1f21c8f7047 100644 (file)
@@ -365,6 +365,8 @@ Region::set_length (nframes_t len, void *src)
                        return;
                }
                
+
+               _last_length = _length;
                _length = len;
 
                _flags = Region::Flag (_flags & ~WholeFile);
@@ -443,6 +445,7 @@ Region::special_set_position (nframes_t pos)
           a way to store its "natural" or "captured" position.
        */
 
+       _position = _position;
        _position = pos;
 }
 
@@ -454,6 +457,7 @@ Region::set_position (nframes_t pos, void *src)
        }
 
        if (_position != pos) {
+               _last_position = _position;
                _position = pos;
 
                /* check that the new _position wouldn't make the current
@@ -463,6 +467,7 @@ Region::set_position (nframes_t pos, void *src)
                */
 
                if (max_frames - _length < _position) {
+                       _last_length = _length;
                        _length = max_frames - _position;
                }
        }
@@ -482,6 +487,7 @@ Region::set_position_on_top (nframes_t pos, void *src)
        }
 
        if (_position != pos) {
+               _last_position = _position;
                _position = pos;
        }
 
@@ -499,7 +505,7 @@ Region::set_position_on_top (nframes_t pos, void *src)
 }
 
 void
-Region::nudge_position (long n, void *src)
+Region::nudge_position (nframes64_t n, void *src)
 {
        if (_flags & Locked) {
                return;
@@ -509,6 +515,8 @@ Region::nudge_position (long n, void *src)
                return;
        }
        
+       _last_position = _position;
+
        if (n > 0) {
                if (_position > max_frames - n) {
                        _position = max_frames;
@@ -527,11 +535,12 @@ Region::nudge_position (long n, void *src)
 }
 
 void
-Region::set_ancestral_data (nframes64_t s, nframes64_t l, float st)
+Region::set_ancestral_data (nframes64_t s, nframes64_t l, float st, float sh)
 {
        _ancestral_length = l;
        _ancestral_start = s;
        _stretch = st;
+       _shift = sh;
 }
 
 void
@@ -723,10 +732,16 @@ Region::trim_to_internal (nframes_t position, nframes_t length, void *src)
                what_changed = Change (what_changed|StartChanged);
        }
        if (_length != length) {
+               if (!_frozen) {
+                       _last_length = _length;
+               }
                _length = length;
                what_changed = Change (what_changed|LengthChanged);
        }
        if (_position != position) {
+               if (!_frozen) {
+                       _last_position = _position;
+               }
                _position = position;
                what_changed = Change (what_changed|PositionChanged);
        }
@@ -867,14 +882,16 @@ Region::adjust_to_sync (nframes_t pos)
 {
        int sync_dir;
        nframes_t offset = sync_offset (sync_dir);
+
+       // cerr << "adjusting pos = " << pos << " to sync at " << _sync_position << " offset = " << offset << " with dir = " << sync_dir << endl;
        
        if (sync_dir > 0) {
                if (max_frames - pos > offset) {
-                       pos += offset;
+                       pos -= offset;
                }
        } else {
                if (pos > offset) {
-                       pos -= offset;
+                       pos += offset;
                } else {
                        pos = 0;
                }
@@ -893,6 +910,24 @@ Region::sync_position() const
        }
 }
 
+void
+Region::raise ()
+{
+       boost::shared_ptr<Playlist> pl (playlist());
+       if (pl) {
+               pl->raise_region (shared_from_this ());
+       }
+}
+
+void
+Region::lower ()
+{
+       boost::shared_ptr<Playlist> pl (playlist());
+       if (pl) {
+               pl->lower_region (shared_from_this ());
+       }
+}
+
 
 void
 Region::raise_to_top ()
@@ -945,6 +980,8 @@ Region::state (bool full_state)
        node->add_property ("ancestral-length", buf);
        snprintf (buf, sizeof (buf), "%.12g", _stretch);
        node->add_property ("stretch", buf);
+       snprintf (buf, sizeof (buf), "%.12g", _shift);
+       node->add_property ("shift", buf);
        
        switch (_first_edit) {
        case EditChangesNothing:
@@ -1017,9 +1054,11 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send)
                sscanf (prop->value().c_str(), "%" PRIu32, &val);
                if (val != _length) {
                        what_changed = Change (what_changed|LengthChanged);
+                       _last_length = _length;
                        _length = val;
                }
        } else {
+               _last_length = _length;
                _length = 1;
        }
 
@@ -1027,9 +1066,11 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send)
                sscanf (prop->value().c_str(), "%" PRIu32, &val);
                if (val != _position) {
                        what_changed = Change (what_changed|PositionChanged);
+                       _last_position = _position;
                        _position = val;
                }
        } else {
+               _last_position = _position;
                _position = 0;
        }
 
@@ -1076,6 +1117,12 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send)
                _stretch = 1.0;
        }
 
+       if ((prop = node.property ("shift")) != 0) {
+               _shift = atof (prop->value());
+       } else {
+               _shift = 1.0;
+       }
+
        /* note: derived classes set flags */
 
        if (_extra_xml) {
@@ -1128,6 +1175,8 @@ void
 Region::freeze ()
 {
        _frozen++;
+       _last_length = _length;
+       _last_position = _position;
 }
 
 void
@@ -1261,27 +1310,46 @@ Region::source_equivalent (boost::shared_ptr<const Region> other) const
 bool
 Region::verify_length (nframes_t len)
 {
+       if (source() && source()->destructive()) {
+               return true;
+       }
+
+       nframes_t maxlen = 0;
+
        for (uint32_t n=0; n < _sources.size(); ++n) {
-               if (_start > _sources[n]->length() - len) {
-                       return false;
-               }
+               maxlen = max (maxlen, _sources[n]->length() - _start);
        }
+       
+       len = min (len, maxlen);
+       
        return true;
 }
 
 bool
-Region::verify_start_and_length (nframes_t new_start, nframes_t new_length)
+Region::verify_start_and_length (nframes_t new_start, nframes_t& new_length)
 {
+       if (source() && source()->destructive()) {
+               return true;
+       }
+
+       nframes_t maxlen = 0;
+
        for (uint32_t n=0; n < _sources.size(); ++n) {
-               if (new_length > _sources[n]->length() - new_start) {
-                       return false;
-               }
+               maxlen = max (maxlen, _sources[n]->length() - new_start);
        }
+
+       new_length = min (new_length, maxlen);
+
        return true;
 }
+
 bool
 Region::verify_start (nframes_t pos)
 {
+       if (source() && source()->destructive()) {
+               return true;
+       }
+
        for (uint32_t n=0; n < _sources.size(); ++n) {
                if (pos > _sources[n]->length() - _length) {
                        return false;
@@ -1293,6 +1361,10 @@ Region::verify_start (nframes_t pos)
 bool
 Region::verify_start_mutable (nframes_t& new_start)
 {
+       if (source() && source()->destructive()) {
+               return true;
+       }
+
        for (uint32_t n=0; n < _sources.size(); ++n) {
                if (new_start > _sources[n]->length() - _length) {
                        new_start = _sources[n]->length() - _length;
index 8193d4ed77ae38929c502dd5f710e254e3ebe301..084c4e58b5e949fb8e6e13eaa8d5157e61c83f78 100644 (file)
@@ -80,10 +80,11 @@ Route::init ()
        _muted = false;
        _soloed = false;
        _solo_safe = false;
+       _recordable = true;
+       _active = true;
        _phase_invert = false;
        _denormal_protection = false;
        order_keys[strdup (N_("signal"))] = order_key_cnt++;
-       _active = true;
        _silent = false;
        _meter_point = MeterPostFader;
        _initial_delay = 0;
@@ -1662,10 +1663,14 @@ Route::add_processor_from_xml (const XMLNode& node)
                        if ((prop = node.property ("type")) != 0) {
 
                                boost::shared_ptr<Processor> processor;
+                               bool have_insert = false;
 
-                               if (prop->value() == "ladspa" || prop->value() == "Ladspa" || prop->value() == "vst") {
-
+                               if (prop->value() == "ladspa" || prop->value() == "Ladspa" || 
+                                   prop->value() == "vst" ||
+                                   prop->value() == "audiounit") {
+                                       
                                        processor.reset (new PluginInsert(_session, node));
+                                       have_insert = true;
                                        
                                } else if (prop->value() == "port") {
 
@@ -1674,19 +1679,20 @@ Route::add_processor_from_xml (const XMLNode& node)
                                } else if (prop->value() == "send") {
 
                                        processor.reset (new Send (_session, node));
+                                       have_insert = true;
 
                                } else {
 
                                        error << string_compose(_("unknown Processor type \"%1\"; ignored"), prop->value()) << endmsg;
                                }
-
+                               
                                add_processor (processor);
                                
                        } else {
                                error << _("Processor XML node has no type property") << endmsg;
                        }
                }
-               
+
                catch (failed_constructor &err) {
                        warning << _("processor could not be created. Ignored.") << endmsg;
                        return;
@@ -1732,7 +1738,8 @@ Route::_set_state (const XMLNode& node, bool call_base)
        if ((prop = node.property (X_("denormal-protection"))) != 0) {
                set_denormal_protection (prop->value()=="yes"?true:false, this);
        }
-
+       
+       _active = true;
        if ((prop = node.property (X_("active"))) != 0) {
                set_active (prop->value() == "yes");
        }
index e155800d23e044b7b9ff093f9c09095ed9a3efd4..a7f85a5c84bcfdcbecdeb4cc11b6c05a09972af2 100644 (file)
@@ -97,6 +97,14 @@ static const int CPU_CACHE_ALIGN = 64;
 static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it matters less */
 #endif
 
+bool Session::_disable_all_loaded_plugins = false;
+
+Session::compute_peak_t          Session::compute_peak          = 0;
+Session::find_peaks_t            Session::find_peaks            = 0;
+Session::apply_gain_to_buffer_t  Session::apply_gain_to_buffer  = 0;
+Session::mix_buffers_with_gain_t Session::mix_buffers_with_gain = 0;
+Session::mix_buffers_no_gain_t   Session::mix_buffers_no_gain   = 0;
+
 sigc::signal<int> Session::AskAboutPendingState;
 sigc::signal<void> Session::SendFeedback;
 
@@ -105,9 +113,9 @@ sigc::signal<void> Session::StartTimeChanged;
 sigc::signal<void> Session::EndTimeChanged;
 
 Session::Session (AudioEngine &eng,
-                 string fullpath,
-                 string snapshot_name,
-                 string* mix_template)
+                 const string& fullpath,
+                 const string& snapshot_name,
+                 string mix_template)
 
        : _engine (eng),
          _scratch_buffers(new BufferSet()),
@@ -127,62 +135,29 @@ Session::Session (AudioEngine &eng,
          _click_io ((IO*) 0),
          main_outs (0)
 {
+       bool new_session;
+
        if (!eng.connected()) {
                throw failed_constructor();
        }
+       
+       cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (1)" << endl;
 
        n_physical_outputs = _engine.n_physical_outputs();
        n_physical_inputs =  _engine.n_physical_inputs();
 
        first_stage_init (fullpath, snapshot_name);
 
-       initialize_start_and_end_locations(0, compute_initial_length ());
-
-       if(mix_template) {
-               // try and create a new session directory
-               try
-               {
-                       if(!_session_dir->create()) {
-                               // an existing session.
-                               // throw a_more_meaningful_exception()
-                               destroy ();
-                               throw failed_constructor ();
-                       }
-               }
-               catch(sys::filesystem_error& ex)
-               {
-                       destroy ();
-                       throw failed_constructor ();
-               }
-
-               if(!create_session_file_from_template (*mix_template)) {
-                       destroy ();
-                       throw failed_constructor ();
-               }
-
-               cerr << "Creating session " << fullpath
-                       <<" using template" << *mix_template
-                       << endl;
-       } else {
-               // must be an existing session
-               try
-               {
-                       // ensure the necessary session subdirectories exist
-                       // in case the directory structure has changed etc.
-                       _session_dir->create();
-               }
-               catch(sys::filesystem_error& ex)
-               {
+       new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
+       if (new_session) {
+               if (create (new_session, mix_template, compute_initial_length())) {
+                       cerr << "create failed\n";
                        destroy ();
                        throw failed_constructor ();
                }
-
-               cerr << "Loading session " << fullpath
-                       << " using snapshot " << snapshot_name << " (1)"
-                       << endl;
        }
-
-       if (second_stage_init (false)) {
+       
+       if (second_stage_init (new_session)) {
                destroy ();
                throw failed_constructor ();
        }
@@ -228,6 +203,8 @@ Session::Session (AudioEngine &eng,
          main_outs (0)
 
 {
+       bool new_session;
+
        if (!eng.connected()) {
                throw failed_constructor();
        }
@@ -247,11 +224,13 @@ Session::Session (AudioEngine &eng,
 
        first_stage_init (fullpath, snapshot_name);
 
-       initialize_start_and_end_locations(0, initial_length);
-       
-       if (!_session_dir->create () || !create_session_file ())        {
-               destroy ();
-               throw failed_constructor ();
+       new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
+
+       if (new_session) {
+               if (create (new_session, string(), initial_length)) {
+                       destroy ();
+                       throw failed_constructor ();
+               }
        }
 
        {
@@ -286,7 +265,7 @@ Session::Session (AudioEngine &eng,
        Config->set_input_auto_connect (input_ac);
        Config->set_output_auto_connect (output_ac);
 
-       if (second_stage_init (true)) {
+       if (second_stage_init (new_session)) {
                destroy ();
                throw failed_constructor ();
        }
@@ -3273,7 +3252,7 @@ Session::midi_path_from_name (string name)
 
        return spath;
 }
-
+       
 boost::shared_ptr<MidiSource>
 Session::create_midi_source_for_session (MidiDiskstream& ds)
 {
index afb284b0f49a4ab549eee18002894b8929c11e2f..148ff9273993cf50fbf9dd7b6d358ccdc1c6d013 100644 (file)
@@ -233,10 +233,6 @@ Session::butler_thread_work ()
                        }
                }
 
-               //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 ();
                }
@@ -249,10 +245,23 @@ Session::butler_thread_work ()
 
                boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader ();
 
+//             for (i = dsl->begin(); i != dsl->end(); ++i) {
+//                     cerr << "BEFORE " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
+//             }
+
                for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) {
 
                        boost::shared_ptr<Diskstream> ds = *i;
 
+                       /* don't read inactive tracks */
+
+                       /*IO* io = ds->io();
+                       
+                       if (ds->io() && !ds->io()->active()) {
+                               cerr << "Skip inactive diskstream " << ds->io()->name() << endl;
+                               continue;
+                       }*/
+
                        switch (ds->do_refill ()) {
                        case 0:
                                bytes += ds->read_data_count();
@@ -294,6 +303,9 @@ Session::butler_thread_work ()
 
                for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) {
                        // cerr << "write behind for " << (*i)->name () << endl;
+
+                       /* note that we still try to flush diskstreams attached to inactive routes
+                        */
                        
                        switch ((*i)->do_flush (Session::ButlerContext)) {
                        case 0:
index bf1d9f1a09f3f80310cefc5db329928b6a0e2274..f1355b331b09da9fe7bf6cff606ad35a897b789f 100644 (file)
@@ -41,6 +41,7 @@ static const char* event_names[] = {
        "SetDiskstreamSpeed",
        "Locate",
        "LocateRoll",
+       "LocateRollLocate",
        "SetLoop",
        "PunchIn",
        "PunchOut",
@@ -351,6 +352,13 @@ Session::process_event (Event* ev)
                _send_smpte_update = true;
                break;
 
+       case Event::LocateRollLocate:
+               // locate is handled by ::request_roll_at_and_return()
+               _requested_return_frame = ev->target_frame;
+               set_transport_speed (ev->speed, true);
+               break;
+
+
        case Event::SetTransportSpeed:
                set_transport_speed (ev->speed, ev->yes_or_no);
                break;
index b0addd21f6bc7b84f352d60b0d686fab077fd192..b1058f2e7e4e50335bce3beddc2059a504d569ba 100644 (file)
@@ -428,6 +428,10 @@ AudioExportSpecification::process (nframes_t nframes)
 int
 Session::start_audio_export (AudioExportSpecification& spec)
 {
+       if (!_engine.connected()) {
+               return -1;
+       }
+
        if (spec.prepare (current_block_size, frame_rate())) {
                return -1;
        }
index 44b63e08756bee087038e7777b382db7ddd2eb51..6476ab30f7f1ba9678d2d5f59e685e9c0189b75c 100644 (file)
@@ -52,6 +52,8 @@ Session::process (nframes_t nframes)
 {
        MIDI::Manager::instance()->cycle_start(nframes);
 
+       _silent = false;
+
        if (synced_to_jack() && waiting_to_start) {
                if ( _engine.transport_state() == AudioEngine::TransportRolling) {
                        actually_start_transport ();
@@ -302,7 +304,7 @@ Session::process_with_events (nframes_t nframes)
        }
 
        if (!process_can_proceed()) {
-               no_roll (nframes, 0);
+               _silent = true;
                return;
        }
 
@@ -317,8 +319,8 @@ Session::process_with_events (nframes_t nframes)
                Event* this_event;
                Events::iterator the_next_one;
                
-               if (post_transport_work & (PostTransportLocate|PostTransportStop)) {
-                       no_roll (nframes, 0);
+               if (!process_can_proceed()) {
+                       _silent = true;
                        return;
                }
                
@@ -494,7 +496,7 @@ Session::follow_slave (nframes_t nframes, nframes_t offset)
             << endl;
 #endif 
 
-       if (Config->get_timecode_source_is_synced()) {
+       if (_slave->is_always_synced() || Config->get_timecode_source_is_synced()) {
 
                /* if the TC source is synced, then we assume that its 
                   speed is binary: 0.0 or 1.0
@@ -642,7 +644,7 @@ Session::follow_slave (nframes_t nframes, nframes_t offset)
                slave_state = Stopped;
        }
 
-       if (slave_state == Running && !Config->get_timecode_source_is_synced()) {
+       if (slave_state == Running && !_slave->is_always_synced() && !Config->get_timecode_source_is_synced()) {
 
 
                if (_transport_speed != 0.0f) {
@@ -743,67 +745,64 @@ Session::process_without_events (nframes_t nframes)
        long frames_moved;
        nframes_t offset = 0;
 
-       {
-               if (post_transport_work & (PostTransportLocate|PostTransportStop)) {
-                       no_roll (nframes, 0);
-                       return;
-               }
-
-               if (!_exporting && _slave) {
-                       if (!follow_slave (nframes, 0)) {
-                               return;
-                       }
-               } 
+       if (!process_can_proceed()) {
+               _silent = true;
+               return;
+       }
 
-               if (_transport_speed == 0) {
-                       no_roll (nframes, 0);
+       if (!_exporting && _slave) {
+               if (!follow_slave (nframes, 0)) {
                        return;
                }
        
                send_midi_time_code_for_cycle(nframes);
+       } 
+
+       if (_transport_speed == 0) {
+               no_roll (nframes, 0);
+               return;
+       }
                
-               if (actively_recording()) {
-                       stop_limit = max_frames;
+       if (actively_recording()) {
+               stop_limit = max_frames;
+       } else {
+               if (Config->get_stop_at_session_end()) {
+                       stop_limit = current_end_frame();
                } else {
-                       if (Config->get_stop_at_session_end()) {
-                               stop_limit = current_end_frame();
-                       } else {
-                               stop_limit = max_frames;
-                       }
+                       stop_limit = max_frames;
                }
+       }
                
-               if (maybe_stop (stop_limit)) {
-                       no_roll (nframes, 0);
-                       return;
-               
+       if (maybe_stop (stop_limit)) {
+               no_roll (nframes, 0);
+               return;
+       } 
 
-               if (maybe_sync_start (nframes, offset)) {
-                       return;
-               }
+       if (maybe_sync_start (nframes, offset)) {
+               return;
+       }
 
-               click (_transport_frame, nframes, offset);
+       click (_transport_frame, nframes, offset);
 
-               prepare_diskstreams ();
+       prepare_diskstreams ();
        
-               frames_moved = (long) floor (_transport_speed * nframes);
+       frames_moved = (long) floor (_transport_speed * nframes);
 
-               if (process_routes (nframes, offset)) {
-                       no_roll (nframes, offset);
-                       return;
-               }
-
-               commit_diskstreams (nframes, session_needs_butler);
+       if (process_routes (nframes, offset)) {
+               no_roll (nframes, offset);
+               return;
+       }
 
-               if (frames_moved < 0) {
-                       decrement_transport_position (-frames_moved);
-               } else {
-                       increment_transport_position (frames_moved);
-               }
+       commit_diskstreams (nframes, session_needs_butler);
 
-               maybe_stop (stop_limit);
-               check_declick_out ();
+       if (frames_moved < 0) {
+               decrement_transport_position (-frames_moved);
+       } else {
+               increment_transport_position (frames_moved);
+       }
 
-       } /* implicit release of route lock */
+       maybe_stop (stop_limit);
+       check_declick_out ();
 
        if (session_needs_butler)
                summon_butler ();
index 877047d93ab763daf5e0926867b462cfc06b3f9d..fa4b103958b9630d2741640385972adb6500e33a 100644 (file)
@@ -418,49 +418,106 @@ Session::setup_raid_path (string path)
        last_rr_session_dir = session_dirs.begin();
 }
 
-void
-Session::initialize_start_and_end_locations (nframes_t start, nframes_t end)
+int
+Session::create (bool& new_session, const string& mix_template, nframes_t initial_length)
 {
-       start_location->set_end (start);
-       _locations.add (start_location);
+       string dir;
 
-       end_location->set_end (end);
-       _locations.add (end_location);
-}
+       if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
+               error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
+               return -1;
+       }
 
-bool
-Session::create_session_file ()
-{
-       _state_of_the_state = Clean;
+       dir = session_directory().peak_path().to_string();
 
-       if (save_state (_current_snapshot_name)) {
-               error << "Could not create new session file" << endmsg;
-               return false;
+       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+               error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+               return -1;
        }
-       return true;
-}
 
-bool
-Session::create_session_file_from_template (const string& template_path)
-{
-       sys::path session_file_path(_session_dir->root_path());
+       dir = session_directory().sound_path().to_string();
 
-       session_file_path /= _name + statefile_suffix;
+       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+               error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+               return -1;
+       }
+       
+       dir = session_directory().midi_path().to_string();
 
-       try
-       {
-               sys::copy_file (template_path, session_file_path);
+       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+               error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+               return -1;
        }
-       catch(sys::filesystem_error& ex)
-       {
-               error << string_compose (_("Could not use session template %1 to create new session (%2)."),
-                               template_path, ex.what())
-                       << endmsg;
-               return false;
+
+       dir = session_directory().dead_sound_path().to_string();
+
+       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+               error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+               return -1;
        }
-       return true;
+
+       dir = session_directory().export_path().to_string();
+
+       if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+               error << string_compose(_("Session: cannot create session export dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+               return -1;
+       }
+
+
+       /* check new_session so we don't overwrite an existing one */
+
+       if (!mix_template.empty()) {
+               std::string in_path = mix_template;
+
+               ifstream in(in_path.c_str());
+
+               if (in){
+                       string out_path = _path;
+                       out_path += _name;
+                       out_path += statefile_suffix;
+
+                       ofstream out(out_path.c_str());
+
+                       if (out){
+                               out << in.rdbuf();
+
+                               // okay, session is set up.  Treat like normal saved
+                               // session from now on.
+
+                               new_session = false;
+                               return 0;
+
+                       } else {
+                               error << string_compose (_("Could not open %1 for writing mix template"), out_path) 
+                                       << endmsg;
+                               return -1;
+                       }
+
+               } else {
+                       error << string_compose (_("Could not open mix template %1 for reading"), in_path) 
+                               << endmsg;
+                       return -1;
+               }
+
+       }
+
+       /* set initial start + end point */
+
+       start_location->set_end (0);
+       _locations.add (start_location);
+
+       end_location->set_end (initial_length);
+       _locations.add (end_location);
+
+       _state_of_the_state = Clean;
+
+
+       save_state ("");
+
+       return 0;
 }
 
+
 int
 Session::load_diskstreams (const XMLNode& node)
 {
@@ -2767,7 +2824,7 @@ Session::restore_history (string snapshot_name)
        const string xml_filename = snapshot_name + history_suffix;
        const sys::path xml_path = _session_dir->root_path() / xml_filename;
 
-       info << string_compose(_("Loading history from '%1'."), xml_path.to_string()) << endmsg;
+    cerr << "Loading history from " << xml_path.to_string() << endmsg;
 
        if (!sys::exists (xml_path)) {
                info << string_compose (_("%1: no history file \"%2\" for this session."),
index 2776fbf41dac5135ed0ee7d10bea7a6e23fa5445..1398872b36194933238ba9cfefb17e5e82f367b8 100644 (file)
@@ -29,6 +29,7 @@
 #include <glibmm/thread.h>
 #include <pbd/pthread_utils.h>
 #include <pbd/memento_command.h>
+#include <pbd/stacktrace.h>
 
 #include <midi++/mmc.h>
 #include <midi++/port.h>
@@ -392,17 +393,35 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                update_latency_compensation (true, abort);
        }
 
-       if ((Config->get_slave_source() == None && Config->get_auto_return()) || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
+       if ((Config->get_slave_source() == None && Config->get_auto_return()) || 
+           (post_transport_work & PostTransportLocate) || 
+           (_requested_return_frame >= 0) ||
+           synced_to_jack()) {
                
                if (pending_locate_flush) {
                        flush_all_inserts ();
                }
                
-               if (((Config->get_slave_source() == None && Config->get_auto_return()) || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
+               if (((Config->get_slave_source() == None && Config->get_auto_return()) || 
+                    synced_to_jack() ||
+                    _requested_return_frame >= 0) &&
+                   !(post_transport_work & PostTransportLocate)) {
 
-                       _transport_frame = last_stop_frame;
+                       bool do_locate = false;
+
+                       if (_requested_return_frame >= 0) {
+                               _transport_frame = _requested_return_frame;
+                               _requested_return_frame = -1;
+                               do_locate = true;
+                       } else {
+                               _transport_frame = last_stop_frame;
+                       }
 
                        if (synced_to_jack() && !play_loop) {
+                               do_locate = true;
+                       }
+                       
+                       if (do_locate) {
                                // cerr << "non-realtimestop: transport locate to " << _transport_frame << endl;
                                _engine.transport_locate (_transport_frame);
                        }
@@ -478,7 +497,9 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                
        }
 
-       PositionChanged (_transport_frame); /* EMIT SIGNAL */
+        nframes_t tf = _transport_frame;
+
+        PositionChanged (tf); /* EMIT SIGNAL */
        TransportStateChange (); /* EMIT SIGNAL */
 
        /* and start it up again if relevant */
@@ -1202,6 +1223,14 @@ Session::setup_auto_play ()
        merge_event (ev);
 }
 
+void
+Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
+{
+       request_locate (start, false);
+       Event *ev = new Event (Event::LocateRollLocate, Event::Add, Event::Immediate, return_to, 1.0);
+       queue_event (ev);
+}
+
 void
 Session::request_bounded_roll (nframes_t start, nframes_t end)
 {
index b8d82bdb9d7caa96280cdbbe48f56fc35c6edec8..29f36cc2cd3be54c2d6d655414f6d847a6762aca 100644 (file)
@@ -345,7 +345,8 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n
        
        // FIXME: assumes tempo never changes after start
        const double frames_per_beat = _session.tempo_map().tempo_at(_timeline_position).frames_per_beat(
-                       _session.engine().frame_rate());
+                       _session.engine().frame_rate(),
+                       _session.tempo_map().meter_at(_timeline_position));
        
        const uint64_t start_ticks = (uint64_t)((start / frames_per_beat) * _ppqn);
 
@@ -456,8 +457,9 @@ SMFSource::append_event_unlocked(const MidiEvent& ev)
        assert(ev.time() >= _last_ev_time);
        
        // FIXME: assumes tempo never changes after start
-       const double frames_per_beat = _session.tempo_map().tempo_at
-                       (_timeline_position).frames_per_beat(_session.engine().frame_rate());
+       const double frames_per_beat = _session.tempo_map().tempo_at(_timeline_position).frames_per_beat(
+                       _session.engine().frame_rate(),
+                       _session.tempo_map().meter_at(_timeline_position));
        
        const uint32_t delta_time = (uint32_t)((ev.time() - _last_ev_time) / frames_per_beat * _ppqn);
 
@@ -888,7 +890,8 @@ SMFSource::load_model(bool lock, bool force_reload)
        
        // FIXME: assumes tempo never changes after start
        const double frames_per_beat = _session.tempo_map().tempo_at(_timeline_position).frames_per_beat(
-                       _session.engine().frame_rate());
+                       _session.engine().frame_rate(),
+                       _session.tempo_map().meter_at(_timeline_position));
        
        uint32_t delta_t = 0;
        int ret;
index 96dc2c777908b33e9570414580e3cf4d8b164337..58a51f8bbe714e7a6b6d1c2841e671cdbe89b088 100644 (file)
@@ -33,33 +33,27 @@ using namespace std;
 const char * const sndfile_header_formats_strings[SNDFILE_HEADER_FORMATS+1] = {
        N_("WAV"),
        N_("AIFF"),
-       N_("raw (no header)"),
-       N_("PAF (Ensoniq Paris)"),
-       N_("AU (Sun/NeXT)"),
-       N_("IRCAM"),
+       N_("CAF"),
        N_("W64 (64 bit WAV)"),
+       N_("raw (no header)"),
        0
 };
 
 const char* const sndfile_file_endings_strings[SNDFILE_HEADER_FORMATS+1] = {
        N_(".wav"),
        N_(".aiff"),
-       N_(".raw"),
-       N_(".paf"),
-       N_(".au"),
-       N_(".ircam"),
+       N_(".caf"),
        N_(".w64"),
+       N_(".raw"),
        0
 };
 
 int sndfile_header_formats[SNDFILE_HEADER_FORMATS] = {
        SF_FORMAT_WAV,
        SF_FORMAT_AIFF,
-       SF_FORMAT_RAW,
-       SF_FORMAT_PAF,
-       SF_FORMAT_AU,
-       SF_FORMAT_IRCAM,
-       SF_FORMAT_W64
+       SF_FORMAT_CAF,
+       SF_FORMAT_W64,
+       SF_FORMAT_RAW
 };
 
 const char * const sndfile_bitdepth_formats_strings[SNDFILE_BITDEPTH_FORMATS+1] = {
index 89d4e3ed79fb3143547c95d6ef5be76048ea2522..661beef40b2e74de54734ed6b449cf71ac746a0e 100644 (file)
@@ -60,7 +60,7 @@ peak_thread_work ()
                if (SourceFactory::files_with_peaks.empty()) {
                        goto wait;
                }
-               
+
                boost::shared_ptr<AudioSource> as (SourceFactory::files_with_peaks.front().lock());
                SourceFactory::files_with_peaks.pop_front ();
                SourceFactory::peak_building_lock.unlock ();
@@ -68,7 +68,6 @@ peak_thread_work ()
                if (!as) {
                        continue;
                }
-
                as->setup_peakfile ();
        }
 }
diff --git a/libs/ardour/st_pitch.cc b/libs/ardour/st_pitch.cc
new file mode 100644 (file)
index 0000000..3999c1a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+    Copyright (C) 2004-2007 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 <cmath>
+
+#include <pbd/error.h>
+
+#include <ardour/types.h>
+#include <ardour/pitch.h>
+#include <ardour/audiofilesource.h>
+#include <ardour/session.h>
+#include <ardour/audioregion.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+
+Pitch::Pitch (Session& s, TimeFXRequest& req)
+       : Filter (s)
+       , tsr (req)
+
+{
+       tsr.progress = 0.0f;
+}
+
+int
+Pitch::run (boost::shared_ptr<Region> region)
+{
+       tsr.progress = 1.0f;
+       tsr.done = true;
+
+       return 1;
+}
diff --git a/libs/ardour/st_stretch.cc b/libs/ardour/st_stretch.cc
new file mode 100644 (file)
index 0000000..e96cd79
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+    Copyright (C) 2004-2007 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 <cmath>
+
+#include <pbd/error.h>
+
+#include <ardour/types.h>
+#include <ardour/stretch.h>
+#include <ardour/audiofilesource.h>
+#include <ardour/session.h>
+#include <ardour/audioregion.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+using namespace soundtouch;
+
+Stretch::Stretch (Session& s, TimeFXRequest& req)
+       : Filter (s)
+       , tsr (req)
+{
+       float percentage;
+
+       /* the soundtouch code wants a *tempo* change percentage, which is 
+          of opposite sign to the length change.  
+       */
+
+       percentage = -tsr.time_fraction;
+
+       st.setSampleRate (s.frame_rate());
+       st.setChannels (1);
+       st.setTempoChange (percentage);
+       st.setPitchSemiTones (0);
+       st.setRateChange (0);
+       
+       st.setSetting(SETTING_USE_QUICKSEEK, tsr.quick_seek);
+       st.setSetting(SETTING_USE_AA_FILTER, tsr.antialias);
+
+       tsr.progress = 0.0f;
+}
+
+Stretch::~Stretch ()
+{
+}
+
+int
+Stretch::run (boost::shared_ptr<Region> a_region)
+{
+       SourceList nsrcs;
+       nframes_t total_frames;
+       nframes_t done;
+       int ret = -1;
+       const nframes_t bufsize = 16384;
+       gain_t *gain_buffer = 0;
+       Sample *buffer = 0;
+       char suffix[32];
+       string new_name;
+       string::size_type at;
+
+       tsr.progress = 0.0f;
+       tsr.done = false;
+       
+       boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion>(a_region);
+
+       total_frames = region->length() * region->n_channels();
+       done = 0;
+
+       /* the name doesn't need to be super-precise, but allow for 2 fractional
+          digits just to disambiguate close but not identical stretches.
+       */
+       
+       snprintf (suffix, sizeof (suffix), "@%d", (int) floor (tsr.time_fraction * 100.0f));
+
+       /* create new sources */
+       
+       if (make_new_sources (region, nsrcs, suffix)) {
+               goto out;
+       }
+
+       gain_buffer = new gain_t[bufsize];
+       buffer = new Sample[bufsize];
+
+       // soundtouch throws runtime_error on error
+
+       try {
+               for (uint32_t i = 0; i < nsrcs.size(); ++i) {
+
+                       boost::shared_ptr<AudioSource> asrc
+                               = boost::dynamic_pointer_cast<AudioSource>(nsrcs[i]);
+
+                       nframes_t pos = 0;
+                       nframes_t this_read = 0;
+
+                       st.clear();
+
+                       while (!tsr.cancel && pos < region->length()) {
+                               nframes_t this_time;
+                       
+                               this_time = min (bufsize, region->length() - pos);
+
+                               /* read from the master (original) sources for the region, 
+                                  not the ones currently in use, in case it's already been 
+                                  subject to timefx.  
+                               */
+
+                               if ((this_read = region->master_read_at (buffer, buffer, gain_buffer, pos + region->position(), this_time)) != this_time) {
+                                       error << string_compose (_("tempoize: error reading data from %1"), asrc->name()) << endmsg;
+                                       goto out;
+                               }
+                       
+                               pos += this_read;
+                               done += this_read;
+
+                               tsr.progress = (float) done / total_frames;
+                               
+                               st.putSamples (buffer, this_read);
+                       
+                               while ((this_read = st.receiveSamples (buffer, bufsize)) > 0 && !tsr.cancel) {
+                                       if (asrc->write (buffer, this_read) != this_read) {
+                                               error << string_compose (_("error writing tempo-adjusted data to %1"), asrc->name()) << endmsg;
+                                               goto out;
+                                       }
+                               }
+                       }
+               
+                       if (!tsr.cancel) {
+                               st.flush ();
+                       }
+               
+                       while (!tsr.cancel && (this_read = st.receiveSamples (buffer, bufsize)) > 0) {
+                               if (asrc->write (buffer, this_read) != this_read) {
+                                       error << string_compose (_("error writing tempo-adjusted data to %1"), asrc->name()) << endmsg;
+                                       goto out;
+                               }
+                       }
+               }
+
+       } catch (runtime_error& err) {
+               error << _("timefx code failure. please notify ardour-developers.") << endmsg;
+               error << err.what() << endmsg;
+               goto out;
+       }
+
+       new_name = region->name();
+       at = new_name.find ('@');
+
+       // remove any existing stretch indicator
+
+       if (at != string::npos && at > 2) {
+               new_name = new_name.substr (0, at - 1);
+       }
+
+       new_name += suffix;
+
+       ret = finish (region, nsrcs, new_name);
+
+       /* now reset ancestral data for each new region */
+
+       for (vector<boost::shared_ptr<Region> >::iterator x = results.begin(); x != results.end(); ++x) {
+               nframes64_t astart = (*x)->ancestral_start();
+               nframes64_t alength = (*x)->ancestral_length();
+               nframes_t start;
+               nframes_t length;
+
+               // note: tsr.fraction is a percentage of original length. 100 = no change, 
+               // 50 is half as long, 200 is twice as long, etc.
+
+               float stretch = (*x)->stretch() * (tsr.time_fraction/100.0);
+
+               start = (nframes_t) floor (astart + ((astart - (*x)->start()) / stretch));
+               length = (nframes_t) floor (alength / stretch);
+
+               (*x)->set_ancestral_data (start, length, stretch, (*x)->shift());
+       }
+
+  out:
+
+       if (gain_buffer) {
+               delete [] gain_buffer;
+       }
+
+       if (buffer) {
+               delete [] buffer;
+       }
+
+       if (ret || tsr.cancel) {
+               for (SourceList::iterator si = nsrcs.begin(); si != nsrcs.end(); ++si) {
+                       (*si)->mark_for_remove ();
+               }
+       }
+       
+       tsr.done = true;
+
+       return ret;
+}
diff --git a/libs/ardour/stretch.cc b/libs/ardour/stretch.cc
deleted file mode 100644 (file)
index 64b741d..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
-    Copyright (C) 2004-2007 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 <cmath>
-
-#include <pbd/error.h>
-
-#include <ardour/types.h>
-#include <ardour/stretch.h>
-#include <ardour/audiofilesource.h>
-#include <ardour/session.h>
-#include <ardour/audioregion.h>
-
-#include "i18n.h"
-
-using namespace std;
-using namespace ARDOUR;
-using namespace PBD;
-using namespace soundtouch;
-
-Stretch::Stretch (Session& s, TimeStretchRequest& req)
-       : Filter (s)
-       , tsr (req)
-{
-       float percentage;
-
-       /* the soundtouch code wants a *tempo* change percentage, which is 
-          of opposite sign to the length change.  
-       */
-
-       percentage = -tsr.fraction;
-
-       st.setSampleRate (s.frame_rate());
-       st.setChannels (1);
-       st.setTempoChange (percentage);
-       st.setPitchSemiTones (0);
-       st.setRateChange (0);
-       
-       st.setSetting(SETTING_USE_QUICKSEEK, tsr.quick_seek);
-       st.setSetting(SETTING_USE_AA_FILTER, tsr.antialias);
-
-       tsr.progress = 0.0f;
-}
-
-Stretch::~Stretch ()
-{
-}
-
-int
-Stretch::run (boost::shared_ptr<Region> r)
-{
-       boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (r);
-
-       if (!region) {
-               return -1;
-       }
-
-       SourceList nsrcs;
-       nframes_t total_frames;
-       nframes_t done;
-       int ret = -1;
-       const nframes_t bufsize = 16384;
-       gain_t *gain_buffer = 0;
-       Sample *buffer = 0;
-       char suffix[32];
-       string new_name;
-       string::size_type at;
-
-       tsr.progress = 0.0f;
-       tsr.done = false;
-
-       total_frames = region->length() * region->n_channels();
-       done = 0;
-
-       /* the name doesn't need to be super-precise, but allow for 2 fractional
-          digits just to disambiguate close but not identical stretches.
-       */
-       
-       snprintf (suffix, sizeof (suffix), "@%d", (int) floor (tsr.fraction * 100.0f));
-
-       /* create new sources */
-       
-       if (make_new_sources (region, nsrcs, suffix)) {
-               goto out;
-       }
-
-       gain_buffer = new gain_t[bufsize];
-       buffer = new Sample[bufsize];
-
-       // soundtouch throws runtime_error on error
-
-       try {
-               for (uint32_t i = 0; i < nsrcs.size(); ++i) {
-
-                       boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (nsrcs[i]);
-
-                       if (!afs) {
-                               continue;
-                       }
-                       
-                       nframes_t pos = 0;
-                       nframes_t this_read = 0;
-
-                       st.clear();
-
-                       while (!tsr.cancel && pos < region->length()) {
-                               nframes_t this_time;
-                       
-                               this_time = min (bufsize, region->length() - pos);
-
-                               /* read from the master (original) sources for the region, 
-                                  not the ones currently in use, in case it's already been 
-                                  subject to timefx.  
-                               */
-
-                               if ((this_read = region->master_read_at (buffer, buffer, gain_buffer, pos + region->position(), this_time)) != this_time) {
-                                       error << string_compose (_("tempoize: error reading data from %1"), afs->name()) << endmsg;
-                                       goto out;
-                               }
-                       
-                               pos += this_read;
-                               done += this_read;
-
-                               tsr.progress = (float) done / total_frames;
-                               
-                               st.putSamples (buffer, this_read);
-                       
-                               while ((this_read = st.receiveSamples (buffer, bufsize)) > 0 && !tsr.cancel) {
-                                       if (afs->write (buffer, this_read) != this_read) {
-                                               error << string_compose (_("error writing tempo-adjusted data to %1"), afs->name()) << endmsg;
-                                               goto out;
-                                       }
-                               }
-                       }
-               
-                       if (!tsr.cancel) {
-                               st.flush ();
-                       }
-               
-                       while (!tsr.cancel && (this_read = st.receiveSamples (buffer, bufsize)) > 0) {
-                               if (afs->write (buffer, this_read) != this_read) {
-                                       error << string_compose (_("error writing tempo-adjusted data to %1"), afs->name()) << endmsg;
-                                       goto out;
-                               }
-                       }
-               }
-
-       } catch (runtime_error& err) {
-               error << _("timefx code failure. please notify ardour-developers.") << endmsg;
-               error << err.what() << endmsg;
-               goto out;
-       }
-
-       new_name = region->name();
-       at = new_name.find ('@');
-
-       // remove any existing stretch indicator
-
-       if (at != string::npos && at > 2) {
-               new_name = new_name.substr (0, at - 1);
-       }
-
-       new_name += suffix;
-
-       ret = finish (region, nsrcs, new_name);
-
-       /* now reset ancestral data for each new region */
-
-       for (vector<boost::shared_ptr<Region> >::iterator x = results.begin(); x != results.end(); ++x) {
-
-               boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (*x);
-
-               assert (region != 0);
-
-               nframes64_t astart = region->ancestral_start();
-               nframes64_t alength = region->ancestral_length();
-               nframes_t start;
-               nframes_t length;
-
-               // note: tsr.fraction is a percentage of original length. 100 = no change, 
-               // 50 is half as long, 200 is twice as long, etc.
-
-               float stretch = region->stretch() * (tsr.fraction/100.0);
-
-               start = (nframes_t) floor (astart + ((astart - region->start()) / stretch));
-               length = (nframes_t) floor (alength / stretch);
-
-               region->set_ancestral_data (start, length, stretch);
-       }
-
-  out:
-
-       if (gain_buffer) {
-               delete [] gain_buffer;
-       }
-
-       if (buffer) {
-               delete [] buffer;
-       }
-
-       if (ret || tsr.cancel) {
-               for (SourceList::iterator si = nsrcs.begin(); si != nsrcs.end(); ++si) {
-                       (*si)->mark_for_remove ();
-               }
-       }
-       
-       tsr.done = true;
-
-       return ret;
-}
index cd59e93054145fb05160c52f1aad2fdecfd9ab46..780f5c6a5df6513ff903cdd8e6706595ad5ecf5b 100644 (file)
@@ -43,12 +43,17 @@ Tempo    TempoMap::_default_tempo (120.0);
 
 const double Meter::ticks_per_beat = 1920.0;
 
+double Tempo::frames_per_beat (nframes_t sr, const Meter& meter) const
+{
+       return  ((60.0 * sr) / (_beats_per_minute * meter.note_divisor()/_note_type));
+}
+
 /***********************************************************************/
 
 double
 Meter::frames_per_bar (const Tempo& tempo, nframes_t sr) const
 {
-       return ((60.0 * sr * _beats_per_bar) / tempo.beats_per_minute());
+       return ((60.0 * sr * _beats_per_bar) / (tempo.beats_per_minute() * _note_type/tempo.note_type()));
 }
 
 /***********************************************************************/
@@ -86,6 +91,16 @@ TempoSection::TempoSection (const XMLNode& node)
                error << _("TempoSection XML node has an illegal \"beats_per_minute\" value") << endmsg;
                throw failed_constructor();
        }
+       
+       if ((prop = node.property ("note-type")) == 0) {
+               /* older session, make note type be quarter by default */
+               _note_type = 4.0;
+       } else {
+               if (sscanf (prop->value().c_str(), "%lf", &_note_type) != 1 || _note_type < 1.0) {
+                       error << _("TempoSection XML node has an illegal \"note-type\" value") << endmsg;
+                       throw failed_constructor();
+               }
+       }
 
        if ((prop = node.property ("movable")) == 0) {
                error << _("TempoSection XML node has no \"movable\" property") << endmsg;
@@ -109,6 +124,8 @@ TempoSection::get_state() const
        root->add_property ("start", buf);
        snprintf (buf, sizeof (buf), "%f", _beats_per_minute);
        root->add_property ("beats-per-minute", buf);
+       snprintf (buf, sizeof (buf), "%f", _note_type);
+       root->add_property ("note-type", buf);
        snprintf (buf, sizeof (buf), "%s", movable()?"yes":"no");
        root->add_property ("movable", buf);
 
@@ -210,7 +227,7 @@ TempoMap::TempoMap (nframes_t fr)
        start.beats = 1;
        start.ticks = 0;
 
-       TempoSection *t = new TempoSection (start, _default_tempo.beats_per_minute());
+       TempoSection *t = new TempoSection (start, _default_tempo.beats_per_minute(), _default_tempo.note_type());
        MeterSection *m = new MeterSection (start, _default_meter.beats_per_bar(), _default_meter.note_divisor());
 
        t->set_movable (false);
@@ -359,7 +376,7 @@ TempoMap::add_tempo (const Tempo& tempo, BBT_Time where)
        
                where.ticks = 0;
                
-               do_insert (new TempoSection (where, tempo.beats_per_minute()));
+               do_insert (new TempoSection (where, tempo.beats_per_minute(), tempo.note_type()));
        }
 
        StateChanged (Change (0));
@@ -614,7 +631,7 @@ TempoMap::bbt_time_with_metric (nframes_t frame, BBT_Time& bbt, const Metric& me
 
        const double beats_per_bar = metric.meter().beats_per_bar();
        const double frames_per_bar = metric.meter().frames_per_bar (metric.tempo(), _frame_rate);
-       const double beat_frames = metric.tempo().frames_per_beat (_frame_rate);
+       const double beat_frames = metric.tempo().frames_per_beat (_frame_rate, metric.meter());
 
        /* now compute how far beyond that point we actually are. */
 
@@ -667,7 +684,7 @@ TempoMap::count_frames_between ( const BBT_Time& start, const BBT_Time& end) con
                + start.ticks/Meter::ticks_per_beat;
 
 
-       start_frame = m.frame() + (nframes_t) rint( beat_offset * m.tempo().frames_per_beat(_frame_rate));
+       start_frame = m.frame() + (nframes_t) rint( beat_offset * m.tempo().frames_per_beat(_frame_rate, m.meter()));
 
        m =  metric_at(end);
 
@@ -676,7 +693,7 @@ TempoMap::count_frames_between ( const BBT_Time& start, const BBT_Time& end) con
        beat_offset = bar_offset * m.meter().beats_per_bar() - (m.start().beats -1) + (end.beats - 1) 
                + end.ticks/Meter::ticks_per_beat;
 
-       end_frame = m.frame() + (nframes_t) rint(beat_offset * m.tempo().frames_per_beat(_frame_rate));
+       end_frame = m.frame() + (nframes_t) rint(beat_offset * m.tempo().frames_per_beat(_frame_rate, m.meter()));
 
        frames = end_frame - start_frame;
 
@@ -697,7 +714,7 @@ TempoMap::count_frames_between_metrics (const Meter& meter, const Tempo& tempo,
        double beat_frames = 0;
 
        beats_per_bar = meter.beats_per_bar();
-       beat_frames = tempo.frames_per_beat (_frame_rate);
+       beat_frames = tempo.frames_per_beat (_frame_rate,meter);
 
        frames = 0;
 
@@ -1088,7 +1105,7 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
 
        beats_per_bar = meter->beats_per_bar ();
        frames_per_bar = meter->frames_per_bar (*tempo, _frame_rate);
-       beat_frames = tempo->frames_per_beat (_frame_rate);
+       beat_frames = tempo->frames_per_beat (_frame_rate, *meter);
        
        if (meter->frame() > tempo->frame()) {
                bar = meter->start().bars;
@@ -1198,7 +1215,7 @@ TempoMap::get_points (nframes_t lower, nframes_t upper) const
 
                        beats_per_bar = meter->beats_per_bar ();
                        frames_per_bar = meter->frames_per_bar (*tempo, _frame_rate);
-                       beat_frames = tempo->frames_per_beat (_frame_rate);
+                       beat_frames = tempo->frames_per_beat (_frame_rate, *meter);
                        
                        ++i;
                }
@@ -1304,7 +1321,7 @@ TempoMap::dump (std::ostream& o) const
        for (Metrics::const_iterator i = metrics->begin(); i != metrics->end(); ++i) {
 
                if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
-                       o << "Tempo @ " << *i << ' ' << t->beats_per_minute() << " BPM at " << t->start() << " frame= " << t->frame() << " (move? "
+                       o << "Tempo @ " << *i << ' ' << t->beats_per_minute() << " BPM (denom = " << t->note_type() << ") at " << t->start() << " frame= " << t->frame() << " (move? "
                          << t->movable() << ')' << endl;
                } else if ((m = dynamic_cast<const MeterSection*>(*i)) != 0) {
                        o << "Meter @ " << *i << ' ' << m->beats_per_bar() << '/' << m->note_divisor() << " at " << m->start() << " frame= " << m->frame() 
index ac0e6849f93f4827670003d8ae9590d834b896fe..5969d91982f0e94215fd37974cef59e23ae6714d 100644 (file)
@@ -142,7 +142,7 @@ VSTPlugin::get_state()
 {
        XMLNode *root = new XMLNode (state_node_name());
        LocaleGuard lg (X_("POSIX"));
-       
+
        if (_plugin->flags & effFlagsProgramChunks) {
 
                /* fetch the current chunk */
@@ -418,10 +418,12 @@ VSTPlugin::activate ()
        _plugin->dispatcher (_plugin, effMainsChanged, 0, 1, NULL, 0.0f);
 }
 
-uint32_t 
+string
 VSTPlugin::unique_id() const
 {
-       return _plugin->uniqueID;
+       char buf[32];
+       snprintf (buf, sizeof (buf), "%d", _plugin->uniqueID);
+       return string (buf);
 }